From: Rafał Miłecki Date: Wed, 20 Jan 2021 15:49:26 +0000 (+0100) Subject: kernel: add parser finding rootfs after CFE bootfs X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=20b4f77bb69cdded143c15ce962ccd3483bfe77a;p=openwrt%2Fstaging%2Fdangole.git kernel: add parser finding rootfs after CFE bootfs It's required for BCM4908. It cannot use "bcm-wfi-fw" parser because that one requires *two* JFFS2 partitions which is untested / unsupported on the BCM4908 architecture. With a single JFFS2 partition "bcm-wfi-fw" parser will: 1. Fail to find "vmlinux.lz" as it doesn't follow "1-openwrt" file 2. Create partitions that don't precisely match bootfs layout The new parser is described in details in the MTD_SPLIT_CFE_BOOTFS symbol help message. Signed-off-by: Rafał Miłecki --- diff --git a/target/linux/bcm4908/config-5.4 b/target/linux/bcm4908/config-5.4 index 3dfa7b21dc..d13753c49d 100644 --- a/target/linux/bcm4908/config-5.4 +++ b/target/linux/bcm4908/config-5.4 @@ -138,7 +138,8 @@ CONFIG_MTD_NAND_BRCMNAND=y CONFIG_MTD_NAND_CORE=y CONFIG_MTD_NAND_ECC_SW_HAMMING=y CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y +CONFIG_MTD_SPLIT_CFE_BOOTFS=y +# CONFIG_MTD_SPLIT_SQUASHFS_ROOT is not set CONFIG_MTD_UBI=y CONFIG_MTD_UBI_BEB_LIMIT=20 CONFIG_MTD_UBI_BLOCK=y 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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);