diff options
Diffstat (limited to 'drivers/mtd/parsers')
-rw-r--r-- | drivers/mtd/parsers/Kconfig | 16 | ||||
-rw-r--r-- | drivers/mtd/parsers/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/parsers/brcm_u-boot.c | 84 | ||||
-rw-r--r-- | drivers/mtd/parsers/cmdlinepart.c | 4 |
4 files changed, 100 insertions, 5 deletions
diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index b43df73927a0..aaa06050c9bc 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -20,6 +20,16 @@ config MTD_BCM63XX_PARTS This provides partition parsing for BCM63xx devices with CFE bootloaders. +config MTD_BRCM_U_BOOT + tristate "Broadcom's U-Boot partition parser" + depends on ARCH_BCM4908 || COMPILE_TEST + help + Broadcom uses a custom way of storing U-Boot environment variables. + They are placed inside U-Boot partition itself at unspecified offset. + It's possible to locate them by looking for a custom header with a + magic value. This driver does that and creates subpartitions for + each found environment variables block. + config MTD_CMDLINE_PARTS tristate "Command line partition table parsing" depends on MTD @@ -69,8 +79,8 @@ config MTD_OF_PARTS config MTD_OF_PARTS_BCM4908 bool "BCM4908 partitioning support" - depends on MTD_OF_PARTS && (ARCH_BCM4908 || COMPILE_TEST) - default ARCH_BCM4908 + depends on MTD_OF_PARTS && (ARCH_BCMBCA || COMPILE_TEST) + default ARCH_BCMBCA help This provides partitions parser for BCM4908 family devices that can have multiple "firmware" partitions. It takes care of @@ -78,7 +88,7 @@ config MTD_OF_PARTS_BCM4908 config MTD_OF_PARTS_LINKSYS_NS bool "Linksys Northstar partitioning support" - depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST) + depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCMBCA || COMPILE_TEST) default ARCH_BCM_5301X help This provides partitions parser for Linksys devices based on Broadcom diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index 2fcf0ab9e7da..23fa4de4016f 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o +obj-$(CONFIG_MTD_BRCM_U_BOOT) += brcm_u-boot.o obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ofpart-y += ofpart_core.o diff --git a/drivers/mtd/parsers/brcm_u-boot.c b/drivers/mtd/parsers/brcm_u-boot.c new file mode 100644 index 000000000000..7c338dc7b8f3 --- /dev/null +++ b/drivers/mtd/parsers/brcm_u-boot.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright © 2022 Rafał Miłecki <rafal@milecki.pl> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#define BRCM_U_BOOT_MAX_OFFSET 0x200000 +#define BRCM_U_BOOT_STEP 0x1000 + +#define BRCM_U_BOOT_MAX_PARTS 2 + +#define BRCM_U_BOOT_MAGIC 0x75456e76 /* uEnv */ + +struct brcm_u_boot_header { + __le32 magic; + __le32 length; +} __packed; + +static const char *names[BRCM_U_BOOT_MAX_PARTS] = { + "u-boot-env", + "u-boot-env-backup", +}; + +static int brcm_u_boot_parse(struct mtd_info *mtd, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct brcm_u_boot_header header; + struct mtd_partition *parts; + size_t bytes_read; + size_t offset; + int err; + int i = 0; + + parts = kcalloc(BRCM_U_BOOT_MAX_PARTS, sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + for (offset = 0; + offset < min_t(size_t, mtd->size, BRCM_U_BOOT_MAX_OFFSET); + offset += BRCM_U_BOOT_STEP) { + err = mtd_read(mtd, offset, sizeof(header), &bytes_read, (uint8_t *)&header); + if (err && !mtd_is_bitflip(err)) { + pr_err("Failed to read from %s at 0x%zx: %d\n", mtd->name, offset, err); + continue; + } + + if (le32_to_cpu(header.magic) != BRCM_U_BOOT_MAGIC) + continue; + + parts[i].name = names[i]; + parts[i].offset = offset; + parts[i].size = sizeof(header) + le32_to_cpu(header.length); + i++; + pr_info("offset:0x%zx magic:0x%08x BINGO\n", offset, header.magic); + + if (i == BRCM_U_BOOT_MAX_PARTS) + break; + } + + *pparts = parts; + + return i; +}; + +static const struct of_device_id brcm_u_boot_of_match_table[] = { + { .compatible = "brcm,u-boot" }, + {}, +}; +MODULE_DEVICE_TABLE(of, brcm_u_boot_of_match_table); + +static struct mtd_part_parser brcm_u_boot_mtd_parser = { + .parse_fn = brcm_u_boot_parse, + .name = "brcm_u-boot", + .of_match_table = brcm_u_boot_of_match_table, +}; +module_mtd_part_parser(brcm_u_boot_mtd_parser); + +MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/parsers/cmdlinepart.c b/drivers/mtd/parsers/cmdlinepart.c index 0ddff1a4b51f..b34856def816 100644 --- a/drivers/mtd/parsers/cmdlinepart.c +++ b/drivers/mtd/parsers/cmdlinepart.c @@ -193,7 +193,7 @@ static struct mtd_partition * newpart(char *s, parts[this_part].mask_flags = mask_flags; parts[this_part].add_flags = add_flags; if (name) - strlcpy(extra_mem, name, name_len + 1); + strscpy(extra_mem, name, name_len + 1); else sprintf(extra_mem, "Partition_%03d", this_part); parts[this_part].name = extra_mem; @@ -298,7 +298,7 @@ static int mtdpart_setup_real(char *s) this_mtd->parts = parts; this_mtd->num_parts = num_parts; this_mtd->mtd_id = (char*)(this_mtd + 1); - strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); + strscpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); /* link into chain */ this_mtd->next = partitions; |