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