diff options
Diffstat (limited to 'target/linux/generic/backport-5.10/411-v6.0-mtd-parsers-add-support-for-Sercomm-partitions.patch')
-rw-r--r-- | target/linux/generic/backport-5.10/411-v6.0-mtd-parsers-add-support-for-Sercomm-partitions.patch | 301 |
1 files changed, 0 insertions, 301 deletions
diff --git a/target/linux/generic/backport-5.10/411-v6.0-mtd-parsers-add-support-for-Sercomm-partitions.patch b/target/linux/generic/backport-5.10/411-v6.0-mtd-parsers-add-support-for-Sercomm-partitions.patch deleted file mode 100644 index 5ed6fd1b3b..0000000000 --- a/target/linux/generic/backport-5.10/411-v6.0-mtd-parsers-add-support-for-Sercomm-partitions.patch +++ /dev/null @@ -1,301 +0,0 @@ -From 9b78ef0c7997052e9eaa0f7a4513d546fa17358c Mon Sep 17 00:00:00 2001 -From: Mikhail Zhilkin <csharper2005@gmail.com> -Date: Sun, 29 May 2022 11:07:14 +0000 -Subject: [PATCH] mtd: parsers: add support for Sercomm partitions - -This adds an MTD partition parser for the Sercomm partition table that -is used in some Beeline, Netgear and Sercomm routers. - -The Sercomm partition map table contains real partition offsets, which -may differ from device to device depending on the number and location of -bad blocks on NAND. - -Original patch (proposed by NOGUCHI Hiroshi): -Link: https://github.com/openwrt/openwrt/pull/1318#issuecomment-420607394 - -Signed-off-by: NOGUCHI Hiroshi <drvlabo@gmail.com> -Signed-off-by: Mikhail Zhilkin <csharper2005@gmail.com> -Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> -Link: https://lore.kernel.org/linux-mtd/20220529110714.189732-1-csharper2005@gmail.com ---- - drivers/mtd/parsers/Kconfig | 9 ++ - drivers/mtd/parsers/Makefile | 1 + - drivers/mtd/parsers/scpart.c | 248 +++++++++++++++++++++++++++++++++++ - 3 files changed, 258 insertions(+) - create mode 100644 drivers/mtd/parsers/scpart.c - ---- a/drivers/mtd/parsers/Kconfig -+++ b/drivers/mtd/parsers/Kconfig -@@ -179,3 +179,12 @@ config MTD_REDBOOT_PARTS_READONLY - 'FIS directory' images, enable this option. - - endif # MTD_REDBOOT_PARTS -+ -+config MTD_SERCOMM_PARTS -+ tristate "Sercomm partition table parser" -+ depends on MTD && RALINK -+ help -+ This provides partitions table parser for devices with Sercomm -+ partition map. This partition table contains real partition -+ offsets, which may differ from device to device depending on the -+ number and location of bad blocks on NAND. ---- a/drivers/mtd/parsers/Makefile -+++ b/drivers/mtd/parsers/Makefile -@@ -10,5 +10,6 @@ ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS) - obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o -+obj-$(CONFIG_MTD_SERCOMM_PARTS) += scpart.o - obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o - obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o ---- /dev/null -+++ b/drivers/mtd/parsers/scpart.c -@@ -0,0 +1,248 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * drivers/mtd/scpart.c: Sercomm Partition Parser -+ * -+ * Copyright (C) 2018 NOGUCHI Hiroshi -+ * Copyright (C) 2022 Mikhail Zhilkin -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/slab.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/partitions.h> -+#include <linux/module.h> -+ -+#define MOD_NAME "scpart" -+ -+#ifdef pr_fmt -+#undef pr_fmt -+#endif -+ -+#define pr_fmt(fmt) MOD_NAME ": " fmt -+ -+#define ID_ALREADY_FOUND 0xffffffffUL -+ -+#define MAP_OFFS_IN_BLK 0x800 -+#define MAP_MIRROR_NUM 2 -+ -+static const char sc_part_magic[] = { -+ 'S', 'C', 'F', 'L', 'M', 'A', 'P', 'O', 'K', '\0', -+}; -+#define PART_MAGIC_LEN sizeof(sc_part_magic) -+ -+/* assumes that all fields are set by CPU native endian */ -+struct sc_part_desc { -+ uint32_t part_id; -+ uint32_t part_offs; -+ uint32_t part_bytes; -+}; -+ -+static uint32_t scpart_desc_is_valid(struct sc_part_desc *pdesc) -+{ -+ return ((pdesc->part_id != 0xffffffffUL) && -+ (pdesc->part_offs != 0xffffffffUL) && -+ (pdesc->part_bytes != 0xffffffffUL)); -+} -+ -+static int scpart_scan_partmap(struct mtd_info *master, loff_t partmap_offs, -+ struct sc_part_desc **ppdesc) -+{ -+ int cnt = 0; -+ int res = 0; -+ int res2; -+ loff_t offs; -+ size_t retlen; -+ struct sc_part_desc *pdesc = NULL; -+ struct sc_part_desc *tmpdesc; -+ uint8_t *buf; -+ -+ buf = kzalloc(master->erasesize, GFP_KERNEL); -+ if (!buf) { -+ res = -ENOMEM; -+ goto out; -+ } -+ -+ res2 = mtd_read(master, partmap_offs, master->erasesize, &retlen, buf); -+ if (res2 || retlen != master->erasesize) { -+ res = -EIO; -+ goto free; -+ } -+ -+ for (offs = MAP_OFFS_IN_BLK; -+ offs < master->erasesize - sizeof(*tmpdesc); -+ offs += sizeof(*tmpdesc)) { -+ tmpdesc = (struct sc_part_desc *)&buf[offs]; -+ if (!scpart_desc_is_valid(tmpdesc)) -+ break; -+ cnt++; -+ } -+ -+ if (cnt > 0) { -+ int bytes = cnt * sizeof(*pdesc); -+ -+ pdesc = kcalloc(cnt, sizeof(*pdesc), GFP_KERNEL); -+ if (!pdesc) { -+ res = -ENOMEM; -+ goto free; -+ } -+ memcpy(pdesc, &(buf[MAP_OFFS_IN_BLK]), bytes); -+ -+ *ppdesc = pdesc; -+ res = cnt; -+ } -+ -+free: -+ kfree(buf); -+ -+out: -+ return res; -+} -+ -+static int scpart_find_partmap(struct mtd_info *master, -+ struct sc_part_desc **ppdesc) -+{ -+ int magic_found = 0; -+ int res = 0; -+ int res2; -+ loff_t offs = 0; -+ size_t retlen; -+ uint8_t rdbuf[PART_MAGIC_LEN]; -+ -+ while ((magic_found < MAP_MIRROR_NUM) && -+ (offs < master->size) && -+ !mtd_block_isbad(master, offs)) { -+ res2 = mtd_read(master, offs, PART_MAGIC_LEN, &retlen, rdbuf); -+ if (res2 || retlen != PART_MAGIC_LEN) { -+ res = -EIO; -+ goto out; -+ } -+ if (!memcmp(rdbuf, sc_part_magic, PART_MAGIC_LEN)) { -+ pr_debug("Signature found at 0x%llx\n", offs); -+ magic_found++; -+ res = scpart_scan_partmap(master, offs, ppdesc); -+ if (res > 0) -+ goto out; -+ } -+ offs += master->erasesize; -+ } -+ -+out: -+ if (res > 0) -+ pr_info("Valid 'SC PART MAP' (%d partitions) found at 0x%llx\n", res, offs); -+ else -+ pr_info("No valid 'SC PART MAP' was found\n"); -+ -+ return res; -+} -+ -+static int scpart_parse(struct mtd_info *master, -+ const struct mtd_partition **pparts, -+ struct mtd_part_parser_data *data) -+{ -+ const char *partname; -+ int n; -+ int nr_scparts; -+ int nr_parts = 0; -+ int res = 0; -+ struct sc_part_desc *scpart_map = NULL; -+ struct mtd_partition *parts = NULL; -+ struct device_node *mtd_node; -+ struct device_node *ofpart_node; -+ struct device_node *pp; -+ -+ mtd_node = mtd_get_of_node(master); -+ if (!mtd_node) { -+ res = -ENOENT; -+ goto out; -+ } -+ -+ ofpart_node = of_get_child_by_name(mtd_node, "partitions"); -+ if (!ofpart_node) { -+ pr_info("%s: 'partitions' subnode not found on %pOF.\n", -+ master->name, mtd_node); -+ res = -ENOENT; -+ goto out; -+ } -+ -+ nr_scparts = scpart_find_partmap(master, &scpart_map); -+ if (nr_scparts <= 0) { -+ pr_info("No any partitions was found in 'SC PART MAP'.\n"); -+ res = -ENOENT; -+ goto free; -+ } -+ -+ parts = kcalloc(of_get_child_count(ofpart_node), sizeof(*parts), -+ GFP_KERNEL); -+ if (!parts) { -+ res = -ENOMEM; -+ goto free; -+ } -+ -+ for_each_child_of_node(ofpart_node, pp) { -+ u32 scpart_id; -+ -+ if (of_property_read_u32(pp, "sercomm,scpart-id", &scpart_id)) -+ continue; -+ -+ for (n = 0 ; n < nr_scparts ; n++) -+ if ((scpart_map[n].part_id != ID_ALREADY_FOUND) && -+ (scpart_id == scpart_map[n].part_id)) -+ break; -+ if (n >= nr_scparts) -+ /* not match */ -+ continue; -+ -+ /* add the partition found in OF into MTD partition array */ -+ parts[nr_parts].offset = scpart_map[n].part_offs; -+ parts[nr_parts].size = scpart_map[n].part_bytes; -+ parts[nr_parts].of_node = pp; -+ -+ if (!of_property_read_string(pp, "label", &partname)) -+ parts[nr_parts].name = partname; -+ if (of_property_read_bool(pp, "read-only")) -+ parts[nr_parts].mask_flags |= MTD_WRITEABLE; -+ if (of_property_read_bool(pp, "lock")) -+ parts[nr_parts].mask_flags |= MTD_POWERUP_LOCK; -+ -+ /* mark as 'done' */ -+ scpart_map[n].part_id = ID_ALREADY_FOUND; -+ -+ nr_parts++; -+ } -+ -+ if (nr_parts > 0) { -+ *pparts = parts; -+ res = nr_parts; -+ } else -+ pr_info("No partition in OF matches partition ID with 'SC PART MAP'.\n"); -+ -+ of_node_put(pp); -+ -+free: -+ kfree(scpart_map); -+ if (res <= 0) -+ kfree(parts); -+ -+out: -+ return res; -+} -+ -+static const struct of_device_id scpart_parser_of_match_table[] = { -+ { .compatible = "sercomm,sc-partitions" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, scpart_parser_of_match_table); -+ -+static struct mtd_part_parser scpart_parser = { -+ .parse_fn = scpart_parse, -+ .name = "scpart", -+ .of_match_table = scpart_parser_of_match_table, -+}; -+module_mtd_part_parser(scpart_parser); -+ -+/* mtd parsers will request the module by parser name */ -+MODULE_ALIAS("scpart"); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("NOGUCHI Hiroshi <drvlabo@gmail.com>"); -+MODULE_AUTHOR("Mikhail Zhilkin <csharper2005@gmail.com>"); -+MODULE_DESCRIPTION("Sercomm partition parser"); |