brcm63xx: rename target to bcm63xx
[oweals/openwrt.git] / target / linux / bcm63xx / patches-4.14 / 121-mtd-bcm63xxpart-move-imagetag-parsing-to-its-own-par.patch
1 From a2b8c7f648e168573905818dbb4cb90ca3957c65 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jonas.gorski@gmail.com>
3 Date: Wed, 28 Jun 2017 18:29:43 +0200
4 Subject: [PATCH] mtd: bcm63xxpart: move imagetag parsing to its own parser
5
6 Move the bcm963xx Image Tag parsing into its own partition parser. This
7 Allows reusing the parser with different full flash parsers.
8
9 While moving it, rename it to bcm963* to better reflect it isn't chip
10 but board specific.
11
12 Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
13 ---
14 I tried to keep the code as-is, to keep the changes as small as
15 possible.
16
17 One side effect is that the partitions get renumbered, which means any
18 root=/dev/mtdblock* will now point to the wrong mtd device. But since
19 bcm963xx boards will require these hardcoded in the kernel commandline
20 anyway this should b a non issue, as it can be easily updated.
21
22 There is no such thing in the mips/bcm63xx defconfig, so nothing to update
23 there.
24
25  drivers/mtd/Kconfig                   |   1 +
26  drivers/mtd/bcm63xxpart.c             | 155 ++----------------------
27  drivers/mtd/parsers/Kconfig           |  11 ++
28  drivers/mtd/parsers/Makefile          |   1 +
29  drivers/mtd/parsers/parser_imagetag.c | 214 ++++++++++++++++++++++++++++++++++
30  5 files changed, 235 insertions(+), 147 deletions(-)
31  create mode 100644 drivers/mtd/parsers/parser_imagetag.c
32
33 --- a/drivers/mtd/Kconfig
34 +++ b/drivers/mtd/Kconfig
35 @@ -163,6 +163,7 @@ config MTD_BCM63XX_PARTS
36         tristate "BCM63XX CFE partitioning support"
37         depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
38         select CRC32
39 +       select MTD_PARSER_IMAGETAG
40         help
41           This provides partions parsing for BCM63xx devices with CFE
42           bootloaders.
43 --- a/drivers/mtd/bcm63xxpart.c
44 +++ b/drivers/mtd/bcm63xxpart.c
45 @@ -93,51 +93,19 @@ static int bcm63xx_read_nvram(struct mtd
46         return 0;
47  }
48  
49 -static int bcm63xx_read_image_tag(struct mtd_info *master, const char *name,
50 -       loff_t tag_offset, struct bcm_tag *buf)
51 -{
52 -       int ret;
53 -       size_t retlen;
54 -       u32 computed_crc;
55 -
56 -       ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf);
57 -       if (ret)
58 -               return ret;
59 -
60 -       if (retlen != sizeof(*buf))
61 -               return -EIO;
62 -
63 -       computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
64 -                               offsetof(struct bcm_tag, header_crc));
65 -       if (computed_crc == buf->header_crc) {
66 -               STR_NULL_TERMINATE(buf->board_id);
67 -               STR_NULL_TERMINATE(buf->tag_version);
68 -
69 -               pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n",
70 -                       name, tag_offset, buf->tag_version, buf->board_id);
71 -
72 -               return 0;
73 -       }
74 -
75 -       pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n",
76 -               name, tag_offset, buf->header_crc, computed_crc);
77 -       return 1;
78 -}
79 +static const char * const bcm63xx_cfe_part_types[] = {
80 +       "bcm963xx-imagetag",
81 +       NULL,
82 +};
83  
84  static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master,
85         const struct mtd_partition **pparts, struct bcm963xx_nvram *nvram)
86  {
87 -       /* CFE, NVRAM and global Linux are always present */
88 -       int nrparts = 3, curpart = 0;
89 -       struct bcm_tag *buf = NULL;
90         struct mtd_partition *parts;
91 -       int ret;
92 -       unsigned int rootfsaddr, kerneladdr, spareaddr;
93 -       unsigned int rootfslen, kernellen, sparelen, totallen;
94 +       int nrparts = 3, curpart = 0;
95         unsigned int cfelen, nvramlen;
96         unsigned int cfe_erasesize;
97         int i;
98 -       bool rootfs_first = false;
99  
100         cfe_erasesize = max_t(uint32_t, master->erasesize,
101                               BCM963XX_CFE_BLOCK_SIZE);
102 @@ -146,83 +114,9 @@ static int bcm63xx_parse_cfe_nor_partiti
103         nvramlen = nvram->psi_size * SZ_1K;
104         nvramlen = roundup(nvramlen, cfe_erasesize);
105  
106 -       buf = vmalloc(sizeof(struct bcm_tag));
107 -       if (!buf)
108 -               return -ENOMEM;
109 -
110 -       /* Get the tag */
111 -       ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf);
112 -       if (!ret) {
113 -               STR_NULL_TERMINATE(buf->flash_image_start);
114 -               if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) ||
115 -                               rootfsaddr < BCM963XX_EXTENDED_SIZE) {
116 -                       pr_err("invalid rootfs address: %*ph\n",
117 -                               (int)sizeof(buf->flash_image_start),
118 -                               buf->flash_image_start);
119 -                       goto invalid_tag;
120 -               }
121 -
122 -               STR_NULL_TERMINATE(buf->kernel_address);
123 -               if (kstrtouint(buf->kernel_address, 10, &kerneladdr) ||
124 -                               kerneladdr < BCM963XX_EXTENDED_SIZE) {
125 -                       pr_err("invalid kernel address: %*ph\n",
126 -                               (int)sizeof(buf->kernel_address),
127 -                               buf->kernel_address);
128 -                       goto invalid_tag;
129 -               }
130 -
131 -               STR_NULL_TERMINATE(buf->kernel_length);
132 -               if (kstrtouint(buf->kernel_length, 10, &kernellen)) {
133 -                       pr_err("invalid kernel length: %*ph\n",
134 -                               (int)sizeof(buf->kernel_length),
135 -                               buf->kernel_length);
136 -                       goto invalid_tag;
137 -               }
138 -
139 -               STR_NULL_TERMINATE(buf->total_length);
140 -               if (kstrtouint(buf->total_length, 10, &totallen)) {
141 -                       pr_err("invalid total length: %*ph\n",
142 -                               (int)sizeof(buf->total_length),
143 -                               buf->total_length);
144 -                       goto invalid_tag;
145 -               }
146 -
147 -               kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE;
148 -               rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE;
149 -               spareaddr = roundup(totallen, master->erasesize) + cfelen;
150 -
151 -               if (rootfsaddr < kerneladdr) {
152 -                       /* default Broadcom layout */
153 -                       rootfslen = kerneladdr - rootfsaddr;
154 -                       rootfs_first = true;
155 -               } else {
156 -                       /* OpenWrt layout */
157 -                       rootfsaddr = kerneladdr + kernellen;
158 -                       rootfslen = spareaddr - rootfsaddr;
159 -               }
160 -       } else if (ret > 0) {
161 -invalid_tag:
162 -               kernellen = 0;
163 -               rootfslen = 0;
164 -               rootfsaddr = 0;
165 -               spareaddr = cfelen;
166 -       } else {
167 -               goto out;
168 -       }
169 -       sparelen = master->size - spareaddr - nvramlen;
170 -
171 -       /* Determine number of partitions */
172 -       if (rootfslen > 0)
173 -               nrparts++;
174 -
175 -       if (kernellen > 0)
176 -               nrparts++;
177 -
178         parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
179 -       if (!parts) {
180 -               ret = -ENOMEM;
181 -               goto out;
182 -       }
183 +       if (!parts)
184 +               return -ENOMEM;
185  
186         /* Start building partition list */
187         parts[curpart].name = "CFE";
188 @@ -230,30 +124,6 @@ invalid_tag:
189         parts[curpart].size = cfelen;
190         curpart++;
191  
192 -       if (kernellen > 0) {
193 -               int kernelpart = curpart;
194 -
195 -               if (rootfslen > 0 && rootfs_first)
196 -                       kernelpart++;
197 -               parts[kernelpart].name = "kernel";
198 -               parts[kernelpart].offset = kerneladdr;
199 -               parts[kernelpart].size = kernellen;
200 -               curpart++;
201 -       }
202 -
203 -       if (rootfslen > 0) {
204 -               int rootfspart = curpart;
205 -
206 -               if (kernellen > 0 && rootfs_first)
207 -                       rootfspart--;
208 -               parts[rootfspart].name = "rootfs";
209 -               parts[rootfspart].offset = rootfsaddr;
210 -               parts[rootfspart].size = rootfslen;
211 -               if (sparelen > 0  && !rootfs_first)
212 -                       parts[rootfspart].size += sparelen;
213 -               curpart++;
214 -       }
215 -
216         parts[curpart].name = "nvram";
217         parts[curpart].offset = master->size - nvramlen;
218         parts[curpart].size = nvramlen;
219 @@ -263,22 +133,13 @@ invalid_tag:
220         parts[curpart].name = "linux";
221         parts[curpart].offset = cfelen;
222         parts[curpart].size = master->size - cfelen - nvramlen;
223 +       parts[curpart].types = bcm63xx_cfe_part_types;
224  
225         for (i = 0; i < nrparts; i++)
226                 pr_info("Partition %d is %s offset %llx and length %llx\n", i,
227                         parts[i].name, parts[i].offset, parts[i].size);
228  
229 -       pr_info("Spare partition is offset %x and length %x\n", spareaddr,
230 -               sparelen);
231 -
232         *pparts = parts;
233 -       ret = 0;
234 -
235 -out:
236 -       vfree(buf);
237 -
238 -       if (ret)
239 -               return ret;
240  
241         return nrparts;
242  }
243 --- a/drivers/mtd/parsers/Kconfig
244 +++ b/drivers/mtd/parsers/Kconfig
245 @@ -1,3 +1,14 @@
246 +config MTD_PARSER_IMAGETAG
247 +       tristate "Parser for BCM963XX Image Tag format partitions"
248 +       depends on BCM63XX || BMIPS || COMPILE_TEST
249 +       select CRC32
250 +       help
251 +         Image Tag is the firmware header used by broadcom on their xDSL line
252 +         of devices. It is used to describe the offsets and lengths of kernel
253 +         and rootfs partitions.
254 +         This driver adds support for parsing a partition with an Image Tag
255 +         header and creates up to two partitions, kernel and rootfs.
256 +
257  config MTD_PARSER_TRX
258         tristate "Parser for TRX format partitions"
259         depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST)
260 --- a/drivers/mtd/parsers/Makefile
261 +++ b/drivers/mtd/parsers/Makefile
262 @@ -1 +1,2 @@
263 +obj-$(CONFIG_MTD_PARSER_IMAGETAG)      += parser_imagetag.o
264  obj-$(CONFIG_MTD_PARSER_TRX)           += parser_trx.o
265 --- /dev/null
266 +++ b/drivers/mtd/parsers/parser_imagetag.c
267 @@ -0,0 +1,214 @@
268 +/*
269 + * BCM63XX CFE image tag parser
270 + *
271 + * Copyright Â© 2006-2008  Florian Fainelli <florian@openwrt.org>
272 + *                       Mike Albon <malbon@openwrt.org>
273 + * Copyright Â© 2009-2010  Daniel Dickinson <openwrt@cshore.neomailbox.net>
274 + * Copyright Â© 2011-2013  Jonas Gorski <jonas.gorski@gmail.com>
275 + *
276 + * This program is free software; you can redistribute it and/or modify
277 + * it under the terms of the GNU General Public License as published by
278 + * the Free Software Foundation; either version 2 of the License, or
279 + * (at your option) any later version.
280 + *
281 + */
282 +
283 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
284 +
285 +#include <linux/bcm963xx_tag.h>
286 +#include <linux/crc32.h>
287 +#include <linux/module.h>
288 +#include <linux/kernel.h>
289 +#include <linux/sizes.h>
290 +#include <linux/slab.h>
291 +#include <linux/vmalloc.h>
292 +#include <linux/mtd/mtd.h>
293 +#include <linux/mtd/partitions.h>
294 +
295 +/* Ensure strings read from flash structs are null terminated */
296 +#define STR_NULL_TERMINATE(x) \
297 +       do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0)
298 +
299 +static int bcm963xx_read_imagetag(struct mtd_info *master, const char *name,
300 +       loff_t tag_offset, struct bcm_tag *buf)
301 +{
302 +       int ret;
303 +       size_t retlen;
304 +       u32 computed_crc;
305 +
306 +       ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf);
307 +       if (ret)
308 +               return ret;
309 +
310 +       if (retlen != sizeof(*buf))
311 +               return -EIO;
312 +
313 +       computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
314 +                               offsetof(struct bcm_tag, header_crc));
315 +       if (computed_crc == buf->header_crc) {
316 +               STR_NULL_TERMINATE(buf->board_id);
317 +               STR_NULL_TERMINATE(buf->tag_version);
318 +
319 +               pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n",
320 +                       name, tag_offset, buf->tag_version, buf->board_id);
321 +
322 +               return 0;
323 +       }
324 +
325 +       pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n",
326 +               name, tag_offset, buf->header_crc, computed_crc);
327 +       return -EINVAL;
328 +}
329 +
330 +static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master,
331 +                                       const struct mtd_partition **pparts,
332 +                                       struct mtd_part_parser_data *data)
333 +{
334 +       /* CFE, NVRAM and global Linux are always present */
335 +       int nrparts = 0, curpart = 0;
336 +       struct bcm_tag *buf = NULL;
337 +       struct mtd_partition *parts;
338 +       int ret;
339 +       unsigned int rootfsaddr, kerneladdr, spareaddr, offset;
340 +       unsigned int rootfslen, kernellen, sparelen, totallen;
341 +       int i;
342 +       bool rootfs_first = false;
343 +
344 +       buf = vmalloc(sizeof(struct bcm_tag));
345 +       if (!buf)
346 +               return -ENOMEM;
347 +
348 +       /* Get the tag */
349 +       ret = bcm963xx_read_imagetag(master, "rootfs", 0, buf);
350 +       if (!ret) {
351 +               STR_NULL_TERMINATE(buf->flash_image_start);
352 +               if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) ||
353 +                               rootfsaddr < BCM963XX_EXTENDED_SIZE) {
354 +                       pr_err("invalid rootfs address: %*ph\n",
355 +                               (int)sizeof(buf->flash_image_start),
356 +                               buf->flash_image_start);
357 +                       goto out;
358 +               }
359 +
360 +               STR_NULL_TERMINATE(buf->kernel_address);
361 +               if (kstrtouint(buf->kernel_address, 10, &kerneladdr) ||
362 +                               kerneladdr < BCM963XX_EXTENDED_SIZE) {
363 +                       pr_err("invalid kernel address: %*ph\n",
364 +                               (int)sizeof(buf->kernel_address),
365 +                               buf->kernel_address);
366 +                       goto out;
367 +               }
368 +
369 +               STR_NULL_TERMINATE(buf->kernel_length);
370 +               if (kstrtouint(buf->kernel_length, 10, &kernellen)) {
371 +                       pr_err("invalid kernel length: %*ph\n",
372 +                               (int)sizeof(buf->kernel_length),
373 +                               buf->kernel_length);
374 +                       goto out;
375 +               }
376 +
377 +               STR_NULL_TERMINATE(buf->total_length);
378 +               if (kstrtouint(buf->total_length, 10, &totallen)) {
379 +                       pr_err("invalid total length: %*ph\n",
380 +                               (int)sizeof(buf->total_length),
381 +                               buf->total_length);
382 +                       goto out;
383 +               }
384 +
385 +               /*
386 +                * Addresses are flash absolute, so convert to partition
387 +                * relative addresses. Assume either kernel or rootfs will
388 +                * directly follow the image tag.
389 +                */
390 +               if (rootfsaddr < kerneladdr)
391 +                       offset = rootfsaddr - sizeof(struct bcm_tag);
392 +               else
393 +                       offset = kerneladdr - sizeof(struct bcm_tag);
394 +
395 +               kerneladdr = kerneladdr - offset;
396 +               rootfsaddr = rootfsaddr - offset;
397 +               spareaddr = roundup(totallen, master->erasesize);
398 +
399 +               if (rootfsaddr < kerneladdr) {
400 +                       /* default Broadcom layout */
401 +                       rootfslen = kerneladdr - rootfsaddr;
402 +                       rootfs_first = true;
403 +               } else {
404 +                       /* OpenWrt layout */
405 +                       rootfsaddr = kerneladdr + kernellen;
406 +                       rootfslen = spareaddr - rootfsaddr;
407 +               }
408 +       } else {
409 +               goto out;
410 +       }
411 +       sparelen = master->size - spareaddr;
412 +
413 +       /* Determine number of partitions */
414 +       if (rootfslen > 0)
415 +               nrparts++;
416 +
417 +       if (kernellen > 0)
418 +               nrparts++;
419 +
420 +       parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
421 +       if (!parts) {
422 +               ret = -ENOMEM;
423 +               goto out;
424 +       }
425 +
426 +       /* Start building partition list */
427 +       if (kernellen > 0) {
428 +               int kernelpart = curpart;
429 +
430 +               if (rootfslen > 0 && rootfs_first)
431 +                       kernelpart++;
432 +               parts[kernelpart].name = "kernel";
433 +               parts[kernelpart].offset = kerneladdr;
434 +               parts[kernelpart].size = kernellen;
435 +               curpart++;
436 +       }
437 +
438 +       if (rootfslen > 0) {
439 +               int rootfspart = curpart;
440 +
441 +               if (kernellen > 0 && rootfs_first)
442 +                       rootfspart--;
443 +               parts[rootfspart].name = "rootfs";
444 +               parts[rootfspart].offset = rootfsaddr;
445 +               parts[rootfspart].size = rootfslen;
446 +               if (sparelen > 0  && !rootfs_first)
447 +                       parts[rootfspart].size += sparelen;
448 +               curpart++;
449 +       }
450 +
451 +       for (i = 0; i < nrparts; i++)
452 +               pr_info("Partition %d is %s offset %llx and length %llx\n", i,
453 +                       parts[i].name, parts[i].offset, parts[i].size);
454 +
455 +       pr_info("Spare partition is offset %x and length %x\n", spareaddr,
456 +               sparelen);
457 +
458 +       *pparts = parts;
459 +       ret = 0;
460 +
461 +out:
462 +       vfree(buf);
463 +
464 +       if (ret)
465 +               return ret;
466 +
467 +       return nrparts;
468 +}
469 +
470 +static struct mtd_part_parser bcm963xx_imagetag_parser = {
471 +       .parse_fn = bcm963xx_parse_imagetag_partitions,
472 +       .name = "bcm963xx-imagetag",
473 +};
474 +module_mtd_part_parser(bcm963xx_imagetag_parser);
475 +
476 +MODULE_LICENSE("GPL");
477 +MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>");
478 +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
479 +MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>");
480 +MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com");
481 +MODULE_DESCRIPTION("MTD parser for BCM963XX CFE Image Tag partitions");