diff options
Diffstat (limited to 'target/linux/lantiq/patches-3.8/0041-owrt-mtd-split.patch')
-rw-r--r-- | target/linux/lantiq/patches-3.8/0041-owrt-mtd-split.patch | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/target/linux/lantiq/patches-3.8/0041-owrt-mtd-split.patch b/target/linux/lantiq/patches-3.8/0041-owrt-mtd-split.patch new file mode 100644 index 0000000..ee5fa73 --- /dev/null +++ b/target/linux/lantiq/patches-3.8/0041-owrt-mtd-split.patch @@ -0,0 +1,221 @@ +From 2a295753a10823a47542c779a25bbb1f52c71281 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Fri, 3 Aug 2012 10:27:13 +0200 +Subject: [PATCH 19/25] owrt mtd split + +--- + .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 1 + + arch/mips/lantiq/setup.c | 7 + + drivers/mtd/Kconfig | 4 + + drivers/mtd/mtdpart.c | 173 +++++++++++++++++++- + 4 files changed, 184 insertions(+), 1 deletions(-) + +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -31,6 +31,10 @@ config MTD_ROOTFS_SPLIT + bool "Automatically split 'rootfs' partition for squashfs" + default y + ++config MTD_UIMAGE_SPLIT ++ bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'" ++ default y ++ + config MTD_REDBOOT_PARTS + tristate "RedBoot partition table parsing" + ---help--- +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -844,6 +844,168 @@ static int refresh_rootfs_split(struct m + } + #endif /* CONFIG_MTD_ROOTFS_SPLIT */ + ++#ifdef CONFIG_MTD_UIMAGE_SPLIT ++static unsigned long find_uimage_size(struct mtd_info *mtd, ++ unsigned long offset) ++{ ++#define UBOOT_MAGIC 0x56190527 ++ unsigned long magic = 0; ++ unsigned long temp; ++ size_t len; ++ int ret; ++ ++ ret = mtd_read(mtd, offset, 4, &len, (void *)&magic); ++ if (ret || len != sizeof(magic)) ++ return 0; ++ ++ if (le32_to_cpu(magic) != UBOOT_MAGIC) ++ return 0; ++ ++ ret = mtd_read(mtd, offset + 12, 4, &len, (void *)&temp); ++ if (ret || len != sizeof(temp)) ++ return 0; ++ ++ return temp + 0x40; ++} ++ ++static unsigned long find_eva_size(struct mtd_info *mtd, ++ unsigned long offset) ++{ ++#define EVA_MAGIC 0xfeed1281 ++ unsigned long magic = 0; ++ unsigned long temp; ++ size_t len; ++ int ret; ++ ++ ret = mtd_read(mtd, offset, 4, &len, (void *)&magic); ++ if (ret || len != sizeof(magic)) ++ return 0; ++ ++ if (le32_to_cpu(magic) != EVA_MAGIC) ++ return 0; ++ ++ ret = mtd_read(mtd, offset + 4, 4, &len, (void *)&temp); ++ if (ret || len != sizeof(temp)) ++ return 0; ++ ++ /* add eva header size */ ++ temp = le32_to_cpu(temp) + 0x18; ++ ++ temp &= ~0xffff; ++ temp += 0x10000; ++ return temp; ++} ++ ++static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset) ++{ ++ unsigned long temp; ++ size_t len; ++ int ret; ++ ++ ret = mtd_read(mtd, offset, 4, &len, (void *)&temp); ++ if (ret || len != sizeof(temp)) ++ return 0; ++ ++ ++ return le32_to_cpu(temp) == SQUASHFS_MAGIC; ++} ++ ++static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset) ++{ ++ unsigned long temp; ++ size_t len; ++ int ret; ++ ++ ret = mtd_read(mtd, offset, 4, &len, (void *)&temp); ++ if (ret || len != sizeof(temp)) ++ return 0; ++ ++ return be32_to_cpu(temp) == SQUASHFS_MAGIC; ++} ++ ++static unsigned long find_brnimage_size(struct mtd_info *mtd, ++ unsigned long offset) ++{ ++ unsigned long buf[4]; ++ // Assume at most 2MB of kernel image ++ unsigned long end = offset + (2 << 20); ++ unsigned long ptr = offset + 0x400 - 12; ++ size_t len; ++ int ret; ++ ++ while (ptr < end) { ++ long size_min = ptr - 0x400 - 12 - offset; ++ long size_max = ptr + 12 - offset; ++ ret = mtd_read(mtd, ptr, 16, &len, (void *)buf); ++ if (ret || len != 16) ++ return 0; ++ ++ if (le32_to_cpu(buf[0]) < size_min || ++ le32_to_cpu(buf[0]) > size_max) { ++ ptr += 0x400; ++ continue; ++ } ++ ++ if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) ++ return ptr + 12 - offset; ++ ++ ptr += 0x400; ++ } ++ ++ return 0; ++} ++ ++static int split_uimage(struct mtd_info *mtd, ++ const struct mtd_partition *part) ++{ ++ static struct mtd_partition split_partitions[] = { ++ { ++ .name = "kernel", ++ .offset = 0x0, ++ .size = 0x0, ++ }, { ++ .name = "rootfs", ++ .offset = 0x0, ++ .size = 0x0, ++ }, ++ }; ++ ++ split_partitions[0].size = find_uimage_size(mtd, part->offset); ++ if (!split_partitions[0].size) { ++ split_partitions[0].size = find_eva_size(mtd, part->offset); ++ if (!split_partitions[0].size) { ++ split_partitions[0].size = find_brnimage_size(mtd, part->offset); ++ if (!split_partitions[0].size) { ++ printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n"); ++ return -1; ++ } ++ } ++ } ++ ++ if (detect_eva_squashfs_partition(mtd, ++ part->offset ++ + split_partitions[0].size)) { ++ split_partitions[0].size += 0x100; ++ pr_info("found eva dummy squashfs behind kernel\n"); ++ } else if (!detect_squashfs_partition(mtd, ++ part->offset ++ + split_partitions[0].size)) { ++ split_partitions[0].size &= ~(mtd->erasesize - 1); ++ split_partitions[0].size += mtd->erasesize; ++ } else { ++ pr_info("found squashfs behind kernel\n"); ++ } ++ ++ split_partitions[0].offset = part->offset; ++ split_partitions[1].offset = part->offset + split_partitions[0].size; ++ split_partitions[1].size = part->size - split_partitions[0].size; ++ ++ add_mtd_partitions(mtd, split_partitions, 2); ++ ++ return 0; ++} ++#endif ++ + /* + * This function, given a master MTD object and a partition table, creates + * and registers slave MTD objects which are bound to the master according to +@@ -860,7 +1022,7 @@ int add_mtd_partitions(struct mtd_info * + struct mtd_part *slave; + uint64_t cur_offset = 0; + int i; +-#ifdef CONFIG_MTD_ROOTFS_SPLIT ++#if defined(CONFIG_MTD_ROOTFS_SPLIT) || defined(CONFIG_MTD_UIMAGE_SPLIT) + int ret; + #endif + +@@ -877,6 +1039,15 @@ int add_mtd_partitions(struct mtd_info * + + add_mtd_device(&slave->mtd); + ++#ifdef CONFIG_MTD_UIMAGE_SPLIT ++ if (!strcmp(parts[i].name, "linux")) { ++ ret = split_uimage(master, &parts[i]); ++ ++ if (ret) ++ printk(KERN_WARNING "Can't split linux partition\n"); ++ } ++#endif ++ + if (!strcmp(parts[i].name, "rootfs")) { + #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV + if (ROOT_DEV == 0) { |