lantiq: make the split patch recognize the tplink header
[oweals/openwrt.git] / target / linux / lantiq / patches-3.8 / 0041-owrt-mtd-split.patch
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
5
6 ---
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(-)
12
13 Index: linux-3.8.13/drivers/mtd/Kconfig
14 ===================================================================
15 --- linux-3.8.13.orig/drivers/mtd/Kconfig       2013-08-04 19:55:18.499988719 +0200
16 +++ linux-3.8.13/drivers/mtd/Kconfig    2013-08-04 19:55:22.599988819 +0200
17 @@ -31,6 +31,10 @@
18         bool "Automatically split 'rootfs' partition for squashfs"
19         default y
20  
21 +config MTD_UIMAGE_SPLIT
22 +       bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
23 +       default y
24 +
25  config MTD_REDBOOT_PARTS
26         tristate "RedBoot partition table parsing"
27         ---help---
28 Index: linux-3.8.13/drivers/mtd/mtdpart.c
29 ===================================================================
30 --- linux-3.8.13.orig/drivers/mtd/mtdpart.c     2013-08-04 19:55:18.791988726 +0200
31 +++ linux-3.8.13/drivers/mtd/mtdpart.c  2013-08-06 13:39:13.212319144 +0200
32 @@ -833,6 +833,191 @@
33  }
34  #endif /* CONFIG_MTD_ROOTFS_SPLIT */
35  
36 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
37 +static unsigned long find_uimage_size(struct mtd_info *mtd,
38 +                                     unsigned long offset)
39 +{
40 +#define UBOOT_MAGIC    0x56190527
41 +       unsigned long magic = 0;
42 +       unsigned long temp;
43 +       size_t len;
44 +       int ret;
45 +
46 +       ret = mtd_read(mtd, offset, 4, &len, (void *)&magic);
47 +       if (ret || len != sizeof(magic))
48 +               return 0;
49 +
50 +       if (le32_to_cpu(magic) != UBOOT_MAGIC)
51 +               return 0;
52 +
53 +       ret = mtd_read(mtd, offset + 12, 4, &len, (void *)&temp);
54 +       if (ret || len != sizeof(temp))
55 +               return 0;
56 +
57 +       return temp + 0x40;
58 +}
59 +
60 +static unsigned long find_tplink_size(struct mtd_info *mtd,
61 +                                     unsigned long offset)
62 +{
63 +#define TPLINK_MAGIC   0x00000002
64 +       unsigned long magic = 0;
65 +       unsigned long temp;
66 +       size_t len;
67 +       int ret;
68 +
69 +       ret = mtd_read(mtd, offset, 4, &len, (void *)&magic);
70 +       if (ret || len != sizeof(magic))
71 +               return 0;
72 +
73 +       if (le32_to_cpu(magic) != TPLINK_MAGIC)
74 +               return 0;
75 +
76 +       ret = mtd_read(mtd, offset + 0x78, 4, &len, (void *)&temp);
77 +       if (ret || len != sizeof(temp))
78 +               return 0;
79 +
80 +       return temp + 0x200;
81 +}
82 +
83 +static unsigned long find_eva_size(struct mtd_info *mtd,
84 +                                     unsigned long offset)
85 +{
86 +#define EVA_MAGIC      0xfeed1281
87 +       unsigned long magic = 0;
88 +       unsigned long temp;
89 +       size_t len;
90 +       int ret;
91 +
92 +       ret = mtd_read(mtd, offset, 4, &len, (void *)&magic);
93 +       if (ret || len != sizeof(magic))
94 +               return 0;
95 +
96 +       if (le32_to_cpu(magic) != EVA_MAGIC)
97 +               return 0;
98 +
99 +       ret = mtd_read(mtd, offset + 4, 4, &len, (void *)&temp);
100 +       if (ret || len != sizeof(temp))
101 +               return 0;
102 +
103 +       /* add eva header size */
104 +       temp = le32_to_cpu(temp) + 0x18;
105 +
106 +       temp &= ~0xffff;
107 +       temp += 0x10000;
108 +       return temp;
109 +}
110 +
111 +static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
112 +{
113 +       unsigned long temp;
114 +       size_t len;
115 +       int ret;
116 +
117 +       ret = mtd_read(mtd, offset, 4, &len, (void *)&temp);
118 +       if (ret || len != sizeof(temp))
119 +               return 0;
120 +
121 +
122 +       return le32_to_cpu(temp) == SQUASHFS_MAGIC;
123 +}
124 +
125 +static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
126 +{
127 +       unsigned long temp;
128 +       size_t len;
129 +       int ret;
130 +
131 +       ret = mtd_read(mtd, offset, 4, &len, (void *)&temp);
132 +       if (ret || len != sizeof(temp))
133 +               return 0;
134 +
135 +       return be32_to_cpu(temp) == SQUASHFS_MAGIC;
136 +}
137 +
138 +static unsigned long find_brnimage_size(struct mtd_info *mtd,
139 +                                       unsigned long offset)
140 +{
141 +       unsigned long buf[4];
142 +       // Assume at most 2MB of kernel image
143 +       unsigned long end = offset + (2 << 20);
144 +       unsigned long ptr = offset + 0x400 - 12;
145 +       size_t len;
146 +       int ret;
147 +
148 +       while (ptr < end) {
149 +               long size_min = ptr - 0x400 - 12 - offset;
150 +               long size_max = ptr + 12 - offset;
151 +               ret = mtd_read(mtd, ptr, 16, &len, (void *)buf);
152 +               if (ret || len != 16)
153 +                       return 0;
154 +
155 +               if (le32_to_cpu(buf[0]) < size_min ||
156 +                   le32_to_cpu(buf[0]) > size_max) {
157 +                       ptr += 0x400;
158 +                       continue;
159 +               }
160 +
161 +               if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
162 +                       return ptr + 12 - offset;
163 +
164 +               ptr += 0x400;
165 +       }
166 +
167 +       return 0;
168 +}
169 +
170 +static int split_uimage(struct mtd_info *mtd,
171 +                       const struct mtd_partition *part)
172 +{
173 +       static struct mtd_partition split_partitions[] = {
174 +               {
175 +                       .name = "kernel",
176 +                       .offset = 0x0,
177 +                       .size = 0x0,
178 +               }, {
179 +                       .name = "rootfs",
180 +                       .offset = 0x0,
181 +                       .size = 0x0,
182 +               },
183 +       };
184 +
185 +       split_partitions[0].size = find_uimage_size(mtd, part->offset);
186 +       if (!split_partitions[0].size)
187 +               split_partitions[0].size = find_eva_size(mtd, part->offset);
188 +       if (!split_partitions[0].size)
189 +               split_partitions[0].size = find_brnimage_size(mtd, part->offset);
190 +       if (!split_partitions[0].size)
191 +               split_partitions[0].size = find_tplink_size(mtd, part->offset);
192 +       if (!split_partitions[0].size) {
193 +               printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n");
194 +               return -1;
195 +       }
196 +
197 +       if (detect_eva_squashfs_partition(mtd,
198 +                                      part->offset
199 +                                      + split_partitions[0].size)) {
200 +               split_partitions[0].size += 0x100;
201 +               pr_info("found eva dummy squashfs behind kernel\n");
202 +       } else if (!detect_squashfs_partition(mtd,
203 +                                      part->offset
204 +                                      + split_partitions[0].size)) {
205 +               split_partitions[0].size &= ~(mtd->erasesize - 1);
206 +               split_partitions[0].size += mtd->erasesize;
207 +       } else {
208 +               pr_info("found squashfs behind kernel\n");
209 +       }
210 +
211 +       split_partitions[0].offset = part->offset;
212 +       split_partitions[1].offset = part->offset + split_partitions[0].size;
213 +       split_partitions[1].size = part->size - split_partitions[0].size;
214 +
215 +       add_mtd_partitions(mtd, split_partitions, 2);
216 +
217 +       return 0;
218 +}
219 +#endif
220 +
221  /*
222   * This function, given a master MTD object and a partition table, creates
223   * and registers slave MTD objects which are bound to the master according to
224 @@ -849,7 +1034,7 @@
225         struct mtd_part *slave;
226         uint64_t cur_offset = 0;
227         int i;
228 -#ifdef CONFIG_MTD_ROOTFS_SPLIT
229 +#if defined(CONFIG_MTD_ROOTFS_SPLIT) || defined(CONFIG_MTD_UIMAGE_SPLIT)
230         int ret;
231  #endif
232  
233 @@ -866,6 +1051,15 @@
234  
235                 add_mtd_device(&slave->mtd);
236  
237 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
238 +               if (!strcmp(parts[i].name, "linux")) {
239 +                       ret = split_uimage(master, &parts[i]);
240 +
241 +                       if (ret)
242 +                               printk(KERN_WARNING "Can't split linux partition\n");
243 +               }
244 +#endif
245 +
246                 if (!strcmp(parts[i].name, "rootfs")) {
247  #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
248                         if (ROOT_DEV == 0) {