--- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -27,6 +27,11 @@ config MTD_SPLIT_FIRMWARE_NAME depends on MTD_SPLIT_FIRMWARE default "firmware" +config MTD_UIMAGE_SPLIT + bool "Enable split support for firmware partitions containing a uImage" + depends on MTD_SPLIT_FIRMWARE + default y + source "drivers/mtd/mtdsplit/Kconfig" endmenu --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -680,6 +680,37 @@ mtd_pad_erasesize(struct mtd_info *mtd, return len; } +#define UBOOT_MAGIC 0x27051956 + +static void split_uimage(struct mtd_info *master, struct mtd_part *part) +{ + struct { + __be32 magic; + __be32 pad[2]; + __be32 size; + } hdr; + size_t len; + + if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr)) + return; + + if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC)) + return; + + len = be32_to_cpu(hdr.size) + 0x40; + len = mtd_pad_erasesize(master, part->offset, len); + if (len + master->erasesize > part->mtd.size) + return; + + if (config_enabled(CONFIG_MTD_SPLIT_UIMAGE_FW)) + pr_err("Dedicated partitioner didn't split firmware partition, please fill a bug report!\n"); + else + pr_warn("Support for built-in firmware splitter will be removed, please use CONFIG_MTD_SPLIT_UIMAGE_FW\n"); + + __mtd_add_partition(master, "rootfs", part->offset + len, + part->mtd.size - len, false); +} + #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else @@ -688,7 +719,14 @@ mtd_pad_erasesize(struct mtd_info *mtd, static void split_firmware(struct mtd_info *master, struct mtd_part *part) { - run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); + int ret; + + ret = run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE); + if (ret > 0) + return; + + if (config_enabled(CONFIG_MTD_UIMAGE_SPLIT)) + split_uimage(master, part); } void __weak arch_split_mtd_part(struct mtd_info *master, const char *name,