diff options
Diffstat (limited to 'target/linux/lantiq/patches-3.18/0101-mtd-split.patch')
-rw-r--r-- | target/linux/lantiq/patches-3.18/0101-mtd-split.patch | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/target/linux/lantiq/patches-3.18/0101-mtd-split.patch b/target/linux/lantiq/patches-3.18/0101-mtd-split.patch new file mode 100644 index 0000000000..69c632314c --- /dev/null +++ b/target/linux/lantiq/patches-3.18/0101-mtd-split.patch @@ -0,0 +1,192 @@ +--- 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 +@@ -630,7 +630,7 @@ out_register: + } + + +-static int ++int + __mtd_add_partition(struct mtd_info *master, const char *name, + long long offset, long long length, bool dup_check) + { +@@ -751,7 +751,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; +@@ -821,7 +821,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; + |