mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	Fixes a regression on spi flash devices (upstream commit 1583eaece6fa). Changelogs: * https://www.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.1.7 * https://www.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.1.8 * https://www.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.1.9 * https://www.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.1.10 096-ipv4-off-by-one-in-continuation-handling-in-proc-net.patch was applied upstream and dropped. Signed-off-by: Mathias Kresin <openwrt@kresin.me> [update from 4.1.9 to 4.1.10] Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> SVN-Revision: 47104
		
			
				
	
	
		
			193 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/arch/mips/lantiq/xway/Makefile
 | |
| +++ b/arch/mips/lantiq/xway/Makefile
 | |
| @@ -1,6 +1,6 @@
 | |
|  obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
 | |
|  
 | |
| -obj-y += vmmc.o tffs.o
 | |
| +obj-y += vmmc.o tffs.o mtd_split.o
 | |
|  
 | |
|  obj-y += eth_mac.o
 | |
|  obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
 | |
| --- /dev/null
 | |
| +++ b/arch/mips/lantiq/xway/mtd_split.c
 | |
| @@ -0,0 +1,129 @@
 | |
| +#include <linux/magic.h>
 | |
| +#include <linux/root_dev.h>
 | |
| +#include <linux/mtd/mtd.h>
 | |
| +#include <linux/mtd/partitions.h>
 | |
| +
 | |
| +#define ROOTFS_SPLIT_NAME "rootfs_data"
 | |
| +
 | |
| +struct squashfs_super_block {
 | |
| +	__le32 s_magic;
 | |
| +	__le32 pad0[9];
 | |
| +	__le64 bytes_used;
 | |
| +};
 | |
| +
 | |
| +static void split_brnimage_kernel(struct mtd_info *master, const char *name,
 | |
| +                                       int offset, int size)
 | |
| +{
 | |
| +	unsigned long buf[4];
 | |
| +	// Assume at most 2MB of kernel image
 | |
| +	unsigned long end = offset + (2 << 20);
 | |
| +	unsigned long part_size = offset + 0x400 - 12;
 | |
| +	size_t len;
 | |
| +	int ret;
 | |
| +
 | |
| +	if (strcmp(name, "firmware") != 0)
 | |
| +		return;
 | |
| +	while (part_size < end) {
 | |
| +		long size_min = part_size - 0x400 - 12 - offset;
 | |
| +		long size_max = part_size + 12 - offset;
 | |
| +		ret = mtd_read(master, part_size, 16, &len, (void *)buf);
 | |
| +		if (ret || len != 16)
 | |
| +			return;
 | |
| +
 | |
| +		if (le32_to_cpu(buf[0]) < size_min ||
 | |
| +				le32_to_cpu(buf[0]) > size_max) {
 | |
| +			part_size += 0x400;
 | |
| +			continue;
 | |
| +		}
 | |
| +
 | |
| +		if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) {
 | |
| +			part_size += 12 - offset;
 | |
| +			__mtd_add_partition(master, "rootfs", offset + part_size,
 | |
| +			                            size - part_size, false);
 | |
| +			return;
 | |
| +		}
 | |
| +		part_size += 0x400;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +static void split_eva_kernel(struct mtd_info *master, const char *name,
 | |
| +				int offset, int size)
 | |
| +{
 | |
| +#define EVA_MAGIC   0xfeed1281
 | |
| +	unsigned long magic = 0;
 | |
| +	unsigned long part_size = 0, p;
 | |
| +	size_t len;
 | |
| +	int ret;
 | |
| +
 | |
| +	if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
 | |
| +		return;
 | |
| +
 | |
| +	ret = mtd_read(master, offset, 4, &len, (void *)&magic);
 | |
| +	if (ret || len != sizeof(magic))
 | |
| +		return;
 | |
| +
 | |
| +	if (le32_to_cpu(magic) != EVA_MAGIC)
 | |
| +		return;
 | |
| +
 | |
| +	ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size);
 | |
| +	if (ret || len != sizeof(part_size))
 | |
| +		return;
 | |
| +
 | |
| +	p = part_size = le32_to_cpu(part_size) + 0x18;
 | |
| +	p &= ~0xffff;
 | |
| +	p += 0x10000;
 | |
| +
 | |
| +	ret = mtd_read(master, offset + p, 4, &len, (void *)&magic);
 | |
| +	if (ret || len != sizeof(magic))
 | |
| +		return;
 | |
| +
 | |
| +	if (magic == SQUASHFS_MAGIC)
 | |
| +		part_size = p + 0x100;
 | |
| +	else
 | |
| +	        part_size = mtd_pad_erasesize(master, offset, len);
 | |
| +
 | |
| +	if (part_size + master->erasesize > size)
 | |
| +		return;
 | |
| +
 | |
| +	__mtd_add_partition(master, "rootfs", offset + part_size,
 | |
| +			    size - part_size, false);
 | |
| +}
 | |
| +
 | |
| +static void split_tplink_kernel(struct mtd_info *master, const char *name,
 | |
| +				int offset, int size)
 | |
| +{
 | |
| +#define TPLINK_MAGIC   0x00000002
 | |
| +	unsigned long magic = 0;
 | |
| +	unsigned long part_size = 0;
 | |
| +	size_t len;
 | |
| +	int ret;
 | |
| +
 | |
| +	if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
 | |
| +		return;
 | |
| +
 | |
| +	ret = mtd_read(master, offset, 4, &len, (void *)&magic);
 | |
| +	if (ret || len != sizeof(magic))
 | |
| +		return;
 | |
| +
 | |
| +	if (le32_to_cpu(magic) != TPLINK_MAGIC)
 | |
| +		return;
 | |
| +
 | |
| +	ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size);
 | |
| +	if (ret || len != sizeof(part_size))
 | |
| +		return;
 | |
| +
 | |
| +	part_size = be32_to_cpu(part_size) + 0x200;
 | |
| +	if (part_size + master->erasesize > size)
 | |
| +		return;
 | |
| +
 | |
| +	__mtd_add_partition(master, "rootfs", offset + part_size,
 | |
| +			    size - part_size, false);
 | |
| +}
 | |
| +
 | |
| +void arch_split_mtd_part(struct mtd_info *master, const char *name,
 | |
| +				int offset, int size)
 | |
| +{
 | |
| +	split_tplink_kernel(master, name, offset, size);
 | |
| +	split_eva_kernel(master, name, offset, size);
 | |
| +	split_brnimage_kernel(master, name, offset, size);
 | |
| +}
 | |
| --- a/include/linux/mtd/partitions.h
 | |
| +++ b/include/linux/mtd/partitions.h
 | |
| @@ -89,12 +89,17 @@ extern void deregister_mtd_parser(struct
 | |
|  int mtd_is_partition(const struct mtd_info *mtd);
 | |
|  int mtd_add_partition(struct mtd_info *master, const char *name,
 | |
|  		      long long offset, long long length);
 | |
| +int __mtd_add_partition(struct mtd_info *master, const char *name,
 | |
| +		    long long offset, long long length, bool dup_check);
 | |
| +
 | |
|  int mtd_del_partition(struct mtd_info *master, int partno);
 | |
|  struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
 | |
|  uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
 | |
|  uint64_t mtd_get_device_size(const struct mtd_info *mtd);
 | |
| -extern void __weak arch_split_mtd_part(struct mtd_info *master,
 | |
| -				       const char *name, int offset, int size);
 | |
| +void __weak arch_split_mtd_part(struct mtd_info *master,
 | |
| + 				       const char *name, int offset, int size);
 | |
| +unsigned long
 | |
| +mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len);
 | |
|  
 | |
|  int parse_mtd_partitions_by_type(struct mtd_info *master,
 | |
|  				 enum mtd_parser_type type,
 | |
| --- a/drivers/mtd/mtdpart.c
 | |
| +++ b/drivers/mtd/mtdpart.c
 | |
| @@ -659,7 +659,7 @@ static int mtd_add_partition_attrs(struc
 | |
|  }
 | |
|  
 | |
|  
 | |
| -static int
 | |
| +int
 | |
|  __mtd_add_partition(struct mtd_info *master, const char *name,
 | |
|  		    long long offset, long long length, bool dup_check)
 | |
|  {
 | |
| @@ -763,7 +763,7 @@ run_parsers_by_type(struct mtd_part *sla
 | |
|  	return nr_parts;
 | |
|  }
 | |
|  
 | |
| -static inline unsigned long
 | |
| +unsigned long
 | |
|  mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
 | |
|  {
 | |
|  	unsigned long mask = mtd->erasesize - 1;
 | |
| @@ -792,7 +792,6 @@ static void split_uimage(struct mtd_info
 | |
|  		return;
 | |
|  
 | |
|  	len = be32_to_cpu(hdr.size) + 0x40;
 | |
| -	len = mtd_pad_erasesize(master, part->offset, len);
 | |
|  	if (len + master->erasesize > part->mtd.size)
 | |
|  		return;
 | |
|  
 |