From f5f1d40b5ec8130afa5440f958713e1d029b0161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 23 Jun 2017 10:58:16 +0200 Subject: [PATCH] kernel: backport MTD patch extracing TRX code to separated parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- target/linux/bcm53xx/config-4.9 | 1 + ...part-add-device-specific-workarounds.patch | 2 +- ...parser-out-of-bcm47xxpart-into-a-sep.patch | 320 ++++++++++++++++++ ...30-mtd-add-myloader-partition-parser.patch | 8 +- ...check-for-bad-blocks-when-calculatin.patch | 89 ++--- ...bcm47xxpart-detect-T_Meter-partition.patch | 2 +- 6 files changed, 362 insertions(+), 60 deletions(-) create mode 100644 target/linux/generic/patches-4.9/065-v4.13-0008-mtd-extract-TRX-parser-out-of-bcm47xxpart-into-a-sep.patch diff --git a/target/linux/bcm53xx/config-4.9 b/target/linux/bcm53xx/config-4.9 index 2859f03cad..c98ba7b478 100644 --- a/target/linux/bcm53xx/config-4.9 +++ b/target/linux/bcm53xx/config-4.9 @@ -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 diff --git a/target/linux/bcm53xx/patches-4.9/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch b/target/linux/bcm53xx/patches-4.9/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch index 0223ab4776..b4a25a39d0 100644 --- a/target/linux/bcm53xx/patches-4.9/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch +++ b/target/linux/bcm53xx/patches-4.9/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch @@ -17,7 +17,7 @@ Signed-off-by: Rafał Miłecki #include -@@ -249,6 +250,36 @@ static int bcm47xxpart_parse(struct mtd_ +@@ -134,6 +135,36 @@ static int bcm47xxpart_parse(struct mtd_ break; } diff --git a/target/linux/generic/patches-4.9/065-v4.13-0008-mtd-extract-TRX-parser-out-of-bcm47xxpart-into-a-sep.patch b/target/linux/generic/patches-4.9/065-v4.13-0008-mtd-extract-TRX-parser-out-of-bcm47xxpart-into-a-sep.patch new file mode 100644 index 0000000000..3761a46610 --- /dev/null +++ b/target/linux/generic/patches-4.9/065-v4.13-0008-mtd-extract-TRX-parser-out-of-bcm47xxpart-into-a-sep.patch @@ -0,0 +1,320 @@ +From 99352afe8f169c95b294b6b9a8d0e18cd9e3c2a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +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 +Signed-off-by: Brian Norris +--- + 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 ++ * ++ * 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 ++#include ++#include ++#include ++ ++#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"); diff --git a/target/linux/generic/patches-4.9/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/patches-4.9/430-mtd-add-myloader-partition-parser.patch index a022564e9e..9bf014e881 100644 --- a/target/linux/generic/patches-4.9/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/patches-4.9/430-mtd-add-myloader-partition-parser.patch @@ -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 diff --git a/target/linux/generic/patches-4.9/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch b/target/linux/generic/patches-4.9/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch index 379e551b7f..2726220b8e 100644 --- a/target/linux/generic/patches-4.9/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch +++ b/target/linux/generic/patches-4.9/431-mtd-bcm47xxpart-check-for-bad-blocks-when-calculatin.patch @@ -8,35 +8,32 @@ Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- - 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 + 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++; + } + diff --git a/target/linux/generic/patches-4.9/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch b/target/linux/generic/patches-4.9/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch index a19e943efe..b7b56cb5aa 100644 --- a/target/linux/generic/patches-4.9/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch +++ b/target/linux/generic/patches-4.9/432-mtd-bcm47xxpart-detect-T_Meter-partition.patch @@ -24,7 +24,7 @@ Signed-off-by: Rafał Miłecki #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; }