kernel: backport MTD patch extracing TRX code to separated parser
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
parent
4d5f296af8
commit
f5f1d40b5e
@ -225,6 +225,7 @@ CONFIG_MTD_M25P80=y
|
||||
CONFIG_MTD_NAND=y
|
||||
CONFIG_MTD_NAND_BRCMNAND=y
|
||||
CONFIG_MTD_NAND_ECC=y
|
||||
CONFIG_MTD_PARSER_TRX=y
|
||||
# CONFIG_MTD_PHYSMAP_OF is not set
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_MTD_SPLIT_FIRMWARE=y
|
||||
|
@ -17,7 +17,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
#include <uapi/linux/magic.h>
|
||||
|
||||
@@ -249,6 +250,36 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
@@ -134,6 +135,36 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,320 @@
|
||||
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");
|
@ -1,8 +1,8 @@
|
||||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -174,6 +174,22 @@ config MTD_BCM47XX_PARTS
|
||||
This provides partitions parser for devices based on BCM47xx
|
||||
boards.
|
||||
@@ -178,6 +178,22 @@ menu "Partition parsers"
|
||||
source "drivers/mtd/parsers/Kconfig"
|
||||
endmenu
|
||||
|
||||
+config MTD_MYLOADER_PARTS
|
||||
+ tristate "MyLoader partition parsing"
|
||||
@ -30,6 +30,6 @@
|
||||
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
|
||||
obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
|
||||
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
||||
obj-y += parsers/
|
||||
|
||||
# 'Users' - code which presents functionality to userspace.
|
||||
obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
|
||||
|
@ -8,35 +8,32 @@ Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/mtd/bcm47xxpart.c | 50 +++++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 40 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -62,6 +62,34 @@ static void bcm47xxpart_add_part(struct
|
||||
part->mask_flags = mask_flags;
|
||||
}
|
||||
--- a/drivers/mtd/parsers/parser_trx.c
|
||||
+++ b/drivers/mtd/parsers/parser_trx.c
|
||||
@@ -29,6 +29,33 @@ struct trx_header {
|
||||
uint32_t offset[3];
|
||||
} __packed;
|
||||
|
||||
+/*
|
||||
+ * Calculate real end offset (address) for a given amount of data. It checks
|
||||
+ * all blocks skipping bad ones.
|
||||
+ */
|
||||
+static size_t bcm47xxpart_real_offset(struct mtd_info *master, size_t offset,
|
||||
+ size_t bytes)
|
||||
+static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes)
|
||||
+{
|
||||
+ size_t real_offset = offset;
|
||||
+ size_t real_offset = 0;
|
||||
+
|
||||
+ if (mtd_block_isbad(master, real_offset))
|
||||
+ if (mtd_block_isbad(mtd, real_offset))
|
||||
+ pr_warn("Base offset shouldn't be at bad block");
|
||||
+
|
||||
+ while (bytes >= master->erasesize) {
|
||||
+ bytes -= master->erasesize;
|
||||
+ real_offset += master->erasesize;
|
||||
+ while (mtd_block_isbad(master, real_offset)) {
|
||||
+ real_offset += master->erasesize;
|
||||
+ while (bytes >= mtd->erasesize) {
|
||||
+ bytes -= mtd->erasesize;
|
||||
+ real_offset += mtd->erasesize;
|
||||
+ while (mtd_block_isbad(mtd, real_offset)) {
|
||||
+ real_offset += mtd->erasesize;
|
||||
+
|
||||
+ if (real_offset >= master->size)
|
||||
+ return real_offset - master->erasesize;
|
||||
+ if (real_offset >= mtd->size)
|
||||
+ return real_offset - mtd->erasesize;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -45,47 +42,31 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
+ return real_offset;
|
||||
+}
|
||||
+
|
||||
static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master,
|
||||
size_t offset)
|
||||
static const char *parser_trx_data_part_name(struct mtd_info *master,
|
||||
size_t offset)
|
||||
{
|
||||
@@ -91,6 +119,7 @@ static int bcm47xxpart_parse_trx(struct
|
||||
{
|
||||
struct trx_header header;
|
||||
size_t bytes_read;
|
||||
+ size_t offset;
|
||||
int curr_part = 0;
|
||||
int i, err;
|
||||
|
||||
@@ -110,21 +139,25 @@ static int bcm47xxpart_parse_trx(struct
|
||||
|
||||
/* 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);
|
||||
+ offset = bcm47xxpart_real_offset(master, trx->offset,
|
||||
+ header.offset[i]);
|
||||
+ bcm47xxpart_add_part(&parts[curr_part++], "loader", offset, 0);
|
||||
@@ -83,21 +110,21 @@ static int parser_trx_parse(struct mtd_i
|
||||
if (trx.offset[2]) {
|
||||
part = &parts[curr_part++];
|
||||
part->name = "loader";
|
||||
- part->offset = trx.offset[i];
|
||||
+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (header.offset[i]) {
|
||||
- bcm47xxpart_add_part(&parts[curr_part++], "linux",
|
||||
- trx->offset + header.offset[i], 0);
|
||||
+ offset = bcm47xxpart_real_offset(master, trx->offset,
|
||||
+ header.offset[i]);
|
||||
+ bcm47xxpart_add_part(&parts[curr_part++], "linux", offset, 0);
|
||||
if (trx.offset[i]) {
|
||||
part = &parts[curr_part++];
|
||||
part->name = "linux";
|
||||
- part->offset = trx.offset[i];
|
||||
+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (header.offset[i]) {
|
||||
- size_t offset = trx->offset + header.offset[i];
|
||||
- const char *name = bcm47xxpart_trx_data_part_name(master,
|
||||
- offset);
|
||||
+ const char *name;
|
||||
+
|
||||
+ offset = bcm47xxpart_real_offset(master, trx->offset,
|
||||
+ header.offset[i]);
|
||||
+ name = bcm47xxpart_trx_data_part_name(master, offset);
|
||||
|
||||
bcm47xxpart_add_part(&parts[curr_part++], name, offset, 0);
|
||||
if (trx.offset[i]) {
|
||||
part = &parts[curr_part++];
|
||||
part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
|
||||
- part->offset = trx.offset[i];
|
||||
+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
#define ML_MAGIC1 0x39685a42
|
||||
#define ML_MAGIC2 0x26594131
|
||||
#define TRX_MAGIC 0x30524448
|
||||
@@ -297,6 +298,15 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
@@ -182,6 +183,15 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
MTD_WRITEABLE);
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user