You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
8.3 KiB
320 lines
8.3 KiB
From 99352afe8f169c95b294b6b9a8d0e18cd9e3c2a0 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
|
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 <rafal@milecki.pl>
|
|
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
|
---
|
|
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 <rafal@milecki.pl>
|
|
+ *
|
|
+ * 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");
|
|
|