123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- From 99352afe8f169c95b294b6b9a8d0e18cd9e3c2a0 Mon Sep 17 00:00:00 2001
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
- Date: Wed, 21 Jun 2017 08:26:47 +0200
- Subject: [PATCH] mtd: extract TRX parser out of bcm47xxpart into a separated
- module
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- This makes TRX parsing code reusable with other platforms and parsers.
- Please note this patch doesn't really change anything in the existing
- code, just moves it. There is still some place for improvement (e.g.
- working on non-hacky method of checking rootfs format) but it's not
- really a subject of this change.
- Signed-off-by: Rafał Miłecki <[email protected]>
- Signed-off-by: Brian Norris <[email protected]>
- ---
- drivers/mtd/Kconfig | 4 ++
- drivers/mtd/Makefile | 1 +
- drivers/mtd/bcm47xxpart.c | 99 ++----------------------------
- drivers/mtd/parsers/Kconfig | 8 +++
- drivers/mtd/parsers/Makefile | 1 +
- drivers/mtd/parsers/parser_trx.c | 126 +++++++++++++++++++++++++++++++++++++++
- 6 files changed, 145 insertions(+), 94 deletions(-)
- create mode 100644 drivers/mtd/parsers/Kconfig
- create mode 100644 drivers/mtd/parsers/Makefile
- create mode 100644 drivers/mtd/parsers/parser_trx.c
- --- a/drivers/mtd/Kconfig
- +++ b/drivers/mtd/Kconfig
- @@ -155,6 +155,10 @@ config MTD_BCM47XX_PARTS
- This provides partitions parser for devices based on BCM47xx
- boards.
-
- +menu "Partition parsers"
- +source "drivers/mtd/parsers/Kconfig"
- +endmenu
- +
- comment "User Modules And Translation Layers"
-
- #
- --- a/drivers/mtd/Makefile
- +++ b/drivers/mtd/Makefile
- @@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
- obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
- obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
- obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
- +obj-y += parsers/
-
- # 'Users' - code which presents functionality to userspace.
- obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
- --- a/drivers/mtd/bcm47xxpart.c
- +++ b/drivers/mtd/bcm47xxpart.c
- @@ -43,7 +43,8 @@
- #define ML_MAGIC2 0x26594131
- #define TRX_MAGIC 0x30524448
- #define SHSQ_MAGIC 0x71736873 /* shsq (weird ZTE H218N endianness) */
- -#define UBI_EC_MAGIC 0x23494255 /* UBI# */
- +
- +static const char * const trx_types[] = { "trx", NULL };
-
- struct trx_header {
- uint32_t magic;
- @@ -62,89 +63,6 @@ static void bcm47xxpart_add_part(struct
- part->mask_flags = mask_flags;
- }
-
- -static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master,
- - size_t offset)
- -{
- - uint32_t buf;
- - size_t bytes_read;
- - int err;
- -
- - err = mtd_read(master, offset, sizeof(buf), &bytes_read,
- - (uint8_t *)&buf);
- - if (err && !mtd_is_bitflip(err)) {
- - pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
- - offset, err);
- - goto out_default;
- - }
- -
- - if (buf == UBI_EC_MAGIC)
- - return "ubi";
- -
- -out_default:
- - return "rootfs";
- -}
- -
- -static int bcm47xxpart_parse_trx(struct mtd_info *master,
- - struct mtd_partition *trx,
- - struct mtd_partition *parts,
- - size_t parts_len)
- -{
- - struct trx_header header;
- - size_t bytes_read;
- - int curr_part = 0;
- - int i, err;
- -
- - if (parts_len < 3) {
- - pr_warn("No enough space to add TRX partitions!\n");
- - return -ENOMEM;
- - }
- -
- - err = mtd_read(master, trx->offset, sizeof(header), &bytes_read,
- - (uint8_t *)&header);
- - if (err && !mtd_is_bitflip(err)) {
- - pr_err("mtd_read error while reading TRX header: %d\n", err);
- - return err;
- - }
- -
- - i = 0;
- -
- - /* We have LZMA loader if offset[2] points to sth */
- - if (header.offset[2]) {
- - bcm47xxpart_add_part(&parts[curr_part++], "loader",
- - trx->offset + header.offset[i], 0);
- - i++;
- - }
- -
- - if (header.offset[i]) {
- - bcm47xxpart_add_part(&parts[curr_part++], "linux",
- - trx->offset + header.offset[i], 0);
- - i++;
- - }
- -
- - if (header.offset[i]) {
- - size_t offset = trx->offset + header.offset[i];
- - const char *name = bcm47xxpart_trx_data_part_name(master,
- - offset);
- -
- - bcm47xxpart_add_part(&parts[curr_part++], name, offset, 0);
- - i++;
- - }
- -
- - /*
- - * Assume that every partition ends at the beginning of the one it is
- - * followed by.
- - */
- - for (i = 0; i < curr_part; i++) {
- - u64 next_part_offset = (i < curr_part - 1) ?
- - parts[i + 1].offset :
- - trx->offset + trx->size;
- -
- - parts[i].size = next_part_offset - parts[i].offset;
- - }
- -
- - return curr_part;
- -}
- -
- /**
- * bcm47xxpart_bootpartition - gets index of TRX partition used by bootloader
- *
- @@ -362,17 +280,10 @@ static int bcm47xxpart_parse(struct mtd_
- for (i = 0; i < trx_num; i++) {
- struct mtd_partition *trx = &parts[trx_parts[i]];
-
- - if (i == bcm47xxpart_bootpartition()) {
- - int num_parts;
- -
- - num_parts = bcm47xxpart_parse_trx(master, trx,
- - parts + curr_part,
- - BCM47XXPART_MAX_PARTS - curr_part);
- - if (num_parts > 0)
- - curr_part += num_parts;
- - } else {
- + if (i == bcm47xxpart_bootpartition())
- + trx->types = trx_types;
- + else
- trx->name = "failsafe";
- - }
- }
-
- *pparts = parts;
- --- /dev/null
- +++ b/drivers/mtd/parsers/Kconfig
- @@ -0,0 +1,8 @@
- +config MTD_PARSER_TRX
- + tristate "Parser for TRX format partitions"
- + depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST)
- + help
- + TRX is a firmware format used by Broadcom on their devices. It
- + may contain up to 3/4 partitions (depending on the version).
- + This driver will parse TRX header and report at least two partitions:
- + kernel and rootfs.
- --- /dev/null
- +++ b/drivers/mtd/parsers/Makefile
- @@ -0,0 +1 @@
- +obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
- --- /dev/null
- +++ b/drivers/mtd/parsers/parser_trx.c
- @@ -0,0 +1,126 @@
- +/*
- + * Parser for TRX format partitions
- + *
- + * Copyright (C) 2012 - 2017 Rafał Miłecki <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + */
- +
- +#include <linux/module.h>
- +#include <linux/slab.h>
- +#include <linux/mtd/mtd.h>
- +#include <linux/mtd/partitions.h>
- +
- +#define TRX_PARSER_MAX_PARTS 4
- +
- +/* Magics */
- +#define TRX_MAGIC 0x30524448
- +#define UBI_EC_MAGIC 0x23494255 /* UBI# */
- +
- +struct trx_header {
- + uint32_t magic;
- + uint32_t length;
- + uint32_t crc32;
- + uint16_t flags;
- + uint16_t version;
- + uint32_t offset[3];
- +} __packed;
- +
- +static const char *parser_trx_data_part_name(struct mtd_info *master,
- + size_t offset)
- +{
- + uint32_t buf;
- + size_t bytes_read;
- + int err;
- +
- + err = mtd_read(master, offset, sizeof(buf), &bytes_read,
- + (uint8_t *)&buf);
- + if (err && !mtd_is_bitflip(err)) {
- + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
- + offset, err);
- + goto out_default;
- + }
- +
- + if (buf == UBI_EC_MAGIC)
- + return "ubi";
- +
- +out_default:
- + return "rootfs";
- +}
- +
- +static int parser_trx_parse(struct mtd_info *mtd,
- + const struct mtd_partition **pparts,
- + struct mtd_part_parser_data *data)
- +{
- + struct mtd_partition *parts;
- + struct mtd_partition *part;
- + struct trx_header trx;
- + size_t bytes_read;
- + uint8_t curr_part = 0, i = 0;
- + int err;
- +
- + parts = kzalloc(sizeof(struct mtd_partition) * TRX_PARSER_MAX_PARTS,
- + GFP_KERNEL);
- + if (!parts)
- + return -ENOMEM;
- +
- + err = mtd_read(mtd, 0, sizeof(trx), &bytes_read, (uint8_t *)&trx);
- + if (err) {
- + pr_err("MTD reading error: %d\n", err);
- + kfree(parts);
- + return err;
- + }
- +
- + if (trx.magic != TRX_MAGIC) {
- + kfree(parts);
- + return -ENOENT;
- + }
- +
- + /* We have LZMA loader if there is address in offset[2] */
- + if (trx.offset[2]) {
- + part = &parts[curr_part++];
- + part->name = "loader";
- + part->offset = trx.offset[i];
- + i++;
- + }
- +
- + if (trx.offset[i]) {
- + part = &parts[curr_part++];
- + part->name = "linux";
- + part->offset = trx.offset[i];
- + i++;
- + }
- +
- + if (trx.offset[i]) {
- + part = &parts[curr_part++];
- + part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
- + part->offset = trx.offset[i];
- + i++;
- + }
- +
- + /*
- + * Assume that every partition ends at the beginning of the one it is
- + * followed by.
- + */
- + for (i = 0; i < curr_part; i++) {
- + u64 next_part_offset = (i < curr_part - 1) ?
- + parts[i + 1].offset : mtd->size;
- +
- + parts[i].size = next_part_offset - parts[i].offset;
- + }
- +
- + *pparts = parts;
- + return i;
- +};
- +
- +static struct mtd_part_parser mtd_parser_trx = {
- + .parse_fn = parser_trx_parse,
- + .name = "trx",
- +};
- +module_mtd_part_parser(mtd_parser_trx);
- +
- +MODULE_LICENSE("GPL v2");
- +MODULE_DESCRIPTION("Parser for TRX format partitions");
|