1 From 2a295753a10823a47542c779a25bbb1f52c71281 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Fri, 3 Aug 2012 10:27:13 +0200
4 Subject: [PATCH 19/25] owrt mtd split
7 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 1 +
8 arch/mips/lantiq/setup.c | 7 +
9 drivers/mtd/Kconfig | 4 +
10 drivers/mtd/mtdpart.c | 173 +++++++++++++++++++-
11 4 files changed, 184 insertions(+), 1 deletions(-)
13 diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
14 index 1ec8f2a..1ff93cc 100644
15 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
16 +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
17 @@ -166,6 +166,7 @@ extern unsigned char ltq_boot_select(void);
19 extern __iomem void *ltq_ebu_membase;
20 extern __iomem void *ltq_cgu_membase;
21 +extern unsigned long ltq_brn_boot;
23 static inline int ltq_is_ase(void)
25 diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
26 index 1ff6c9d..708e969 100644
27 --- a/arch/mips/lantiq/setup.c
28 +++ b/arch/mips/lantiq/setup.c
33 +/* set to 1 if the bootloader is BRN-BOOT instead of u-boot */
34 +unsigned long ltq_brn_boot = 0;
36 void __init plat_mem_setup(void)
38 /* assume 16M as default incase uboot fails to pass proper ramsize */
39 @@ -38,6 +41,10 @@ void __init plat_mem_setup(void)
40 if (strict_strtoul(e, 0, &memsize))
41 pr_warn("bad memsize specified\n");
43 + if (!strncmp(e, "BRN-BOOT", 8)){
44 + pr_info("Found BRN-BOOT instead of u-boot\n");
49 memsize *= 1024 * 1024;
50 diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
51 index 982a98b..e2f3f3e 100644
52 --- a/drivers/mtd/Kconfig
53 +++ b/drivers/mtd/Kconfig
54 @@ -31,6 +31,10 @@ config MTD_ROOTFS_SPLIT
55 bool "Automatically split 'rootfs' partition for squashfs"
58 +config MTD_UIMAGE_SPLIT
59 + bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
62 config MTD_REDBOOT_PARTS
63 tristate "RedBoot partition table parsing"
65 diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
66 index 855b70b..93711e2 100644
67 --- a/drivers/mtd/mtdpart.c
68 +++ b/drivers/mtd/mtdpart.c
69 @@ -867,6 +867,168 @@ static int refresh_rootfs_split(struct mtd_info *mtd)
71 #endif /* CONFIG_MTD_ROOTFS_SPLIT */
73 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
74 +static unsigned long find_uimage_size(struct mtd_info *mtd,
75 + unsigned long offset)
77 +#define UBOOT_MAGIC 0x56190527
78 + unsigned long magic = 0;
83 + ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
84 + if (ret || len != sizeof(magic))
87 + if (le32_to_cpu(magic) != UBOOT_MAGIC)
90 + ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
91 + if (ret || len != sizeof(temp))
97 +static unsigned long find_eva_size(struct mtd_info *mtd,
98 + unsigned long offset)
100 +#define EVA_MAGIC 0xfeed1281
101 + unsigned long magic = 0;
102 + unsigned long temp;
106 + ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
107 + if (ret || len != sizeof(magic))
110 + if (le32_to_cpu(magic) != EVA_MAGIC)
113 + ret = mtd->read(mtd, offset + 4, 4, &len, (void *)&temp);
114 + if (ret || len != sizeof(temp))
117 + /* add eva header size */
118 + temp = le32_to_cpu(temp) + 0x18;
125 +static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
127 + unsigned long temp;
131 + ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
132 + if (ret || len != sizeof(temp))
136 + return le32_to_cpu(temp) == SQUASHFS_MAGIC;
139 +static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
141 + unsigned long temp;
145 + ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
146 + if (ret || len != sizeof(temp))
149 + return be32_to_cpu(temp) == SQUASHFS_MAGIC;
152 +static unsigned long find_brnimage_size(struct mtd_info *mtd,
153 + unsigned long offset)
155 + unsigned long buf[4];
156 + // Assume at most 2MB of kernel image
157 + unsigned long end = offset + (2 << 20);
158 + unsigned long ptr = offset + 0x400 - 12;
162 + while (ptr < end) {
163 + long size_min = ptr - 0x400 - 12 - offset;
164 + long size_max = ptr + 12 - offset;
165 + ret = mtd->read(mtd, ptr, 16, &len, (void *)buf);
166 + if (ret || len != 16)
169 + if (le32_to_cpu(buf[0]) < size_min ||
170 + le32_to_cpu(buf[0]) > size_max) {
175 + if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
176 + return ptr + 12 - offset;
184 +static int split_uimage(struct mtd_info *mtd,
185 + const struct mtd_partition *part)
187 + static struct mtd_partition split_partitions[] = {
199 + split_partitions[0].size = find_uimage_size(mtd, part->offset);
200 + if (!split_partitions[0].size) {
201 + split_partitions[0].size = find_eva_size(mtd, part->offset);
202 + if (!split_partitions[0].size) {
203 + split_partitions[0].size = find_brnimage_size(mtd, part->offset);
204 + if (!split_partitions[0].size) {
205 + printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n");
211 + if (detect_eva_squashfs_partition(mtd,
213 + + split_partitions[0].size)) {
214 + split_partitions[0].size += 0x100;
215 + pr_info("found eva dummy squashfs behind kernel\n");
216 + } else if (!detect_squashfs_partition(mtd,
218 + + split_partitions[0].size)) {
219 + split_partitions[0].size &= ~(mtd->erasesize - 1);
220 + split_partitions[0].size += mtd->erasesize;
222 + pr_info("found squashfs behind kernel\n");
225 + split_partitions[0].offset = part->offset;
226 + split_partitions[1].offset = part->offset + split_partitions[0].size;
227 + split_partitions[1].size = part->size - split_partitions[0].size;
229 + add_mtd_partitions(mtd, split_partitions, 2);
236 * This function, given a master MTD object and a partition table, creates
237 * and registers slave MTD objects which are bound to the master according to
238 @@ -883,7 +1045,7 @@ int add_mtd_partitions(struct mtd_info *master,
239 struct mtd_part *slave;
240 uint64_t cur_offset = 0;
242 -#ifdef CONFIG_MTD_ROOTFS_SPLIT
243 +#if defined(CONFIG_MTD_ROOTFS_SPLIT) || defined(CONFIG_MTD_UIMAGE_SPLIT)
247 @@ -900,6 +1062,15 @@ int add_mtd_partitions(struct mtd_info *master,
249 add_mtd_device(&slave->mtd);
251 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
252 + if (!strcmp(parts[i].name, "linux")) {
253 + ret = split_uimage(master, &parts[i]);
256 + printk(KERN_WARNING "Can't split linux partition\n");
260 if (!strcmp(parts[i].name, "rootfs")) {
261 #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV