diff options
Diffstat (limited to 'target/linux/generic')
3 files changed, 99 insertions, 0 deletions
diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig index 3b7e23af33..4832b8d9e4 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Kconfig @@ -25,6 +25,18 @@ config MTD_SPLIT_BCM_WFI_FW depends on MTD_SPLIT_SUPPORT select MTD_SPLIT +config MTD_SPLIT_CFE_BOOTFS + bool "Parser finding rootfs appended to the CFE bootfs" + depends on MTD_SPLIT_SUPPORT && ARCH_BCM4908 + select MTD_SPLIT + help + cferom on BCM4908 (and bcm63xx) uses JFFS2 bootfs partition + for storing kernel, cferam and some device specific files. + There isn't any straight way of storing rootfs so it gets + appended to the JFFS2 bootfs partition. Kernel needs to find + it and run init from it. This parser is responsible for + finding appended rootfs. + config MTD_SPLIT_SEAMA_FW bool "Seama firmware parser" depends on MTD_SPLIT_SUPPORT diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile index 8671628e7c..9217d8f64f 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_MTD_SPLIT) += mtdsplit.o obj-$(CONFIG_MTD_SPLIT_BCM_WFI_FW) += mtdsplit_bcm_wfi.o +obj-$(CONFIG_MTD_SPLIT_CFE_BOOTFS) += mtdsplit_cfe_bootfs.o obj-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o obj-$(CONFIG_MTD_SPLIT_SQUASHFS_ROOT) += mtdsplit_squashfs.o obj-$(CONFIG_MTD_SPLIT_UIMAGE_FW) += mtdsplit_uimage.o diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c new file mode 100644 index 0000000000..5c8a5e1b9b --- /dev/null +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> + */ + +#include <linux/init.h> +#include <linux/jffs2.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/of.h> +#include <linux/slab.h> + +#include "mtdsplit.h" + +#define je16_to_cpu(x) ((x).v16) +#define je32_to_cpu(x) ((x).v32) + +#define NR_PARTS 1 + +static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +{ + struct jffs2_raw_dirent node; + enum mtdsplit_part_type type; + struct mtd_partition *parts; + size_t rootfs_offset; + size_t retlen; + size_t offset; + int err; + + /* Don't parse backup partitions */ + if (strcmp(mtd->name, "firmware")) + return -EINVAL; + + /* Find the end of JFFS2 bootfs partition */ + offset = 0; + do { + err = mtd_read(mtd, offset, sizeof(node), &retlen, (void *)&node); + if (err || retlen != sizeof(node)) + break; + + if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK) + break; + + offset += je32_to_cpu(node.totlen); + offset = (offset + 0x3) & ~0x3; + } while (offset < mtd->size); + + /* Find rootfs partition that follows the bootfs */ + err = mtd_find_rootfs_from(mtd, mtd->erasesize, mtd->size, &rootfs_offset, &type); + if (err) + return err; + + parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + if (type == MTDSPLIT_PART_TYPE_UBI) + parts[0].name = UBI_PART_NAME; + else + parts[0].name = ROOTFS_PART_NAME; + parts[0].offset = rootfs_offset; + parts[0].size = mtd->size - rootfs_offset; + + *pparts = parts; + + return NR_PARTS; +} + +static const struct of_device_id mtdsplit_cfe_bootfs_of_match_table[] = { + { .compatible = "brcm,bcm4908-firmware" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mtdsplit_cfe_bootfs_of_match_table); + +static struct mtd_part_parser mtdsplit_cfe_bootfs_parser = { + .owner = THIS_MODULE, + .name = "cfe-bootfs", + .of_match_table = mtdsplit_cfe_bootfs_of_match_table, + .parse_fn = mtdsplit_cfe_bootfs_parse, +}; + +module_mtd_part_parser(mtdsplit_cfe_bootfs_parser); |