From 68913c964fbff16f60e4a3fc7cd6f9737a2e5c2f Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Sun, 8 Sep 2024 17:16:52 +0800 Subject: [PATCH] uboot: support mainline FIT image Signed-off-by: Tianling Shen --- .../board/mediatek/common/boot_helper.c | 17 ++++++- .../board/mediatek/common/ubi_helper.c | 49 +++++++++++++++++++ .../board/mediatek/mt7981/bootmenu_emmc.c | 24 ++++++++- .../board/mediatek/mt7981/bootmenu_ubi.c | 2 +- .../board/mediatek/mt7986/bootmenu_emmc.c | 24 ++++++++- .../board/mediatek/mt7986/bootmenu_ubi.c | 2 +- .../board/mediatek/common/boot_helper.c | 6 ++- .../board/mediatek/common/bootmenu_mtd.c | 1 + .../board/mediatek/common/mmc_helper.c | 35 ++++++++++++- .../board/mediatek/common/mtd_helper.c | 48 ++++++++++++++++++ 10 files changed, 199 insertions(+), 9 deletions(-) diff --git a/uboot-mtk-20220606/board/mediatek/common/boot_helper.c b/uboot-mtk-20220606/board/mediatek/common/boot_helper.c index ccbcf2c31..ae4af10d5 100644 --- a/uboot-mtk-20220606/board/mediatek/common/boot_helper.c +++ b/uboot-mtk-20220606/board/mediatek/common/boot_helper.c @@ -25,8 +25,12 @@ int boot_from_mem(ulong data_load_addr) { char cmd[64]; + const char *bootconf = env_get("bootconf"); - snprintf(cmd, sizeof(cmd), "bootm 0x%lx", data_load_addr); + if (bootconf && strlen(bootconf) > 0) + snprintf(cmd, sizeof(cmd), "bootm 0x%lx#%s", data_load_addr, bootconf); + else + snprintf(cmd, sizeof(cmd), "bootm 0x%lx", data_load_addr); return run_command(cmd, 0); } @@ -57,7 +61,16 @@ static int _boot_from_mmc(u32 dev, struct mmc *mmc, u64 offset) #endif #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - size = fit_get_size((const void *)data_load_addr); + size = fit_get_totalsize((const void *)data_load_addr); + if (size <= 0x2000) { + /* Load FDT header into memory */ + ret = _mmc_read(mmc, offset, (void *)data_load_addr, size); + if (ret) + return ret; + + /* Read whole FIT image */ + size = fit_get_totalsize((const void *)data_load_addr); + } break; #endif default: diff --git a/uboot-mtk-20220606/board/mediatek/common/ubi_helper.c b/uboot-mtk-20220606/board/mediatek/common/ubi_helper.c index ea803a92f..1e5e2d812 100644 --- a/uboot-mtk-20220606/board/mediatek/common/ubi_helper.c +++ b/uboot-mtk-20220606/board/mediatek/common/ubi_helper.c @@ -511,6 +511,50 @@ out: return ret; } +static int write_ubi_fit_image(const void *data, size_t size, + struct mtd_info *mtd) +{ + int ret; + + ret = mount_ubi(mtd); + if (ret) + return ret; + + if (!find_ubi_volume("fit")) { + /* ubi is dirty, erase ubi and recreate volumes */ + umount_ubi(); + ret = mtd_erase_generic(mtd, 0, mtd->size); + if (ret) + return ret; + + ret = mount_ubi(mtd); + if (ret) + return ret; + + ret = create_ubi_volume("ubootenv", 0x100000, -1, false); + if (ret) + goto out; + + ret = create_ubi_volume("ubootenv2", 0x100000, -1, false); + if (ret) + goto out; + } + + /* Remove this volume first in case of no enough PEBs */ + remove_ubi_volume("rootfs_data"); + + ret = update_ubi_volume("fit", -1, data, size); + if (ret) + goto out; + + ret = create_ubi_volume("rootfs_data", 0, -1, true); + +out: + umount_ubi(); + + return ret; +} + static int boot_from_ubi(struct mtd_info *mtd) { ulong data_load_addr; @@ -528,6 +572,8 @@ static int boot_from_ubi(struct mtd_info *mtd) return ret; ret = read_ubi_volume("kernel", (void *)data_load_addr, 0); + if (ret == -ENODEV) + ret = read_ubi_volume("fit", (void *)data_load_addr, 0); if (ret) return ret; @@ -577,6 +623,9 @@ int ubi_upgrade_image(const void *data, size_t size) } else { ret = parse_image_ram(data, size, mtd->erasesize, &ii); + if (ii.header_type == HEADER_FIT) + return write_ubi_fit_image(data, size, mtd); + if (!ret && ii.type == IMAGE_UBI2) return mtd_update_generic(mtd, data, size); diff --git a/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_emmc.c b/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_emmc.c index 5bc504332..1df848b9d 100644 --- a/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_emmc.c +++ b/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_emmc.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,7 @@ DECLARE_GLOBAL_DATA_PTR; #define GPT_MAX_SIZE (34 * 512) #define PART_FIP_NAME "fip" +#define PART_PRODUCTION_NAME "production" #define PART_KERNEL_NAME "kernel" #define PART_ROOTFS_NAME "rootfs" @@ -145,6 +147,20 @@ int write_firmware(void *priv, const struct data_part_entry *dpe, u32 slot; #endif /* CONFIG_MTK_DUAL_BOOT */ + /* FIT image logic */ + if (genimg_get_format(data) == IMAGE_FORMAT_FIT) { + ret = write_part(PART_PRODUCTION_NAME, data, size, true); + if (ret) + return ret; + + /* Mark rootfs_data unavailable */ + rootfs_data_offs = (size + ROOTDEV_OVERLAY_ALIGN - 1) & + (~(ROOTDEV_OVERLAY_ALIGN - 1)); + erase_part(PART_PRODUCTION_NAME, rootfs_data_offs, SZ_512K); + + return ret; + } + ret = parse_tar_image(data, size, &kernel_data, &kernel_size, &rootfs_data, &rootfs_size); if (ret) @@ -273,7 +289,13 @@ int board_boot_default(void) return dual_boot_mmc(&mbd); #else - return boot_from_mmc_partition(EMMC_DEV_INDEX, 0, PART_KERNEL_NAME); + int ret; + + ret = boot_from_mmc_partition(EMMC_DEV_INDEX, 0, PART_KERNEL_NAME); + if (ret == -ENODEV) + return boot_from_mmc_partition(EMMC_DEV_INDEX, 0, PART_PRODUCTION_NAME); + + return ret; #endif /* CONFIG_MTK_DUAL_BOOT */ } diff --git a/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_ubi.c b/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_ubi.c index 24f7bea5f..34857f04e 100644 --- a/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_ubi.c +++ b/uboot-mtk-20220606/board/mediatek/mt7981/bootmenu_ubi.c @@ -91,7 +91,7 @@ static int write_flash_image(void *priv, const struct data_part_entry *dpe, static int erase_env(void *priv, const struct data_part_entry *dpe, const void *data, size_t size) { -#if !defined(CONFIG_MTK_SECURE_BOOT) && !defined(CONFIG_ENV_IS_NOWHERE) +#if !defined(CONFIG_MTK_SECURE_BOOT) && defined(CONFIG_ENV_IS_IN_MTD) struct mtd_info *mtd; ubi_probe_mtd_devices(); diff --git a/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_emmc.c b/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_emmc.c index 5bc504332..1df848b9d 100644 --- a/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_emmc.c +++ b/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_emmc.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,7 @@ DECLARE_GLOBAL_DATA_PTR; #define GPT_MAX_SIZE (34 * 512) #define PART_FIP_NAME "fip" +#define PART_PRODUCTION_NAME "production" #define PART_KERNEL_NAME "kernel" #define PART_ROOTFS_NAME "rootfs" @@ -145,6 +147,20 @@ int write_firmware(void *priv, const struct data_part_entry *dpe, u32 slot; #endif /* CONFIG_MTK_DUAL_BOOT */ + /* FIT image logic */ + if (genimg_get_format(data) == IMAGE_FORMAT_FIT) { + ret = write_part(PART_PRODUCTION_NAME, data, size, true); + if (ret) + return ret; + + /* Mark rootfs_data unavailable */ + rootfs_data_offs = (size + ROOTDEV_OVERLAY_ALIGN - 1) & + (~(ROOTDEV_OVERLAY_ALIGN - 1)); + erase_part(PART_PRODUCTION_NAME, rootfs_data_offs, SZ_512K); + + return ret; + } + ret = parse_tar_image(data, size, &kernel_data, &kernel_size, &rootfs_data, &rootfs_size); if (ret) @@ -273,7 +289,13 @@ int board_boot_default(void) return dual_boot_mmc(&mbd); #else - return boot_from_mmc_partition(EMMC_DEV_INDEX, 0, PART_KERNEL_NAME); + int ret; + + ret = boot_from_mmc_partition(EMMC_DEV_INDEX, 0, PART_KERNEL_NAME); + if (ret == -ENODEV) + return boot_from_mmc_partition(EMMC_DEV_INDEX, 0, PART_PRODUCTION_NAME); + + return ret; #endif /* CONFIG_MTK_DUAL_BOOT */ } diff --git a/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_ubi.c b/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_ubi.c index 24f7bea5f..34857f04e 100644 --- a/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_ubi.c +++ b/uboot-mtk-20220606/board/mediatek/mt7986/bootmenu_ubi.c @@ -91,7 +91,7 @@ static int write_flash_image(void *priv, const struct data_part_entry *dpe, static int erase_env(void *priv, const struct data_part_entry *dpe, const void *data, size_t size) { -#if !defined(CONFIG_MTK_SECURE_BOOT) && !defined(CONFIG_ENV_IS_NOWHERE) +#if !defined(CONFIG_MTK_SECURE_BOOT) && defined(CONFIG_ENV_IS_IN_MTD) struct mtd_info *mtd; ubi_probe_mtd_devices(); diff --git a/uboot-mtk-20230718-09eda825/board/mediatek/common/boot_helper.c b/uboot-mtk-20230718-09eda825/board/mediatek/common/boot_helper.c index ecd2258f5..2a53ef594 100644 --- a/uboot-mtk-20230718-09eda825/board/mediatek/common/boot_helper.c +++ b/uboot-mtk-20230718-09eda825/board/mediatek/common/boot_helper.c @@ -22,8 +22,12 @@ int boot_from_mem(ulong data_load_addr) { char cmd[64]; + const char *bootconf = env_get("bootconf"); - snprintf(cmd, sizeof(cmd), "bootm 0x%lx", data_load_addr); + if (bootconf && strlen(bootconf) > 0) + snprintf(cmd, sizeof(cmd), "bootm 0x%lx#%s", data_load_addr, bootconf); + else + snprintf(cmd, sizeof(cmd), "bootm 0x%lx", data_load_addr); return run_command(cmd, 0); } diff --git a/uboot-mtk-20230718-09eda825/board/mediatek/common/bootmenu_mtd.c b/uboot-mtk-20230718-09eda825/board/mediatek/common/bootmenu_mtd.c index 90ad66da5..5a0a1362a 100644 --- a/uboot-mtk-20230718-09eda825/board/mediatek/common/bootmenu_mtd.c +++ b/uboot-mtk-20230718-09eda825/board/mediatek/common/bootmenu_mtd.c @@ -331,6 +331,7 @@ static int erase_env(void *priv, const struct data_part_entry *dpe, return -EIO; ubi_remove_vol(CONFIG_ENV_UBI_VOLUME); + create_ubi_volume(CONFIG_ENV_UBI_VOLUME, CONFIG_ENV_SIZE, UBI_VID_OFFSET, false); ubi_exit(); #else struct mtd_info *mtd; diff --git a/uboot-mtk-20230718-09eda825/board/mediatek/common/mmc_helper.c b/uboot-mtk-20230718-09eda825/board/mediatek/common/mmc_helper.c index 0b5431a38..17f04960e 100644 --- a/uboot-mtk-20230718-09eda825/board/mediatek/common/mmc_helper.c +++ b/uboot-mtk-20230718-09eda825/board/mediatek/common/mmc_helper.c @@ -36,6 +36,7 @@ */ #define ROOTDEV_OVERLAY_ALIGN (64ULL * 1024ULL) +#define PART_PRODUCTION_NAME "production" #define PART_KERNEL_NAME "kernel" #define PART_ROOTFS_NAME "rootfs" @@ -691,7 +692,16 @@ static int _boot_from_mmc(struct mmc *mmc, u64 offset) #endif #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - size = fit_get_size((const void *)data_load_addr); + size = fit_get_totalsize((const void *)data_load_addr); + if (size <= 0x2000) { + /* Load FDT header into memory */ + ret = _mmc_read(mmc, offset, (void *)data_load_addr, size); + if (ret) + return ret; + + /* Read whole FIT image */ + size = fit_get_totalsize((const void *)data_load_addr); + } break; #endif default: @@ -965,10 +975,17 @@ static int mmc_dual_boot(u32 dev) int mmc_boot_image(u32 dev) { + int ret; + if (IS_ENABLED(CONFIG_MTK_DUAL_BOOT)) return mmc_dual_boot(dev); - return boot_from_mmc_partition(dev, 0, PART_KERNEL_NAME); + ret = boot_from_mmc_partition(dev, 0, PART_KERNEL_NAME); + if (ret == -ENOENT) { + return boot_from_mmc_partition(dev, 0, PART_PRODUCTION_NAME); + } + + return ret; } int mmc_upgrade_image(u32 dev, const void *data, size_t size) @@ -980,6 +997,20 @@ int mmc_upgrade_image(u32 dev, const void *data, size_t size) u32 slot; int ret; + /* FIT image logic */ + if (genimg_get_format(data) == IMAGE_FORMAT_FIT) { + ret = mmc_write_part(dev, 0, PART_PRODUCTION_NAME, data, size, true); + if (ret) + return ret; + + /* Mark rootfs_data unavailable */ + rootfs_data_offs = (size + ROOTDEV_OVERLAY_ALIGN - 1) & + (~(ROOTDEV_OVERLAY_ALIGN - 1)); + mmc_erase_part(dev, 0, PART_PRODUCTION_NAME, rootfs_data_offs, SZ_512K); + + return ret; + } + if (IS_ENABLED(CONFIG_MTK_DUAL_BOOT)) { slot = dual_boot_get_next_slot(); printf("Upgrading image slot %u ...\n", slot); diff --git a/uboot-mtk-20230718-09eda825/board/mediatek/common/mtd_helper.c b/uboot-mtk-20230718-09eda825/board/mediatek/common/mtd_helper.c index b40e5b399..87b8b3741 100644 --- a/uboot-mtk-20230718-09eda825/board/mediatek/common/mtd_helper.c +++ b/uboot-mtk-20230718-09eda825/board/mediatek/common/mtd_helper.c @@ -29,6 +29,7 @@ #define PART_UBI_NAME "ubi" #define PART_FIRMWARE_NAME "firmware" +#define PART_FIT_NAME "fit" #define PART_KERNEL_NAME "kernel" #define PART_ROOTFS_NAME "rootfs" #define PART_ROOTFS_DATA_NAME "rootfs_data" @@ -634,6 +635,48 @@ static int read_ubi_volume(const char *volume, void *buff, size_t size) return ubi_volume_read((char *)volume, buff, size); } +static int write_ubi_fit_image(const void *data, size_t size, + struct mtd_info *mtd) +{ + int ret; + + ret = mount_ubi(mtd, true); + if (ret) + return ret; + + if (!ubi_find_volume(PART_FIT_NAME)) { + /* ubi is dirty, erase ubi and recreate volumes */ + ubi_exit(); + ret = mtd_erase_skip_bad(mtd, 0, size, mtd->size, NULL, NULL, true); + if (ret) + return ret; + + ret = mount_ubi(mtd, true); + if (ret) + return ret; + + ret = create_ubi_volume("ubootenv", 0x100000, -1, false); + if (ret) + goto out; + + ret = create_ubi_volume("ubootenv2", 0x100000, -1, false); + if (ret) + goto out; + } + + /* Remove this volume first in case of no enough PEBs */ + remove_ubi_volume(PART_ROOTFS_DATA_NAME); + + ret = update_ubi_volume(PART_FIT_NAME, -1, data, size); + if (ret) + goto out; + + ret = create_ubi_volume(PART_ROOTFS_DATA_NAME, 0, -1, true); + +out: + return ret; +} + #ifdef CONFIG_MEDIATEK_MULTI_MTD_LAYOUT static int write_ubi2_tar_image_separate(const void *data, size_t size, struct mtd_info *mtd_kernel, struct mtd_info *mtd_rootfs) @@ -988,6 +1031,8 @@ static int boot_from_ubi(struct mtd_info *mtd) return ret; ret = read_ubi_volume(PART_KERNEL_NAME, (void *)data_load_addr, 0); + if (ret == ENODEV) + ret = read_ubi_volume(PART_FIT_NAME, (void *)data_load_addr, 0); if (ret) return ret; @@ -1067,6 +1112,9 @@ int mtd_upgrade_image(const void *data, size_t size) } else { ret = parse_image_ram(data, size, mtd->erasesize, &ii); + if (ii.header_type == HEADER_FIT) + return write_ubi_fit_image(data, size, mtd); + if (!ret && ii.type == IMAGE_UBI2 && !IS_ENABLED(CONFIG_MTK_DUAL_BOOT)) return mtd_update_generic(mtd, data, size, true);