1 --- a/arch/mips/lantiq/xway/Makefile
2 +++ b/arch/mips/lantiq/xway/Makefile
4 obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o
7 +obj-y += vmmc.o mtd_split.o
10 obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
12 +++ b/arch/mips/lantiq/xway/mtd_split.c
14 +#include <linux/magic.h>
15 +#include <linux/root_dev.h>
16 +#include <linux/mtd/mtd.h>
17 +#include <linux/mtd/partitions.h>
19 +#define ROOTFS_SPLIT_NAME "rootfs_data"
21 +struct squashfs_super_block {
27 +static void split_brnimage_kernel(struct mtd_info *master, const char *name,
28 + int offset, int size)
30 + unsigned long buf[4];
31 + // Assume at most 2MB of kernel image
32 + unsigned long end = offset + (2 << 20);
33 + unsigned long part_size = offset + 0x400 - 12;
37 + if (strcmp(name, "firmware") != 0)
39 + while (part_size < end) {
40 + long size_min = part_size - 0x400 - 12 - offset;
41 + long size_max = part_size + 12 - offset;
42 + ret = mtd_read(master, part_size, 16, &len, (void *)buf);
43 + if (ret || len != 16)
46 + if (le32_to_cpu(buf[0]) < size_min ||
47 + le32_to_cpu(buf[0]) > size_max) {
52 + if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) {
53 + part_size += 12 - offset;
54 + __mtd_add_partition(master, "rootfs", offset + part_size,
55 + size - part_size, false);
62 +static void split_eva_kernel(struct mtd_info *master, const char *name,
63 + int offset, int size)
65 +#define EVA_MAGIC 0xfeed1281
66 + unsigned long magic = 0;
67 + unsigned long part_size = 0, p;
71 + if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
74 + ret = mtd_read(master, offset, 4, &len, (void *)&magic);
75 + if (ret || len != sizeof(magic))
78 + if (le32_to_cpu(magic) != EVA_MAGIC)
81 + ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size);
82 + if (ret || len != sizeof(part_size))
85 + p = part_size = le32_to_cpu(part_size) + 0x18;
89 + ret = mtd_read(master, offset + p, 4, &len, (void *)&magic);
90 + if (ret || len != sizeof(magic))
93 + if (magic == SQUASHFS_MAGIC)
94 + part_size = p + 0x100;
96 + part_size = mtd_pad_erasesize(master, offset, len);
98 + if (part_size + master->erasesize > size)
101 + __mtd_add_partition(master, "rootfs", offset + part_size,
102 + size - part_size, false);
105 +static void split_tplink_kernel(struct mtd_info *master, const char *name,
106 + int offset, int size)
108 +#define TPLINK_MAGIC 0x00000002
109 + unsigned long magic = 0;
110 + unsigned long part_size = 0;
114 + if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
117 + ret = mtd_read(master, offset, 4, &len, (void *)&magic);
118 + if (ret || len != sizeof(magic))
121 + if (le32_to_cpu(magic) != TPLINK_MAGIC)
124 + ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size);
125 + if (ret || len != sizeof(part_size))
128 + part_size = be32_to_cpu(part_size) + 0x200;
129 + if (part_size + master->erasesize > size)
132 + __mtd_add_partition(master, "rootfs", offset + part_size,
133 + size - part_size, false);
136 +void arch_split_mtd_part(struct mtd_info *master, const char *name,
137 + int offset, int size)
139 + split_tplink_kernel(master, name, offset, size);
140 + split_eva_kernel(master, name, offset, size);
141 + split_brnimage_kernel(master, name, offset, size);
143 --- a/include/linux/mtd/partitions.h
144 +++ b/include/linux/mtd/partitions.h
145 @@ -89,12 +89,17 @@ extern int deregister_mtd_parser(struct
146 int mtd_is_partition(const struct mtd_info *mtd);
147 int mtd_add_partition(struct mtd_info *master, char *name,
148 long long offset, long long length);
149 +int __mtd_add_partition(struct mtd_info *master, char *name,
150 + long long offset, long long length, bool dup_check);
152 int mtd_del_partition(struct mtd_info *master, int partno);
153 struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
154 uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
155 uint64_t mtd_get_device_size(const struct mtd_info *mtd);
156 -extern void __weak arch_split_mtd_part(struct mtd_info *master,
157 - const char *name, int offset, int size);
158 +void __weak arch_split_mtd_part(struct mtd_info *master,
159 + const char *name, int offset, int size);
161 +mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len);
163 int parse_mtd_partitions_by_type(struct mtd_info *master,
164 enum mtd_parser_type type,
165 --- a/drivers/mtd/mtdpart.c
166 +++ b/drivers/mtd/mtdpart.c
167 @@ -615,7 +615,7 @@ out_register:
173 __mtd_add_partition(struct mtd_info *master, char *name,
174 long long offset, long long length, bool dup_check)
176 @@ -736,7 +736,7 @@ run_parsers_by_type(struct mtd_part *sla
180 -static inline unsigned long
182 mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
184 unsigned long mask = mtd->erasesize - 1;
185 @@ -805,7 +805,6 @@ static void split_uimage(struct mtd_info
188 len = be32_to_cpu(hdr.size) + 0x40;
189 - len = mtd_pad_erasesize(master, part->offset, len);
190 if (len + master->erasesize > part->mtd.size)