kernel: backport MTD patch extracing TRX code to separated parser

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
owl
Rafał Miłecki 2017-06-23 10:58:16 +02:00
parent 4d5f296af8
commit f5f1d40b5e
6 changed files with 362 additions and 60 deletions

View File

@ -225,6 +225,7 @@ CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_BRCMNAND=y CONFIG_MTD_NAND_BRCMNAND=y
CONFIG_MTD_NAND_ECC=y CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_PARSER_TRX=y
# CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MTD_PHYSMAP_OF is not set
CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_FIRMWARE=y

View File

@ -17,7 +17,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
#include <uapi/linux/magic.h> #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; break;
} }

View File

@ -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");

View File

@ -1,8 +1,8 @@
--- a/drivers/mtd/Kconfig --- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig
@@ -174,6 +174,22 @@ config MTD_BCM47XX_PARTS @@ -178,6 +178,22 @@ menu "Partition parsers"
This provides partitions parser for devices based on BCM47xx source "drivers/mtd/parsers/Kconfig"
boards. endmenu
+config MTD_MYLOADER_PARTS +config MTD_MYLOADER_PARTS
+ tristate "MyLoader partition parsing" + tristate "MyLoader partition parsing"
@ -30,6 +30,6 @@
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o +obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
obj-y += parsers/
# 'Users' - code which presents functionality to userspace. # 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o

View File

@ -8,35 +8,32 @@ Content-Transfer-Encoding: 8bit
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> 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 --- a/drivers/mtd/parsers/parser_trx.c
+++ b/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/parsers/parser_trx.c
@@ -62,6 +62,34 @@ static void bcm47xxpart_add_part(struct @@ -29,6 +29,33 @@ struct trx_header {
part->mask_flags = mask_flags; uint32_t offset[3];
} } __packed;
+/* +/*
+ * Calculate real end offset (address) for a given amount of data. It checks + * Calculate real end offset (address) for a given amount of data. It checks
+ * all blocks skipping bad ones. + * all blocks skipping bad ones.
+ */ + */
+static size_t bcm47xxpart_real_offset(struct mtd_info *master, size_t offset, +static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes)
+ 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"); + pr_warn("Base offset shouldn't be at bad block");
+ +
+ while (bytes >= master->erasesize) { + while (bytes >= mtd->erasesize) {
+ bytes -= master->erasesize; + bytes -= mtd->erasesize;
+ real_offset += master->erasesize; + real_offset += mtd->erasesize;
+ while (mtd_block_isbad(master, real_offset)) { + while (mtd_block_isbad(mtd, real_offset)) {
+ real_offset += master->erasesize; + real_offset += mtd->erasesize;
+ +
+ if (real_offset >= master->size) + if (real_offset >= mtd->size)
+ return real_offset - master->erasesize; + return real_offset - mtd->erasesize;
+ } + }
+ } + }
+ +
@ -45,47 +42,31 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+ return real_offset; + return real_offset;
+} +}
+ +
static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, static const char *parser_trx_data_part_name(struct mtd_info *master,
size_t offset) size_t offset)
{ {
@@ -91,6 +119,7 @@ static int bcm47xxpart_parse_trx(struct @@ -83,21 +110,21 @@ static int parser_trx_parse(struct mtd_i
{ if (trx.offset[2]) {
struct trx_header header; part = &parts[curr_part++];
size_t bytes_read; part->name = "loader";
+ size_t offset; - part->offset = trx.offset[i];
int curr_part = 0; + part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
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);
i++; i++;
} }
if (header.offset[i]) { if (trx.offset[i]) {
- bcm47xxpart_add_part(&parts[curr_part++], "linux", part = &parts[curr_part++];
- trx->offset + header.offset[i], 0); part->name = "linux";
+ offset = bcm47xxpart_real_offset(master, trx->offset, - part->offset = trx.offset[i];
+ header.offset[i]); + part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
+ bcm47xxpart_add_part(&parts[curr_part++], "linux", offset, 0);
i++; i++;
} }
if (header.offset[i]) { if (trx.offset[i]) {
- size_t offset = trx->offset + header.offset[i]; part = &parts[curr_part++];
- const char *name = bcm47xxpart_trx_data_part_name(master, part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
- offset); - part->offset = trx.offset[i];
+ const char *name; + part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
+
+ 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);
i++; i++;
}

View File

@ -24,7 +24,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
#define ML_MAGIC1 0x39685a42 #define ML_MAGIC1 0x39685a42
#define ML_MAGIC2 0x26594131 #define ML_MAGIC2 0x26594131
#define TRX_MAGIC 0x30524448 #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); MTD_WRITEABLE);
continue; continue;
} }