bcm63xx: copy files to kernel 5.4
[openwrt/staging/wigyori.git] / target / linux / bcm63xx / patches-5.4 / 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 @@ -162,6 +162,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,2 +1,3 @@
263 +obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
264 obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
265 obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
266 --- /dev/null
267 +++ b/drivers/mtd/parsers/parser_imagetag.c
268 @@ -0,0 +1,214 @@
269 +/*
270 + * BCM63XX CFE image tag parser
271 + *
272 + * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org>
273 + * Mike Albon <malbon@openwrt.org>
274 + * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
275 + * Copyright © 2011-2013 Jonas Gorski <jonas.gorski@gmail.com>
276 + *
277 + * This program is free software; you can redistribute it and/or modify
278 + * it under the terms of the GNU General Public License as published by
279 + * the Free Software Foundation; either version 2 of the License, or
280 + * (at your option) any later version.
281 + *
282 + */
283 +
284 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
285 +
286 +#include <linux/bcm963xx_tag.h>
287 +#include <linux/crc32.h>
288 +#include <linux/module.h>
289 +#include <linux/kernel.h>
290 +#include <linux/sizes.h>
291 +#include <linux/slab.h>
292 +#include <linux/vmalloc.h>
293 +#include <linux/mtd/mtd.h>
294 +#include <linux/mtd/partitions.h>
295 +
296 +/* Ensure strings read from flash structs are null terminated */
297 +#define STR_NULL_TERMINATE(x) \
298 + do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0)
299 +
300 +static int bcm963xx_read_imagetag(struct mtd_info *master, const char *name,
301 + loff_t tag_offset, struct bcm_tag *buf)
302 +{
303 + int ret;
304 + size_t retlen;
305 + u32 computed_crc;
306 +
307 + ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf);
308 + if (ret)
309 + return ret;
310 +
311 + if (retlen != sizeof(*buf))
312 + return -EIO;
313 +
314 + computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
315 + offsetof(struct bcm_tag, header_crc));
316 + if (computed_crc == buf->header_crc) {
317 + STR_NULL_TERMINATE(buf->board_id);
318 + STR_NULL_TERMINATE(buf->tag_version);
319 +
320 + pr_info("%s: CFE image tag found at 0x%llx with version %s, board type %s\n",
321 + name, tag_offset, buf->tag_version, buf->board_id);
322 +
323 + return 0;
324 + }
325 +
326 + pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual %08x)\n",
327 + name, tag_offset, buf->header_crc, computed_crc);
328 + return -EINVAL;
329 +}
330 +
331 +static int bcm963xx_parse_imagetag_partitions(struct mtd_info *master,
332 + const struct mtd_partition **pparts,
333 + struct mtd_part_parser_data *data)
334 +{
335 + /* CFE, NVRAM and global Linux are always present */
336 + int nrparts = 0, curpart = 0;
337 + struct bcm_tag *buf = NULL;
338 + struct mtd_partition *parts;
339 + int ret;
340 + unsigned int rootfsaddr, kerneladdr, spareaddr, offset;
341 + unsigned int rootfslen, kernellen, sparelen, totallen;
342 + int i;
343 + bool rootfs_first = false;
344 +
345 + buf = vmalloc(sizeof(struct bcm_tag));
346 + if (!buf)
347 + return -ENOMEM;
348 +
349 + /* Get the tag */
350 + ret = bcm963xx_read_imagetag(master, "rootfs", 0, buf);
351 + if (!ret) {
352 + STR_NULL_TERMINATE(buf->flash_image_start);
353 + if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) ||
354 + rootfsaddr < BCM963XX_EXTENDED_SIZE) {
355 + pr_err("invalid rootfs address: %*ph\n",
356 + (int)sizeof(buf->flash_image_start),
357 + buf->flash_image_start);
358 + goto out;
359 + }
360 +
361 + STR_NULL_TERMINATE(buf->kernel_address);
362 + if (kstrtouint(buf->kernel_address, 10, &kerneladdr) ||
363 + kerneladdr < BCM963XX_EXTENDED_SIZE) {
364 + pr_err("invalid kernel address: %*ph\n",
365 + (int)sizeof(buf->kernel_address),
366 + buf->kernel_address);
367 + goto out;
368 + }
369 +
370 + STR_NULL_TERMINATE(buf->kernel_length);
371 + if (kstrtouint(buf->kernel_length, 10, &kernellen)) {
372 + pr_err("invalid kernel length: %*ph\n",
373 + (int)sizeof(buf->kernel_length),
374 + buf->kernel_length);
375 + goto out;
376 + }
377 +
378 + STR_NULL_TERMINATE(buf->total_length);
379 + if (kstrtouint(buf->total_length, 10, &totallen)) {
380 + pr_err("invalid total length: %*ph\n",
381 + (int)sizeof(buf->total_length),
382 + buf->total_length);
383 + goto out;
384 + }
385 +
386 + /*
387 + * Addresses are flash absolute, so convert to partition
388 + * relative addresses. Assume either kernel or rootfs will
389 + * directly follow the image tag.
390 + */
391 + if (rootfsaddr < kerneladdr)
392 + offset = rootfsaddr - sizeof(struct bcm_tag);
393 + else
394 + offset = kerneladdr - sizeof(struct bcm_tag);
395 +
396 + kerneladdr = kerneladdr - offset;
397 + rootfsaddr = rootfsaddr - offset;
398 + spareaddr = roundup(totallen, master->erasesize);
399 +
400 + if (rootfsaddr < kerneladdr) {
401 + /* default Broadcom layout */
402 + rootfslen = kerneladdr - rootfsaddr;
403 + rootfs_first = true;
404 + } else {
405 + /* OpenWrt layout */
406 + rootfsaddr = kerneladdr + kernellen;
407 + rootfslen = spareaddr - rootfsaddr;
408 + }
409 + } else {
410 + goto out;
411 + }
412 + sparelen = master->size - spareaddr;
413 +
414 + /* Determine number of partitions */
415 + if (rootfslen > 0)
416 + nrparts++;
417 +
418 + if (kernellen > 0)
419 + nrparts++;
420 +
421 + parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
422 + if (!parts) {
423 + ret = -ENOMEM;
424 + goto out;
425 + }
426 +
427 + /* Start building partition list */
428 + if (kernellen > 0) {
429 + int kernelpart = curpart;
430 +
431 + if (rootfslen > 0 && rootfs_first)
432 + kernelpart++;
433 + parts[kernelpart].name = "kernel";
434 + parts[kernelpart].offset = kerneladdr;
435 + parts[kernelpart].size = kernellen;
436 + curpart++;
437 + }
438 +
439 + if (rootfslen > 0) {
440 + int rootfspart = curpart;
441 +
442 + if (kernellen > 0 && rootfs_first)
443 + rootfspart--;
444 + parts[rootfspart].name = "rootfs";
445 + parts[rootfspart].offset = rootfsaddr;
446 + parts[rootfspart].size = rootfslen;
447 + if (sparelen > 0 && !rootfs_first)
448 + parts[rootfspart].size += sparelen;
449 + curpart++;
450 + }
451 +
452 + for (i = 0; i < nrparts; i++)
453 + pr_info("Partition %d is %s offset %llx and length %llx\n", i,
454 + parts[i].name, parts[i].offset, parts[i].size);
455 +
456 + pr_info("Spare partition is offset %x and length %x\n", spareaddr,
457 + sparelen);
458 +
459 + *pparts = parts;
460 + ret = 0;
461 +
462 +out:
463 + vfree(buf);
464 +
465 + if (ret)
466 + return ret;
467 +
468 + return nrparts;
469 +}
470 +
471 +static struct mtd_part_parser bcm963xx_imagetag_parser = {
472 + .parse_fn = bcm963xx_parse_imagetag_partitions,
473 + .name = "bcm963xx-imagetag",
474 +};
475 +module_mtd_part_parser(bcm963xx_imagetag_parser);
476 +
477 +MODULE_LICENSE("GPL");
478 +MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>");
479 +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
480 +MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>");
481 +MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com");
482 +MODULE_DESCRIPTION("MTD parser for BCM963XX CFE Image Tag partitions");