1 --- a/drivers/mtd/Kconfig
2 +++ b/drivers/mtd/Kconfig
3 @@ -31,6 +31,10 @@ config MTD_ROOTFS_SPLIT
4 bool "Automatically split 'rootfs' partition for squashfs"
7 +config MTD_UIMAGE_SPLIT
8 + bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
11 config MTD_REDBOOT_PARTS
12 tristate "RedBoot partition table parsing"
14 --- a/drivers/mtd/mtdpart.c
15 +++ b/drivers/mtd/mtdpart.c
16 @@ -874,6 +874,169 @@ static int refresh_rootfs_split(struct m
18 #endif /* CONFIG_MTD_ROOTFS_SPLIT */
21 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
22 +static unsigned long find_uimage_size(struct mtd_info *mtd,
23 + unsigned long offset)
25 +#define UBOOT_MAGIC 0x56190527
26 + unsigned long magic = 0;
31 + ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
32 + if (ret || len != sizeof(magic))
35 + if (le32_to_cpu(magic) != UBOOT_MAGIC)
38 + ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
39 + if (ret || len != sizeof(temp))
45 +static unsigned long find_eva_size(struct mtd_info *mtd,
46 + unsigned long offset)
48 +#define EVA_MAGIC 0xfeed1281
49 + unsigned long magic = 0;
54 + ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
55 + if (ret || len != sizeof(magic))
58 + if (le32_to_cpu(magic) != EVA_MAGIC)
61 + ret = mtd->read(mtd, offset + 4, 4, &len, (void *)&temp);
62 + if (ret || len != sizeof(temp))
65 + /* add eva header size */
66 + temp = le32_to_cpu(temp) + 0x18;
73 +static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
79 + ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
80 + if (ret || len != sizeof(temp))
84 + return le32_to_cpu(temp) == SQUASHFS_MAGIC;
87 +static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
93 + ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
94 + if (ret || len != sizeof(temp))
97 + return be32_to_cpu(temp) == SQUASHFS_MAGIC;
100 +static unsigned long find_brnimage_size(struct mtd_info *mtd,
101 + unsigned long offset)
103 + unsigned long buf[4];
104 + // Assume at most 2MB of kernel image
105 + unsigned long end = offset + (2 << 20);
106 + unsigned long ptr = offset + 0x400 - 12;
110 + while (ptr < end) {
111 + long size_min = ptr - 0x400 - 12 - offset;
112 + long size_max = ptr + 12 - offset;
113 + ret = mtd->read(mtd, ptr, 16, &len, (void *)buf);
114 + if (ret || len != 16)
117 + if (le32_to_cpu(buf[0]) < size_min ||
118 + le32_to_cpu(buf[0]) > size_max) {
123 + if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
124 + return ptr + 12 - offset;
132 +static int split_uimage(struct mtd_info *mtd,
133 + const struct mtd_partition *part)
135 + static struct mtd_partition split_partitions[] = {
147 + split_partitions[0].size = find_uimage_size(mtd, part->offset);
148 + if (!split_partitions[0].size) {
149 + split_partitions[0].size = find_eva_size(mtd, part->offset);
150 + if (!split_partitions[0].size) {
151 + split_partitions[0].size = find_brnimage_size(mtd, part->offset);
152 + if (!split_partitions[0].size) {
153 + printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n");
159 + if (detect_eva_squashfs_partition(mtd,
161 + + split_partitions[0].size)) {
162 + split_partitions[0].size += 0x100;
163 + pr_info("found eva dummy squashfs behind kernel\n");
164 + } else if (!detect_squashfs_partition(mtd,
166 + + split_partitions[0].size)) {
167 + split_partitions[0].size &= ~(mtd->erasesize - 1);
168 + split_partitions[0].size += mtd->erasesize;
170 + pr_info("found squashfs behind kernel\n");
173 + split_partitions[0].offset = part->offset;
174 + split_partitions[1].offset = part->offset + split_partitions[0].size;
175 + split_partitions[1].size = part->size - split_partitions[0].size;
177 + add_mtd_partitions(mtd, split_partitions, 2);
184 * This function, given a master MTD object and a partition table, creates
185 * and registers slave MTD objects which are bound to the master according to
186 @@ -907,6 +1070,17 @@ int add_mtd_partitions(struct mtd_info *
188 add_mtd_device(&slave->mtd);
190 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
191 + if (!strcmp(parts[i].name, "linux")) {
192 + ret = split_uimage(master, &parts[i]);
195 + printk(KERN_WARNING
196 + "Can't split linux partition\n");
201 if (!strcmp(parts[i].name, "rootfs")) {
202 #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
204 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
205 +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
206 @@ -166,6 +166,7 @@ extern unsigned char ltq_boot_select(voi
208 extern __iomem void *ltq_ebu_membase;
209 extern __iomem void *ltq_cgu_membase;
210 +extern unsigned long ltq_brn_boot;
212 static inline int ltq_is_ase(void)
214 --- a/arch/mips/lantiq/setup.c
215 +++ b/arch/mips/lantiq/setup.c
220 +/* set to 1 if the bootloader is BRN-BOOT instead of u-boot */
221 +unsigned long ltq_brn_boot = 0;
223 void __init plat_mem_setup(void)
225 /* assume 16M as default incase uboot fails to pass proper ramsize */
226 @@ -38,6 +41,10 @@ void __init plat_mem_setup(void)
227 if (strict_strtoul(e, 0, &memsize))
228 pr_warn("bad memsize specified\n");
230 + if (!strncmp(e, "BRN-BOOT", 8)){
231 + pr_info("Found BRN-BOOT instead of u-boot\n");
236 memsize *= 1024 * 1024;