lantiq/3.10: unbreak the mtd-split patch
[openwrt/openwrt.git] / target / linux / lantiq / patches-3.10 / 0100-mtd-split.patch
1 --- a/arch/mips/lantiq/xway/Makefile
2 +++ b/arch/mips/lantiq/xway/Makefile
3 @@ -1,6 +1,6 @@
4 obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o
5
6 -obj-y += vmmc.o
7 +obj-y += vmmc.o mtd_split.o
8
9 obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
10
11 --- /dev/null
12 +++ b/arch/mips/lantiq/xway/mtd_split.c
13 @@ -0,0 +1,151 @@
14 +#include <linux/magic.h>
15 +#include <linux/root_dev.h>
16 +#include <linux/mtd/mtd.h>
17 +#include <linux/mtd/partitions.h>
18 +
19 +#define ROOTFS_SPLIT_NAME "rootfs_data"
20 +
21 +struct squashfs_super_block {
22 + __le32 s_magic;
23 + __le32 pad0[9];
24 + __le64 bytes_used;
25 +};
26 +
27 +static void split_brnimage_kernel(struct mtd_info *master, const char *name,
28 + int offset, int size)
29 +{
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;
34 + size_t len;
35 + int ret;
36 +
37 + if (strcmp(name, "rootfs") != 0)
38 + return;
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)
44 + return;
45 +
46 + if (le32_to_cpu(buf[0]) < size_min ||
47 + le32_to_cpu(buf[0]) > size_max) {
48 + part_size += 0x400;
49 + continue;
50 + }
51 +
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);
56 + return;
57 + }
58 + part_size += 0x400;
59 + }
60 +}
61 +
62 +static void split_eva_kernel(struct mtd_info *master, const char *name,
63 + int offset, int size)
64 +{
65 +#define EVA_MAGIC 0xfeed1281
66 + unsigned long magic = 0;
67 + unsigned long part_size = 0;
68 + size_t len;
69 + int ret;
70 +
71 + if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
72 + return;
73 +
74 + ret = mtd_read(master, offset, 4, &len, (void *)&magic);
75 + if (ret || len != sizeof(magic))
76 + return;
77 +
78 + if (le32_to_cpu(magic) != EVA_MAGIC)
79 + return;
80 +
81 + ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size);
82 + if (ret || len != sizeof(part_size))
83 + return;
84 +
85 + part_size = le32_to_cpu(part_size) + 0x18;
86 + part_size = mtd_pad_erasesize(master, offset, len);
87 + if (part_size + master->erasesize > size)
88 + return;
89 +
90 + __mtd_add_partition(master, "rootfs", offset + part_size,
91 + size - part_size, false);
92 +}
93 +
94 +static void split_tplink_kernel(struct mtd_info *master, const char *name,
95 + int offset, int size)
96 +{
97 +#define TPLINK_MAGIC 0x00000002
98 + unsigned long magic = 0;
99 + unsigned long part_size = 0;
100 + size_t len;
101 + int ret;
102 +
103 + if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
104 + return;
105 +
106 + ret = mtd_read(master, offset, 4, &len, (void *)&magic);
107 + if (ret || len != sizeof(magic))
108 + return;
109 +
110 + if (le32_to_cpu(magic) != TPLINK_MAGIC)
111 + return;
112 +
113 + ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size);
114 + if (ret || len != sizeof(part_size))
115 + return;
116 +
117 + part_size = be32_to_cpu(part_size) + 0x200;
118 + if (part_size + master->erasesize > size)
119 + return;
120 +
121 + __mtd_add_partition(master, "rootfs", offset + part_size,
122 + size - part_size, false);
123 +}
124 +
125 +static void split_squashfs(struct mtd_info *master, const char *name,
126 + int offset, int size)
127 +{
128 + struct squashfs_super_block sb;
129 + int len, ret;
130 +
131 + offset += 0x100;
132 + size -= 0x100;
133 +
134 + ret = mtd_read(master, offset, sizeof(sb), &len, (void *) &sb);
135 + if (ret || (len != sizeof(sb)))
136 + return;
137 +
138 + if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) )
139 + return;
140 +
141 + if (le64_to_cpu((sb.bytes_used)) <= 0)
142 + printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
143 + master->name);
144 + return;
145 +
146 + len = (u32) le64_to_cpu(sb.bytes_used);
147 + len = mtd_pad_erasesize(master, offset, len);
148 + offset += len;
149 + size -= len ;
150 + printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=0x%x, len=0x%x\n",
151 + ROOTFS_SPLIT_NAME, offset, size);
152 +
153 + __mtd_add_partition(master, ROOTFS_SPLIT_NAME, offset,
154 + size, false);
155 +}
156 +
157 +void arch_split_mtd_part(struct mtd_info *master, const char *name,
158 + int offset, int size)
159 +{
160 + split_tplink_kernel(master, name, offset, size);
161 + split_eva_kernel(master, name, offset, size);
162 + split_brnimage_kernel(master, name, offset, size);
163 + split_squashfs(master, name, offset, size);
164 +}
165 --- a/include/linux/mtd/partitions.h
166 +++ b/include/linux/mtd/partitions.h
167 @@ -89,12 +89,17 @@ extern int deregister_mtd_parser(struct
168 int mtd_is_partition(const struct mtd_info *mtd);
169 int mtd_add_partition(struct mtd_info *master, char *name,
170 long long offset, long long length);
171 +int __mtd_add_partition(struct mtd_info *master, char *name,
172 + long long offset, long long length, bool dup_check);
173 +
174 int mtd_del_partition(struct mtd_info *master, int partno);
175 struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
176 uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
177 uint64_t mtd_get_device_size(const struct mtd_info *mtd);
178 -extern void __weak arch_split_mtd_part(struct mtd_info *master,
179 - const char *name, int offset, int size);
180 +void __weak arch_split_mtd_part(struct mtd_info *master,
181 + const char *name, int offset, int size);
182 +unsigned long
183 +mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len);
184
185 int parse_mtd_partitions_by_type(struct mtd_info *master,
186 enum mtd_parser_type type,
187 --- a/drivers/mtd/mtdpart.c
188 +++ b/drivers/mtd/mtdpart.c
189 @@ -616,7 +616,7 @@ out_register:
190 }
191
192
193 -static int
194 +int
195 __mtd_add_partition(struct mtd_info *master, char *name,
196 long long offset, long long length, bool dup_check)
197 {
198 @@ -737,7 +737,7 @@ run_parsers_by_type(struct mtd_part *sla
199 return nr_parts;
200 }
201
202 -static inline unsigned long
203 +unsigned long
204 mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
205 {
206 unsigned long mask = mtd->erasesize - 1;
207 @@ -806,7 +806,6 @@ static void split_uimage(struct mtd_info
208 return;
209
210 len = be32_to_cpu(hdr.size) + 0x40;
211 - len = mtd_pad_erasesize(master, part->offset, len);
212 if (len + master->erasesize > part->mtd.size)
213 return;
214