From f4cac999821764de726978549406614b6726c8fa Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:14 +0530 Subject: [PATCH 01/20] configs: fwu: remove FWU configs for metadata V2 support Support is to be added in the following commits for the FWU metadata version 2. Disable the FWU feature on platforms that enable it for the V2 addition work. Signed-off-by: Sughosh Ganu Reviewed-by: Ilias Apalodimas Tested-by: Michal Simek --- configs/corstone1000_defconfig | 2 -- configs/sandbox64_defconfig | 1 - configs/synquacer_developerbox_defconfig | 4 ---- 3 files changed, 7 deletions(-) diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig index 8b2f77f6485..29d7550afb6 100644 --- a/configs/corstone1000_defconfig +++ b/configs/corstone1000_defconfig @@ -24,7 +24,6 @@ CONFIG_LOGLEVEL=7 CONFIG_BOARD_LATE_INIT=y CONFIG_SYS_PROMPT="corstone1000# " # CONFIG_CMD_CONSOLE is not set -CONFIG_CMD_FWU_METADATA=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_XIMG is not set CONFIG_CMD_GPT=y @@ -67,4 +66,3 @@ CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_IGNORE_OSINDICATIONS=y -CONFIG_FWU_MULTI_BANK_UPDATE=y diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 3be9a00a857..7e8200e70cb 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -272,7 +272,6 @@ CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y -CONFIG_FWU_MULTI_BANK_UPDATE=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y diff --git a/configs/synquacer_developerbox_defconfig b/configs/synquacer_developerbox_defconfig index 2a0407de407..616d4100744 100644 --- a/configs/synquacer_developerbox_defconfig +++ b/configs/synquacer_developerbox_defconfig @@ -11,14 +11,12 @@ CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="synquacer-sc2a11-developerbox" CONFIG_SYS_LOAD_ADDR=0x80000000 CONFIG_TARGET_DEVELOPERBOX=y -CONFIG_FWU_NUM_IMAGES_PER_BANK=1 CONFIG_AHCI=y CONFIG_FIT=y CONFIG_SYS_BOOTM_LEN=0x800000 CONFIG_BOOTSTAGE_STASH_SIZE=4096 CONFIG_HUSH_PARSER=y CONFIG_SYS_MAXARGS=128 -CONFIG_CMD_FWU_METADATA=y CONFIG_CMD_IMLS=y CONFIG_CMD_ERASEENV=y CONFIG_CMD_NVEDIT_EFI=y @@ -53,7 +51,6 @@ CONFIG_DFU_TFTP=y CONFIG_DFU_MTD=y CONFIG_DFU_RAM=y CONFIG_DFU_SF=y -CONFIG_FWU_MDATA_MTD=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_SYNQUACER=y CONFIG_MMC_SDHCI=y @@ -96,4 +93,3 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_IGNORE_OSINDICATIONS=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y -CONFIG_FWU_MULTI_BANK_UPDATE=y From d99127a69ebf65cd35c33896ea6f4b45b77b8c82 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:15 +0530 Subject: [PATCH 02/20] tools: mkfwumdata: fix the size parameter to the fwrite call The fwrite call returns the number of bytes transferred as part of the write only when the size parameter is 1. Pass the size parameter to the library call as 1 so that the correct number of bytes transferred are returned. Fixes: fdd56bfd3ad ("tools: Add mkfwumdata tool for FWU metadata image") Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- tools/mkfwumdata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index 9732a8ddc5a..b2d90ca7c94 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -259,7 +259,7 @@ fwu_make_mdata(size_t images, size_t banks, char *uuids[], char *output) goto done_make; } - ret = fwrite(mobj->mdata, mobj->size, 1, file); + ret = fwrite(mobj->mdata, 1, mobj->size, file); if (ret != mobj->size) ret = -errno; else From f42a61f57f69c9fac1e21cbfde3f40ebdadc518b Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:16 +0530 Subject: [PATCH 03/20] drivers: fwu: add the size parameter to the metadata access API's In version 2 of the metadata structure, the size of the structure cannot be determined statically at build time. The structure is now broken into the top level structure which contains a field indicating the total size of the structure. Add a size parameter to the metadata access API functions to indicate the number of bytes to be accessed. This is then used to either read the entire structure, or only the top level structure. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- drivers/fwu-mdata/fwu-mdata-uclass.c | 10 ++++++---- drivers/fwu-mdata/gpt_blk.c | 23 +++++++++++++---------- drivers/fwu-mdata/raw_mtd.c | 10 ++++++---- include/fwu.h | 14 ++++++++++---- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c index 0a8edaaa418..145479bab0f 100644 --- a/drivers/fwu-mdata/fwu-mdata-uclass.c +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c @@ -20,7 +20,8 @@ * * Return: 0 if OK, -ve on error */ -int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary, + uint32_t size) { const struct fwu_mdata_ops *ops = device_get_ops(dev); @@ -29,7 +30,7 @@ int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) return -ENOSYS; } - return ops->read_mdata(dev, mdata, primary); + return ops->read_mdata(dev, mdata, primary, size); } /** @@ -37,7 +38,8 @@ int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) * * Return: 0 if OK, -ve on error */ -int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary, + uint32_t size) { const struct fwu_mdata_ops *ops = device_get_ops(dev); @@ -46,7 +48,7 @@ int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) return -ENOSYS; } - return ops->write_mdata(dev, mdata, primary); + return ops->write_mdata(dev, mdata, primary, size); } UCLASS_DRIVER(fwu_mdata) = { diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c index c7284916c4e..97eac3611f7 100644 --- a/drivers/fwu-mdata/gpt_blk.c +++ b/drivers/fwu-mdata/gpt_blk.c @@ -81,15 +81,14 @@ static int gpt_get_mdata_disk_part(struct blk_desc *desc, return -ENOENT; } -static int gpt_read_write_mdata(struct blk_desc *desc, - struct fwu_mdata *mdata, - u8 access, u32 part_num) +static int gpt_read_write_mdata(struct blk_desc *desc, struct fwu_mdata *mdata, + u8 access, u32 part_num, u32 size) { int ret; u32 len, blk_start, blkcnt; struct disk_partition info; - ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1, + ALLOC_CACHE_ALIGN_BUFFER_PAD(u8, mdata_aligned, size, desc->blksz); if (!mdata) @@ -101,7 +100,7 @@ static int gpt_read_write_mdata(struct blk_desc *desc, return -ENOENT; } - len = sizeof(*mdata); + len = size; blkcnt = BLOCK_CNT(len, desc); if (blkcnt > info.size) { log_debug("Block count exceeds FWU metadata partition size\n"); @@ -114,7 +113,7 @@ static int gpt_read_write_mdata(struct blk_desc *desc, log_debug("Error reading FWU metadata from the device\n"); return -EIO; } - memcpy(mdata, mdata_aligned, sizeof(struct fwu_mdata)); + memcpy(mdata, mdata_aligned, size); } else { if (blk_dwrite(desc, blk_start, blkcnt, mdata) != blkcnt) { log_debug("Error writing FWU metadata to the device\n"); @@ -164,7 +163,7 @@ static int fwu_mdata_gpt_blk_probe(struct udevice *dev) } static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, - bool primary) + bool primary, u32 size) { struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); @@ -177,11 +176,13 @@ static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, } return gpt_read_write_mdata(desc, mdata, MDATA_READ, - primary ? g_mdata_part[0] : g_mdata_part[1]); + primary ? + g_mdata_part[0] : g_mdata_part[1], + size); } static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, - bool primary) + bool primary, u32 size) { struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); @@ -194,7 +195,9 @@ static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, } return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, - primary ? g_mdata_part[0] : g_mdata_part[1]); + primary ? + g_mdata_part[0] : g_mdata_part[1], + size); } static const struct fwu_mdata_ops fwu_gpt_blk_ops = { diff --git a/drivers/fwu-mdata/raw_mtd.c b/drivers/fwu-mdata/raw_mtd.c index 17e45179738..9f3f1dc2131 100644 --- a/drivers/fwu-mdata/raw_mtd.c +++ b/drivers/fwu-mdata/raw_mtd.c @@ -97,22 +97,24 @@ lock: return ret; } -static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) +static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, + bool primary, u32 size) { struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); struct mtd_info *mtd = mtd_priv->mtd; u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset; - return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_READ); + return mtd_io_data(mtd, offs, size, mdata, FWU_MTD_READ); } -static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary) +static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, + bool primary, u32 size) { struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); struct mtd_info *mtd = mtd_priv->mtd; u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset; - return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_WRITE); + return mtd_io_data(mtd, offs, size, mdata, FWU_MTD_WRITE); } static int flash_partition_offset(struct udevice *dev, const char *part_name, fdt_addr_t *offset) diff --git a/include/fwu.h b/include/fwu.h index eb5638f4f3a..1815bd0064c 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -32,20 +32,24 @@ struct fwu_mdata_ops { * @dev: FWU metadata device * @mdata: Output FWU mdata read * @primary: If primary or secondary copy of metadata is to be read + * @size: Size in bytes of the metadata to be read * * Return: 0 if OK, -ve on error */ - int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool primary); + int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, + bool primary, uint32_t size); /** * write_mdata() - Write the given FWU metadata copy * @dev: FWU metadata device * @mdata: Copy of the FWU metadata to write * @primary: If primary or secondary copy of metadata is to be written + * @size: Size in bytes of the metadata to be written * * Return: 0 if OK, -ve on error */ - int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool primary); + int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, + bool primary, uint32_t size); }; #define FWU_MDATA_VERSION 0x1 @@ -80,12 +84,14 @@ struct fwu_mdata_ops { /** * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() */ -int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary); +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, + bool primary, uint32_t size); /** * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() */ -int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary); +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, + bool primary, uint32_t size); /** * fwu_get_mdata() - Read, verify and return the FWU metadata From e67c0b76d8e80856cd88256ef1d6ac5da904f503 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:17 +0530 Subject: [PATCH 04/20] drivers: fwu: mtd: allocate buffer for image info dynamically The FWU metadata access driver for MTD partitioned devices currently uses a statically allocated array for storing the updatable image information. This array depends on the number of banks and images per bank. With migration of the FWU metadata to version 2, these parameters are now obtained at runtime from the metadata. Make changes to the FWU metadata access driver for MTD devices to allocate memory for the image information dynamically in the driver's probe function, after having obtained the number of banks and images per bank by reading the metadata. Move the image information as part of the driver's private structure, instead of using a global variable. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- drivers/fwu-mdata/raw_mtd.c | 68 +++++++++++++++++++++++-------------- include/fwu.h | 9 +++++ 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/drivers/fwu-mdata/raw_mtd.c b/drivers/fwu-mdata/raw_mtd.c index 9f3f1dc2131..78a709f766c 100644 --- a/drivers/fwu-mdata/raw_mtd.c +++ b/drivers/fwu-mdata/raw_mtd.c @@ -12,22 +12,11 @@ #include #include -/* Internal helper structure to move data around */ -struct fwu_mdata_mtd_priv { - struct mtd_info *mtd; - char pri_label[50]; - char sec_label[50]; - u32 pri_offset; - u32 sec_offset; -}; - enum fwu_mtd_op { FWU_MTD_READ, FWU_MTD_WRITE, }; -extern struct fwu_mtd_image_info fwu_mtd_images[]; - static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) { return !do_div(size, mtd->erasesize); @@ -134,7 +123,7 @@ static int flash_partition_offset(struct udevice *dev, const char *part_name, fd return (int)size; } -static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) +static int get_fwu_mdata_dev(struct udevice *dev) { struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); const fdt32_t *phandle_p = NULL; @@ -144,8 +133,6 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) fdt_addr_t offset; int ret, size; u32 phandle; - ofnode bank; - int off_img; /* Find the FWU mdata storage device */ phandle_p = ofnode_get_property(dev_ofnode(dev), @@ -199,8 +186,28 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) return ret; mtd_priv->sec_offset = offset; - off_img = 0; + return 0; +} +static int fwu_mtd_image_info_populate(struct udevice *dev, u8 nbanks, + u16 nimages) +{ + struct fwu_mtd_image_info *mtd_images; + struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev); + struct udevice *mtd_dev = mtd_priv->mtd->dev; + fdt_addr_t offset; + ofnode bank; + int off_img; + u32 total_images; + + total_images = nbanks * nimages; + mtd_priv->fwu_mtd_images = malloc(sizeof(struct fwu_mtd_image_info) * + total_images); + if (!mtd_priv->fwu_mtd_images) + return -ENOMEM; + + off_img = 0; + mtd_images = mtd_priv->fwu_mtd_images; ofnode_for_each_subnode(bank, dev_ofnode(dev)) { int bank_num, bank_offset, bank_size; const char *bank_name; @@ -219,8 +226,7 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) int image_num, image_offset, image_size; const char *uuid; - if (off_img == CONFIG_FWU_NUM_BANKS * - CONFIG_FWU_NUM_IMAGES_PER_BANK) { + if (off_img == total_images) { log_err("DT provides more images than configured!\n"); break; } @@ -230,11 +236,11 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) ofnode_read_u32(image, "offset", &image_offset); ofnode_read_u32(image, "size", &image_size); - fwu_mtd_images[off_img].start = bank_offset + image_offset; - fwu_mtd_images[off_img].size = image_size; - fwu_mtd_images[off_img].bank_num = bank_num; - fwu_mtd_images[off_img].image_num = image_num; - strcpy(fwu_mtd_images[off_img].uuidbuf, uuid); + mtd_images[off_img].start = bank_offset + image_offset; + mtd_images[off_img].size = image_size; + mtd_images[off_img].bank_num = bank_num; + mtd_images[off_img].image_num = image_num; + strcpy(mtd_images[off_img].uuidbuf, uuid); log_debug("\tImage%d: %s @0x%x\n\n", image_num, uuid, bank_offset + image_offset); off_img++; @@ -246,8 +252,21 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev) static int fwu_mdata_mtd_probe(struct udevice *dev) { - /* Ensure the metadata can be read. */ - return fwu_get_mdata(NULL); + u8 nbanks; + u16 nimages; + int ret; + + ret = get_fwu_mdata_dev(dev); + if (ret) + return ret; + + nbanks = CONFIG_FWU_NUM_BANKS; + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; + ret = fwu_mtd_image_info_populate(dev, nbanks, nimages); + if (ret) + return ret; + + return 0; } static struct fwu_mdata_ops fwu_mtd_ops = { @@ -266,6 +285,5 @@ U_BOOT_DRIVER(fwu_mdata_mtd) = { .of_match = fwu_mdata_ids, .ops = &fwu_mtd_ops, .probe = fwu_mdata_mtd_probe, - .of_to_plat = fwu_mdata_mtd_of_to_plat, .priv_auto = sizeof(struct fwu_mdata_mtd_priv), }; diff --git a/include/fwu.h b/include/fwu.h index 1815bd0064c..6c4d218e13a 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -26,6 +26,15 @@ struct fwu_mtd_image_info { char uuidbuf[UUID_STR_LEN + 1]; }; +struct fwu_mdata_mtd_priv { + struct mtd_info *mtd; + char pri_label[50]; + char sec_label[50]; + u32 pri_offset; + u32 sec_offset; + struct fwu_mtd_image_info *fwu_mtd_images; +}; + struct fwu_mdata_ops { /** * read_mdata() - Populate the asked FWU metadata copy From 48d9325303d97751e47c6f8abed2cd59a0edc2a6 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:18 +0530 Subject: [PATCH 05/20] fwu: metadata: add support for version 2 of the structure Add support for version 2 of the FWU metadata structure. The top level structure is kept separate through a config symbol. Most of the fields, primarily used for providing information on updatable images are common across the two versions. Also change a few existing structure members used for image identification to reflect the fact that these are GUIDs, and not UUIDs. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- include/fwu_mdata.h | 71 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h index 56189e2f40a..d2521f39b42 100644 --- a/include/fwu_mdata.h +++ b/include/fwu_mdata.h @@ -11,7 +11,7 @@ /** * struct fwu_image_bank_info - firmware image information - * @image_uuid: Guid value of the image in this bank + * @image_guid: Guid value of the image in this bank * @accepted: Acceptance status of the image * @reserved: Reserved * @@ -20,15 +20,15 @@ * acceptance status */ struct fwu_image_bank_info { - efi_guid_t image_uuid; + efi_guid_t image_guid; uint32_t accepted; uint32_t reserved; } __packed; /** * struct fwu_image_entry - information for a particular type of image - * @image_type_uuid: Guid value for identifying the image type - * @location_uuid: Guid of the storage volume where the image is located + * @image_type_guid: Guid value for identifying the image type + * @location_guid: Guid of the storage volume where the image is located * @img_bank_info: Array containing properties of images * * This structure contains information on various types of updatable @@ -36,11 +36,35 @@ struct fwu_image_bank_info { * information per bank. */ struct fwu_image_entry { - efi_guid_t image_type_uuid; - efi_guid_t location_uuid; + efi_guid_t image_type_guid; + efi_guid_t location_guid; struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS]; } __packed; +/** + * struct fwu_fw_store_desc - FWU updatable image information + * @num_banks: Number of firmware banks + * @num_images: Number of images per bank + * @img_entry_size: The size of the img_entry array + * @bank_info_entry_size: The size of the img_bank_info array + * @img_entry: Array of image entries each giving information on a image + * + * This image descriptor structure contains information on the number of + * updatable banks and images per bank. It also gives the total sizes of + * the fwu_image_entry and fwu_image_bank_info arrays. This structure is + * only present in version 2 of the metadata structure. + */ +struct fwu_fw_store_desc { + uint8_t num_banks; + uint8_t reserved; + uint16_t num_images; + uint16_t img_entry_size; + uint16_t bank_info_entry_size; + + struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; +} __packed; + +#if defined(CONFIG_FWU_MDATA_V1) /** * struct fwu_mdata - FWU metadata structure for multi-bank updates * @crc32: crc32 value for the FWU metadata @@ -65,4 +89,39 @@ struct fwu_mdata { struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK]; } __packed; +#else /* CONFIG_FWU_MDATA_V1 */ +/** + * struct fwu_mdata - FWU metadata structure for multi-bank updates + * @crc32: crc32 value for the FWU metadata + * @version: FWU metadata version + * @active_index: Index of the bank currently used for booting images + * @previous_active_inde: Index of the bank used before the current bank + * being used for booting + * @metadata_size: Size of the entire metadata structure, including the + * image descriptors + * @desc_offset: The offset from the start of this structure where the + * image descriptor structure starts. 0 if absent + * @bank_state: State of each bank, valid, invalid or accepted + * @fw_desc: The structure describing the FWU updatable images + * + * This is the top level structure used to store all information for performing + * multi bank updates on the platform. This contains info on the bank being + * used to boot along with the information on state of individual banks. + */ +struct fwu_mdata { + uint32_t crc32; + uint32_t version; + uint32_t active_index; + uint32_t previous_active_index; + uint32_t metadata_size; + uint16_t desc_offset; + uint16_t reserved1; + uint8_t bank_state[4]; + uint32_t reserved2; + + // struct fwu_fw_store_desc fw_desc; +} __packed; + +#endif /* CONFIG_FWU_MDATA_V1 */ + #endif /* _FWU_MDATA_H_ */ From 1cafc2ab8d1e9da4d253442aa719895131c0901e Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:19 +0530 Subject: [PATCH 06/20] fwu: metadata: add a version agnostic structure The FWU specification now has two versions of the FWU metadata structure, and both are to be supported. Introduce a version agnostic structure for storing information about the FWU updatable images. This allows for a split of common version agnostic FWU code and version specific code. The version specific code is then responsible for arranging the data as per the corresponding metadata structure before it gets written to the metadata partitions. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- include/fwu.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/fwu.h b/include/fwu.h index 6c4d218e13a..e681e910274 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -35,6 +36,23 @@ struct fwu_mdata_mtd_priv { struct fwu_mtd_image_info *fwu_mtd_images; }; +struct fwu_data { + uint32_t crc32; + uint32_t version; + uint32_t active_index; + uint32_t previous_active_index; + uint32_t metadata_size; + uint32_t boot_index; + uint32_t num_banks; + uint32_t num_images; + uint8_t bank_state[4]; + bool trial_state; + + struct fwu_mdata *fwu_mdata; + + struct fwu_image_entry fwu_images[CONFIG_FWU_NUM_IMAGES_PER_BANK]; +}; + struct fwu_mdata_ops { /** * read_mdata() - Populate the asked FWU metadata copy From fba5b3fa7c473fb356ce206ad2dbfe1c3917edfa Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:20 +0530 Subject: [PATCH 07/20] fwu: metadata: add functions for handling version specific metadata fields Support is being added in U-Boot for version 2 of the FWU metadata. Support for this version is to co-exist with version 1 support. To achieve this, a common, version agnostic structure has been added to keep information provided by the FWU metadata structure. Add API's to handle the version specific FWU metadata fields. The version agnostic structure gets initialized at boot by reading the FWU metadata. Updates to the FWU metadata result in the API's getting called to populate the version specific fields of the strucure, before the metadata gets written to the storage media. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- include/fwu.h | 57 +++++++++ lib/fwu_updates/fwu_v1.c | 167 +++++++++++++++++++++++++ lib/fwu_updates/fwu_v2.c | 260 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 484 insertions(+) create mode 100644 lib/fwu_updates/fwu_v1.c create mode 100644 lib/fwu_updates/fwu_v2.c diff --git a/include/fwu.h b/include/fwu.h index e681e910274..082b5481d1e 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -313,4 +313,61 @@ int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd); */ int fwu_mtd_get_alt_num(efi_guid_t *image_guid, u8 *alt_num, const char *mtd_dev); +/** + * fwu_populate_mdata_image_info() - Populate the image information + * of the metadata + * @data: Version agnostic FWU metadata information + * + * Populate the image information in the FWU metadata by copying it + * from the version agnostic structure. This is done before the + * metadata gets written to the storage media. + * + * Return: None + */ +void fwu_populate_mdata_image_info(struct fwu_data *data); + +/** + * fwu_get_mdata_size() - Get the FWU metadata size + * @mdata_size: Size of the metadata structure + * + * Get the size of the FWU metadata from the structure. This is later used + * to allocate memory for the structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_get_mdata_size(uint32_t *mdata_size); + +/** + * fwu_state_machine_updates() - Update FWU state of the platform + * @trial_state: Is platform transitioning into Trial State + * @update_index: Bank number to which images have been updated + * + * On successful completion of updates, transition the platform to + * either Trial State or Regular State. + * + * To transition the platform to Trial State, start the + * TrialStateCtr counter, followed by setting the value of bank_state + * field of the metadata to Valid state(applicable only in version 2 + * of metadata). + * + * In case, the platform is to transition directly to Regular State, + * update the bank_state field of the metadata to Accepted + * state(applicable only in version 2 of metadata). + * + * Return: 0 if OK, -ve on error + */ +int fwu_state_machine_updates(bool trial_state, uint32_t update_index); + +/** + * fwu_init() - FWU specific initialisations + * + * Carry out some FWU specific initialisations including allocation + * of memory for the metadata copies, and reading the FWU metadata + * copies into the allocated memory. The metadata fields are then + * copied into a version agnostic structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_init(void); + #endif /* _FWU_H_ */ diff --git a/lib/fwu_updates/fwu_v1.c b/lib/fwu_updates/fwu_v1.c new file mode 100644 index 00000000000..efb8d515008 --- /dev/null +++ b/lib/fwu_updates/fwu_v1.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include + +#include + +#define FWU_MDATA_VERSION 0x1U + +static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank) +{ + u32 i; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_bank_info; + + img_entry = &mdata->img_entry[0]; + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { + img_bank_info = &img_entry[i].img_bank_info[bank]; + if (!img_bank_info->accepted) { + return 1; + } + } + + return 0; +} + +static void fwu_data_init(void) +{ + size_t image_info_size; + void *dst_img_info, *src_img_info; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + data->crc32 = mdata->crc32; + data->version = mdata->version; + data->active_index = mdata->active_index; + data->previous_active_index = mdata->previous_active_index; + + data->metadata_size = sizeof(struct fwu_mdata); + data->num_banks = CONFIG_FWU_NUM_BANKS; + data->num_images = CONFIG_FWU_NUM_IMAGES_PER_BANK; + fwu_plat_get_bootidx(&data->boot_index); + data->trial_state = fwu_check_trial_state(mdata, data->boot_index); + + src_img_info = &mdata->img_entry[0]; + dst_img_info = &data->fwu_images[0]; + image_info_size = sizeof(data->fwu_images); + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +static int fwu_trial_state_update(bool trial_state) +{ + int ret; + struct fwu_data *data = fwu_get_data(); + + if (trial_state) { + ret = fwu_trial_state_ctr_start(); + if (ret) + return ret; + } + + data->trial_state = trial_state; + + return 0; +} + +/** + * fwu_populate_mdata_image_info() - Populate the image information + * of the metadata + * @data: Version agnostic FWU metadata information + * + * Populate the image information in the FWU metadata by copying it + * from the version agnostic structure. This is done before the + * metadata gets written to the storage media. + * + * Return: None + */ +void fwu_populate_mdata_image_info(struct fwu_data *data) +{ + size_t image_info_size; + void *dst_img_info, *src_img_info; + struct fwu_mdata *mdata = data->fwu_mdata; + + image_info_size = sizeof(data->fwu_images); + dst_img_info = &mdata->img_entry[0]; + src_img_info = &data->fwu_images[0]; + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +/** + * fwu_state_machine_updates() - Update FWU state of the platform + * @trial_state: Is platform transitioning into Trial State + * @update_index: Bank number to which images have been updated + * + * On successful completion of updates, transition the platform to + * either Trial State or Regular State. + * + * To transition the platform to Trial State, start the + * TrialStateCtr counter, followed by setting the value of bank_state + * field of the metadata to Valid state(applicable only in version 2 + * of metadata). + * + * In case, the platform is to transition directly to Regular State, + * update the bank_state field of the metadata to Accepted + * state(applicable only in version 2 of metadata). + * + * Return: 0 if OK, -ve on error + */ +int fwu_state_machine_updates(bool trial_state, + __maybe_unused uint32_t update_index) +{ + return fwu_trial_state_update(trial_state); +} + +/** + * fwu_get_mdata_size() - Get the FWU metadata size + * @mdata_size: Size of the metadata structure + * + * Get the size of the FWU metadata. + * + * Return: 0 if OK, -ve on error + */ +int fwu_get_mdata_size(uint32_t *mdata_size) +{ + *mdata_size = sizeof(struct fwu_mdata); + + return 0; +} + +/** + * fwu_init() - FWU specific initialisations + * + * Carry out some FWU specific initialisations including allocation + * of memory for the metadata copies, and reading the FWU metadata + * copies into the allocated memory. The metadata fields are then + * copied into a version agnostic structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_init(void) +{ + int ret; + uint32_t mdata_size; + + fwu_get_mdata_size(&mdata_size); + + ret = fwu_mdata_copies_allocate(mdata_size); + if (ret) + return ret; + + /* + * Now read the entire structure, both copies, and + * validate that the copies. + */ + ret = fwu_get_mdata(NULL); + if (ret) + return ret; + + fwu_data_init(); + + return 0; +} diff --git a/lib/fwu_updates/fwu_v2.c b/lib/fwu_updates/fwu_v2.c new file mode 100644 index 00000000000..108bc9bb4ac --- /dev/null +++ b/lib/fwu_updates/fwu_v2.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include +#include + +#include + +#define FWU_MDATA_VERSION 0x2U + +static inline struct fwu_fw_store_desc *fwu_get_fw_desc(struct fwu_mdata *mdata) +{ + return (struct fwu_fw_store_desc *)((u8 *)mdata + sizeof(*mdata)); +} + +static uint32_t fwu_check_trial_state(struct fwu_mdata *mdata, uint32_t bank) +{ + return mdata->bank_state[bank] == FWU_BANK_VALID ? 1 : 0; +} + +static void fwu_data_init(void) +{ + int i; + size_t image_info_size; + void *dst_img_info, *src_img_info; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + data->crc32 = mdata->crc32; + data->version = mdata->version; + data->active_index = mdata->active_index; + data->previous_active_index = mdata->previous_active_index; + data->metadata_size = mdata->metadata_size; + fwu_plat_get_bootidx(&data->boot_index); + data->trial_state = fwu_check_trial_state(mdata, data->boot_index); + + data->num_banks = fwu_get_fw_desc(mdata)->num_banks; + data->num_images = fwu_get_fw_desc(mdata)->num_images; + + for (i = 0; i < 4; i++) { + data->bank_state[i] = mdata->bank_state[i]; + } + + image_info_size = sizeof(data->fwu_images); + src_img_info = &fwu_get_fw_desc(mdata)->img_entry[0]; + dst_img_info = &data->fwu_images[0]; + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +static int fwu_mdata_sanity_checks(void) +{ + uint8_t num_banks; + uint16_t num_images; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + if (mdata->version != FWU_MDATA_VERSION) { + log_err("FWU metadata version %u. Expected value of %u\n", + mdata->version, FWU_MDATA_VERSION); + return -EINVAL; + } + + if (!mdata->desc_offset) { + log_err("No image information provided with the Metadata. "); + log_err("Image information expected in the metadata\n"); + return -EINVAL; + } + + if (mdata->desc_offset != 0x20) { + log_err("Descriptor Offset(0x%x) in the FWU Metadata not equal to 0x20\n", + mdata->desc_offset); + return -EINVAL; + } + + num_banks = fwu_get_fw_desc(mdata)->num_banks; + num_images = fwu_get_fw_desc(mdata)->num_images; + + if (num_banks != CONFIG_FWU_NUM_BANKS) { + log_err("Number of Banks(%u) in FWU Metadata different from the configured value(%d)", + num_banks, CONFIG_FWU_NUM_BANKS); + return -EINVAL; + } + + if (num_images != CONFIG_FWU_NUM_IMAGES_PER_BANK) { + log_err("Number of Images(%u) in FWU Metadata different from the configured value(%d)", + num_images, CONFIG_FWU_NUM_IMAGES_PER_BANK); + return -EINVAL; + } + + return 0; +} + +static int fwu_bank_state_update(bool trial_state, uint32_t bank) +{ + int ret; + struct fwu_data *data = fwu_get_data(); + struct fwu_mdata *mdata = data->fwu_mdata; + + mdata->bank_state[bank] = data->bank_state[bank] = trial_state ? + FWU_BANK_VALID : FWU_BANK_ACCEPTED; + + ret = fwu_sync_mdata(mdata, BOTH_PARTS); + if (ret) + log_err("Unable to set bank_state for bank %u\n", bank); + else + data->trial_state = trial_state; + + return ret; +} + +static int fwu_trial_state_start(uint update_index) +{ + int ret; + + ret = fwu_trial_state_ctr_start(); + if (ret) + return ret; + + ret = fwu_bank_state_update(1, update_index); + if (ret) + return ret; + + return 0; +} + +/** + * fwu_populate_mdata_image_info() - Populate the image information + * of the metadata + * @data: Version agnostic FWU metadata information + * + * Populate the image information in the FWU metadata by copying it + * from the version agnostic structure. This is done before the + * metadata gets written to the storage media. + * + * Return: None + */ +void fwu_populate_mdata_image_info(struct fwu_data *data) +{ + size_t image_info_size; + struct fwu_mdata *mdata = data->fwu_mdata; + void *dst_img_info, *src_img_info; + + image_info_size = sizeof(data->fwu_images); + dst_img_info = &fwu_get_fw_desc(mdata)->img_entry[0]; + src_img_info = &data->fwu_images[0]; + + memcpy(dst_img_info, src_img_info, image_info_size); +} + +/** + * fwu_state_machine_updates() - Update FWU state of the platform + * @trial_state: Is platform transitioning into Trial State + * @update_index: Bank number to which images have been updated + * + * On successful completion of updates, transition the platform to + * either Trial State or Regular State. + * + * To transition the platform to Trial State, start the + * TrialStateCtr counter, followed by setting the value of bank_state + * field of the metadata to Valid state(applicable only in version 2 + * of metadata). + * + * In case, the platform is to transition directly to Regular State, + * update the bank_state field of the metadata to Accepted + * state(applicable only in version 2 of metadata). + * + * Return: 0 if OK, -ve on error + */ +int fwu_state_machine_updates(bool trial_state, uint32_t update_index) +{ + return trial_state ? fwu_trial_state_start(update_index) : + fwu_bank_state_update(0, update_index); +} + +/** + * fwu_get_mdata_size() - Get the FWU metadata size + * @mdata_size: Size of the metadata structure + * + * Get the size of the FWU metadata from the structure. This is later used + * to allocate memory for the structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_get_mdata_size(uint32_t *mdata_size) +{ + int ret = 0; + struct fwu_mdata mdata = { 0 }; + struct fwu_data *data = fwu_get_data(); + struct udevice *fwu_dev = fwu_get_dev(); + + if (data->metadata_size) { + *mdata_size = data->metadata_size; + return 0; + } + + ret = fwu_read_mdata(fwu_dev, &mdata, 1, + sizeof(struct fwu_mdata)); + if (ret) { + log_err("FWU metadata read failed\n"); + return ret; + } + + *mdata_size = mdata.metadata_size; + if (!*mdata_size) + return -EINVAL; + + return 0; +} + +/** + * fwu_init() - FWU specific initialisations + * + * Carry out some FWU specific initialisations including allocation + * of memory for the metadata copies, and reading the FWU metadata + * copies into the allocated memory. The metadata fields are then + * copied into a version agnostic structure. + * + * Return: 0 if OK, -ve on error + */ +int fwu_init(void) +{ + int ret; + struct fwu_mdata mdata = { 0 }; + struct udevice *fwu_dev = fwu_get_dev(); + + /* + * First we read only the top level structure + * and get the size of the complete structure. + */ + ret = fwu_read_mdata(fwu_dev, &mdata, 1, + sizeof(struct fwu_mdata)); + if (ret) { + log_err("FWU metadata read failed\n"); + return ret; + } + + ret = fwu_mdata_copies_allocate(mdata.metadata_size); + if (ret) + return ret; + + /* + * Now read the entire structure, both copies, and + * validate that the copies. + */ + ret = fwu_get_mdata(NULL); + if (ret) + return ret; + + ret = fwu_mdata_sanity_checks(); + if (ret) + return ret; + + fwu_data_init(); + + return 0; +} From ac62e0b62e02be0bb8c5f0d0dd49fa9bda91d5c5 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:21 +0530 Subject: [PATCH 08/20] fwu: make changes to access version agnostic structure fields With addition of support for version 2 of the FWU metadata structure, the metadata information is collected into a version agnostic structure. Make changes to the FWU functions so that the information that was earlier obtained by reading the metadata structure is now obtained through this version agnostic structure. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- include/fwu.h | 49 +++++++++- lib/fwu_updates/fwu.c | 204 ++++++++++++++++++++++++++++-------------- 2 files changed, 186 insertions(+), 67 deletions(-) diff --git a/include/fwu.h b/include/fwu.h index 082b5481d1e..77ec65e6180 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -79,9 +79,18 @@ struct fwu_mdata_ops { bool primary, uint32_t size); }; -#define FWU_MDATA_VERSION 0x1 #define FWU_IMAGE_ACCEPTED 0x1 +#define FWU_BANK_INVALID (uint8_t)0xFF +#define FWU_BANK_VALID (uint8_t)0xFE +#define FWU_BANK_ACCEPTED (uint8_t)0xFC + +enum { + PRIMARY_PART = 1, + SECONDARY_PART, + BOTH_PARTS, +}; + /* * GUID value defined in the FWU specification for identification * of the FWU metadata partition. @@ -313,6 +322,44 @@ int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd); */ int fwu_mtd_get_alt_num(efi_guid_t *image_guid, u8 *alt_num, const char *mtd_dev); +/** + * fwu_mdata_copies_allocate() - Allocate memory for metadata + * @mdata_size: Size of the metadata structure + * + * Allocate memory for storing both the copies of the FWU metadata. The + * copies are then used as a cache for storing FWU metadata contents. + * + * Return: 0 if OK, -ve on error + */ +int fwu_mdata_copies_allocate(u32 mdata_size); + +/** + * fwu_get_dev() - Return the FWU metadata device + * + * Return the pointer to the FWU metadata device. + * + * Return: Pointer to the FWU metadata dev + */ +struct udevice *fwu_get_dev(void); + +/** + * fwu_get_data() - Return the version agnostic FWU structure + * + * Return the pointer to the version agnostic FWU structure. + * + * Return: Pointer to the FWU data structure + */ +struct fwu_data *fwu_get_data(void); + +/** + * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided + * @data: FWU Data structure + * @part: Bitmask of FWU metadata partitions to be written to + * + * Return: 0 if OK, -ve on error + */ +int fwu_sync_mdata(struct fwu_mdata *mdata, int part); + /** * fwu_populate_mdata_image_info() - Populate the image information * of the metadata diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c index 86518108c2d..5dfea2a4d8d 100644 --- a/lib/fwu_updates/fwu.c +++ b/lib/fwu_updates/fwu.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -17,7 +18,7 @@ #include -static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid */ +struct fwu_data g_fwu_data; static struct udevice *g_dev; static u8 in_trial; static u8 boottime_check; @@ -27,12 +28,6 @@ enum { IMAGE_ACCEPT_CLEAR, }; -enum { - PRIMARY_PART = 1, - SECONDARY_PART, - BOTH_PARTS, -}; - static int trial_counter_update(u16 *trial_state_ctr) { bool delete; @@ -106,23 +101,9 @@ out: return ret; } -static int in_trial_state(struct fwu_mdata *mdata) +static u32 in_trial_state(void) { - u32 i, active_bank; - struct fwu_image_entry *img_entry; - struct fwu_image_bank_info *img_bank_info; - - active_bank = mdata->active_index; - img_entry = &mdata->img_entry[0]; - for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - img_bank_info = &img_entry[i].img_bank_info[active_bank]; - if (!img_bank_info->accepted) { - log_info("System booting in Trial State\n"); - return 1; - } - } - - return 0; + return g_fwu_data.trial_state; } static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id) @@ -141,17 +122,70 @@ static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id) return -ENOENT; } +static int mdata_crc_check(struct fwu_mdata *mdata) +{ + int ret; + u32 calc_crc32; + uint32_t mdata_size; + void *buf = &mdata->version; + + ret = fwu_get_mdata_size(&mdata_size); + if (ret) + return ret; + + calc_crc32 = crc32(0, buf, mdata_size - sizeof(u32)); + return calc_crc32 == mdata->crc32 ? 0 : -EINVAL; +} + +static void fwu_data_crc_update(uint32_t crc32) +{ + g_fwu_data.crc32 = crc32; +} + +/** + * fwu_get_data() - Return the version agnostic FWU structure + * + * Return the pointer to the version agnostic FWU structure. + * + * Return: Pointer to the FWU data structure + */ +struct fwu_data *fwu_get_data(void) +{ + return &g_fwu_data; +} + +static void fwu_populate_mdata_bank_index(struct fwu_data *fwu_data) +{ + struct fwu_mdata *mdata = fwu_data->fwu_mdata; + + mdata->active_index = fwu_data->active_index; + mdata->previous_active_index = fwu_data->previous_active_index; +} + +/** + * fwu_get_dev() - Return the FWU metadata device + * + * Return the pointer to the FWU metadata device. + * + * Return: Pointer to the FWU metadata dev + */ +struct udevice *fwu_get_dev(void) +{ + return g_dev; +} + /** * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided - * @mdata: FWU metadata structure + * @data: FWU Data structure * @part: Bitmask of FWU metadata partitions to be written to * * Return: 0 if OK, -ve on error */ -static int fwu_sync_mdata(struct fwu_mdata *mdata, int part) +int fwu_sync_mdata(struct fwu_mdata *mdata, int part) { - void *buf = &mdata->version; int err; + uint mdata_size; + void *buf = &mdata->version; if (part == BOTH_PARTS) { err = fwu_sync_mdata(mdata, SECONDARY_PART); @@ -160,32 +194,53 @@ static int fwu_sync_mdata(struct fwu_mdata *mdata, int part) part = PRIMARY_PART; } + err = fwu_get_mdata_size(&mdata_size); + if (err) + return err; + /* * Calculate the crc32 for the updated FWU metadata * and put the updated value in the FWU metadata crc32 * field */ - mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + mdata->crc32 = crc32(0, buf, mdata_size - sizeof(u32)); + fwu_data_crc_update(mdata->crc32); - err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART); + err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART, mdata_size); if (err) { log_err("Unable to write %s mdata\n", part == PRIMARY_PART ? "primary" : "secondary"); return err; } - /* update the cached copy of meta-data */ - memcpy(&g_mdata, mdata, sizeof(struct fwu_mdata)); - return 0; } -static inline int mdata_crc_check(struct fwu_mdata *mdata) +/** + * fwu_mdata_copies_allocate() - Allocate memory for metadata + * @mdata_size: Size of the metadata structure + * + * Allocate memory for storing both the copies of the FWU metadata. The + * copies are then used as a cache for storing FWU metadata contents. + * + * Return: 0 if OK, -ve on error + */ +int fwu_mdata_copies_allocate(u32 mdata_size) { - void *buf = &mdata->version; - u32 calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + if (g_fwu_data.fwu_mdata) + return 0; - return calc_crc32 == mdata->crc32 ? 0 : -EINVAL; + /* + * Allocate the total memory that would be needed for both + * the copies. + */ + g_fwu_data.fwu_mdata = calloc(2, mdata_size); + if (!g_fwu_data.fwu_mdata) { + log_err("Unable to allocate space for FWU metadata\n"); + return -ENOMEM; + } + + return 0; } /** @@ -201,21 +256,33 @@ static inline int mdata_crc_check(struct fwu_mdata *mdata) int fwu_get_mdata(struct fwu_mdata *mdata) { int err; + uint32_t mdata_size; bool parts_ok[2] = { false }; - struct fwu_mdata s, *parts_mdata[2]; + struct fwu_mdata *parts_mdata[2]; - parts_mdata[0] = &g_mdata; - parts_mdata[1] = &s; + err = fwu_get_mdata_size(&mdata_size); + if (err) + return err; + + parts_mdata[0] = g_fwu_data.fwu_mdata; + if (!parts_mdata[0]) { + log_err("Memory not allocated for the FWU Metadata copies\n"); + return -ENOMEM; + } + + parts_mdata[1] = (struct fwu_mdata *)((char *)parts_mdata[0] + + mdata_size); /* if mdata already read and ready */ err = mdata_crc_check(parts_mdata[0]); if (!err) goto ret_mdata; - /* else read, verify and, if needed, fix mdata */ + + /* else read, verify and, if needed, fix mdata */ for (int i = 0; i < 2; i++) { parts_ok[i] = false; - err = fwu_read_mdata(g_dev, parts_mdata[i], !i); + err = fwu_read_mdata(g_dev, parts_mdata[i], !i, mdata_size); if (!err) { err = mdata_crc_check(parts_mdata[i]); if (!err) @@ -230,7 +297,7 @@ int fwu_get_mdata(struct fwu_mdata *mdata) * Before returning, check that both the * FWU metadata copies are the same. */ - err = memcmp(parts_mdata[0], parts_mdata[1], sizeof(struct fwu_mdata)); + err = memcmp(parts_mdata[0], parts_mdata[1], mdata_size); if (!err) goto ret_mdata; @@ -247,7 +314,7 @@ int fwu_get_mdata(struct fwu_mdata *mdata) if (parts_ok[i]) continue; - memcpy(parts_mdata[i], parts_mdata[1 - i], sizeof(struct fwu_mdata)); + memcpy(parts_mdata[i], parts_mdata[1 - i], mdata_size); err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART); if (err) { log_debug("mdata : %s write failed\n", i ? "secondary" : "primary"); @@ -257,7 +324,7 @@ int fwu_get_mdata(struct fwu_mdata *mdata) ret_mdata: if (!err && mdata) - memcpy(mdata, parts_mdata[0], sizeof(struct fwu_mdata)); + memcpy(mdata, parts_mdata[0], mdata_size); return err; } @@ -275,13 +342,13 @@ ret_mdata: int fwu_get_active_index(uint *active_idx) { int ret = 0; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; /* * Found the FWU metadata partition, now read the active_index * value */ - *active_idx = mdata->active_index; + *active_idx = data->active_index; if (*active_idx >= CONFIG_FWU_NUM_BANKS) { log_debug("Active index value read is incorrect\n"); ret = -EINVAL; @@ -302,7 +369,7 @@ int fwu_get_active_index(uint *active_idx) int fwu_set_active_index(uint active_idx) { int ret; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; if (active_idx >= CONFIG_FWU_NUM_BANKS) { log_debug("Invalid active index value\n"); @@ -313,14 +380,16 @@ int fwu_set_active_index(uint active_idx) * Update the active index and previous_active_index fields * in the FWU metadata */ - mdata->previous_active_index = mdata->active_index; - mdata->active_index = active_idx; + data->previous_active_index = data->active_index; + data->active_index = active_idx; + + fwu_populate_mdata_bank_index(data); /* * Now write this updated FWU metadata to both the * FWU metadata partitions */ - ret = fwu_sync_mdata(mdata, BOTH_PARTS); + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); if (ret) { log_debug("Failed to update FWU metadata partitions\n"); ret = -EIO; @@ -346,7 +415,7 @@ int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num) int ret, i; uint update_bank; efi_guid_t *image_guid, image_type_id; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; struct fwu_image_entry *img_entry; struct fwu_image_bank_info *img_bank_info; @@ -365,15 +434,15 @@ int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num) ret = -EINVAL; /* - * The FWU metadata has been read. Now get the image_uuid for the + * The FWU metadata has been read. Now get the image_guid for the * image with the update_bank. */ for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { if (!guidcmp(&image_type_id, - &mdata->img_entry[i].image_type_uuid)) { - img_entry = &mdata->img_entry[i]; + &data->fwu_images[i].image_type_guid)) { + img_entry = &data->fwu_images[i]; img_bank_info = &img_entry->img_bank_info[update_bank]; - image_guid = &img_bank_info->image_uuid; + image_guid = &img_bank_info->image_guid; ret = fwu_plat_get_alt_num(g_dev, image_guid, alt_num); if (ret) log_debug("alt_num not found for partition with GUID %pUs\n", @@ -407,21 +476,23 @@ int fwu_revert_boot_index(void) { int ret; u32 cur_active_index; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; /* * Swap the active index and previous_active_index fields * in the FWU metadata */ - cur_active_index = mdata->active_index; - mdata->active_index = mdata->previous_active_index; - mdata->previous_active_index = cur_active_index; + cur_active_index = data->active_index; + data->active_index = data->previous_active_index; + data->previous_active_index = cur_active_index; + + fwu_populate_mdata_bank_index(data); /* * Now write this updated FWU metadata to both the * FWU metadata partitions */ - ret = fwu_sync_mdata(mdata, BOTH_PARTS); + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); if (ret) { log_debug("Failed to update FWU metadata partitions\n"); ret = -EIO; @@ -448,20 +519,21 @@ int fwu_revert_boot_index(void) static int fwu_clrset_image_accept(efi_guid_t *img_type_id, u32 bank, u8 action) { int ret, i; - struct fwu_mdata *mdata = &g_mdata; + struct fwu_data *data = &g_fwu_data; struct fwu_image_entry *img_entry; struct fwu_image_bank_info *img_bank_info; - img_entry = &mdata->img_entry[0]; + img_entry = &data->fwu_images[0]; for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) { + if (!guidcmp(&img_entry[i].image_type_guid, img_type_id)) { img_bank_info = &img_entry[i].img_bank_info[bank]; if (action == IMAGE_ACCEPT_SET) img_bank_info->accepted |= FWU_IMAGE_ACCEPTED; else img_bank_info->accepted = 0; - ret = fwu_sync_mdata(mdata, BOTH_PARTS); + fwu_populate_mdata_image_info(data); + ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS); goto out; } } @@ -627,9 +699,9 @@ static int fwu_boottime_checks(void) return 0; } - ret = fwu_get_mdata(NULL); + ret = fwu_init(); if (ret) { - log_debug("Unable to read meta-data\n"); + log_debug("fwu_init() failed\n"); return ret; } @@ -665,7 +737,7 @@ static int fwu_boottime_checks(void) if (efi_init_obj_list() != EFI_SUCCESS) return 0; - in_trial = in_trial_state(&g_mdata); + in_trial = in_trial_state(); if (!in_trial || (ret = fwu_trial_count_update()) > 0) ret = trial_counter_update(NULL); From 5a5c4dedd3b15f75f3dae490c79b1691adc085e4 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:22 +0530 Subject: [PATCH 09/20] capsule: fwu: transition the platform state on a successful update Transition the platform to either Trial State or Regular State on a successful update. Do this by calling the fwu_state_machine_updates() API function. For version 1 of the FWU metadata, the transition to Trial State is done by starting the Trial State counter, while for version 2, in addition to the counter, the bank_state field of the FWU metadata is also updated to Valid. For transitioning the platform to Regular State, no action is needed with version 1 of the FWU metadata structure, while for version 2, the bank_state field is set to Accepted. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/efi_loader/efi_capsule.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index de0d49ebebd..0937800e588 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -480,6 +480,11 @@ static __maybe_unused efi_status_t fwu_empty_capsule_process( if (ret != EFI_SUCCESS) log_err("Unable to set the Accept bit for the image %pUs\n", image_guid); + + status = fwu_state_machine_updates(0, active_idx); + if (status < 0) + ret = EFI_DEVICE_ERROR; + } return ret; @@ -521,11 +526,10 @@ static __maybe_unused efi_status_t fwu_post_update_process(bool fw_accept_os) log_err("Failed to update FWU metadata index values\n"); } else { log_debug("Successfully updated the active_index\n"); - if (fw_accept_os) { - status = fwu_trial_state_ctr_start(); - if (status < 0) - ret = EFI_DEVICE_ERROR; - } + status = fwu_state_machine_updates(fw_accept_os ? 1 : 0, + update_index); + if (status < 0) + ret = EFI_DEVICE_ERROR; } return ret; From 222cd230e1644b8d327f921b820964e74ba0f1a4 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:23 +0530 Subject: [PATCH 10/20] fwu: add config symbols for enabling FWU metadata versions Support has been added for version 2 of the FWU metadata structure. Add config symbols to enable either of the two versions. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/Kconfig | 14 ++++++++++++++ lib/fwu_updates/Makefile | 2 ++ 2 files changed, 16 insertions(+) diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig index d35247d0e5d..51b7fbbefd3 100644 --- a/lib/fwu_updates/Kconfig +++ b/lib/fwu_updates/Kconfig @@ -31,4 +31,18 @@ config FWU_TRIAL_STATE_CNT the platform is allowed to boot in Trial State after an update. +config FWU_MDATA_V1 + bool "Enable support FWU Metadata version 1" + help + The FWU specification supports two versions of the + metadata structure. This option enables support for FWU + Metadata version 1 access. + +config FWU_MDATA_V2 + bool "Enable support FWU Metadata version 2" + help + The FWU specification supports two versions of the + metadata structure. This option enables support for FWU + Metadata version 2 access. + endif diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile index c9e3c06b489..3681bef46cd 100644 --- a/lib/fwu_updates/Makefile +++ b/lib/fwu_updates/Makefile @@ -6,3 +6,5 @@ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o +obj-$(CONFIG_FWU_MDATA_V1) += fwu_v1.o +obj-$(CONFIG_FWU_MDATA_V2) += fwu_v2.o From 840afae16f10a6f440b70488fdbf7ab59bf5686d Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:24 +0530 Subject: [PATCH 11/20] fwu: mtd: remove unused argument from function call The third argument passed to the function gen_image_alt_info() is not used and is superfluous. Remove this unused argument from the function call. Fixes: 4898679e190 (FWU: Add FWU metadata access driver for MTD storage regions) Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_mtd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index 69cd3d7001f..d48de19009b 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -107,7 +107,7 @@ __weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_id, return fwu_mtd_get_alt_num(image_id, alt_num, "nor1"); } -static int gen_image_alt_info(char *buf, size_t len, int sidx, +static int gen_image_alt_info(char *buf, size_t len, struct fwu_image_entry *img, struct mtd_info *mtd) { char *p = buf, *end = buf + len; @@ -168,8 +168,7 @@ int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) } for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - ret = gen_image_alt_info(buf, len, i * CONFIG_FWU_NUM_BANKS, - &mdata.img_entry[i], mtd); + ret = gen_image_alt_info(buf, len, &mdata.img_entry[i], mtd); if (ret) break; From 1bef7198cd8f747ccd91cc103613afde96d4199f Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:25 +0530 Subject: [PATCH 12/20] fwu: mtd: get MTD partition specific info from driver Information about FWU images on MTD partitions is now stored with the corresponding driver instead of a global variable. Get this information from the driver. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_mtd.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index d48de19009b..f4e0e3107be 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -15,16 +15,21 @@ #include -struct fwu_mtd_image_info -fwu_mtd_images[CONFIG_FWU_NUM_BANKS * CONFIG_FWU_NUM_IMAGES_PER_BANK]; - static struct fwu_mtd_image_info *mtd_img_by_uuid(const char *uuidbuf) { - int num_images = ARRAY_SIZE(fwu_mtd_images); + int num_images; + struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(fwu_get_dev()); + struct fwu_mtd_image_info *image_info = mtd_priv->fwu_mtd_images; + + if (!image_info) + return NULL; + + num_images = CONFIG_FWU_NUM_BANKS * + CONFIG_FWU_NUM_IMAGES_PER_BANK; for (int i = 0; i < num_images; i++) - if (!strcmp(uuidbuf, fwu_mtd_images[i].uuidbuf)) - return &fwu_mtd_images[i]; + if (!strcmp(uuidbuf, image_info[i].uuidbuf)) + return &image_info[i]; return NULL; } From 8ee8b9c900e350464ab2337ce0b0a7b2aa71f0f3 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:26 +0530 Subject: [PATCH 13/20] fwu: mtd: obtain image information from version agnostic structure Make changes to the functions used for generating the DFU's alt variable so that the FWU image information is obtained from the common version agnostic structure instead of reading the metadata. While here, also update the name of the field used for storing the image GUID in the FWU metadata. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- lib/fwu_updates/fwu_mtd.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index f4e0e3107be..e8211dd5baf 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -136,7 +136,7 @@ static int gen_image_alt_info(char *buf, size_t len, /* Query a partition by image UUID */ bank = &img->img_bank_info[i]; - uuid_bin_to_str(bank->image_uuid.b, uuidbuf, UUID_STR_FORMAT_STD); + uuid_bin_to_str(bank->image_guid.b, uuidbuf, UUID_STR_FORMAT_STD); mtd_img_info = mtd_img_by_uuid(uuidbuf); if (!mtd_img_info) { @@ -163,17 +163,13 @@ static int gen_image_alt_info(char *buf, size_t len, int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) { - struct fwu_mdata mdata; int i, l, ret; - - ret = fwu_get_mdata(&mdata); - if (ret < 0) { - log_err("Failed to get the FWU mdata.\n"); - return ret; - } + struct fwu_data *data = fwu_get_data(); + struct fwu_image_entry *img_entry; for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - ret = gen_image_alt_info(buf, len, &mdata.img_entry[i], mtd); + img_entry = &data->fwu_images[i]; + ret = gen_image_alt_info(buf, len, img_entry, mtd); if (ret) break; From 7cfe0d8a4885ec62b21d3173da4863420f2a9b00 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:27 +0530 Subject: [PATCH 14/20] cmd: fwu: make changes for supporting FWU metadata version 2 Add support for displaying data specific to FWU metadata version 2. Because the size of the v2 metadata structure is read from the structure itself, allocate memory for the metadata structure by first getting the size of the structure. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- cmd/fwu_mdata.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c index 5ecda455df6..3c8be576ac7 100644 --- a/cmd/fwu_mdata.c +++ b/cmd/fwu_mdata.c @@ -13,27 +13,33 @@ #include -static void print_mdata(struct fwu_mdata *mdata) +static void print_mdata(struct fwu_data *data) { int i, j; struct fwu_image_entry *img_entry; struct fwu_image_bank_info *img_info; printf("\tFWU Metadata\n"); - printf("crc32: %#x\n", mdata->crc32); - printf("version: %#x\n", mdata->version); - printf("active_index: %#x\n", mdata->active_index); - printf("previous_active_index: %#x\n", mdata->previous_active_index); + printf("crc32: %#x\n", data->crc32); + printf("version: %#x\n", data->version); + printf("active_index: %#x\n", data->active_index); + printf("previous_active_index: %#x\n", data->previous_active_index); + + if (data->version == 2) { + for (i = 0; i < 4; i++) + printf("bank_state[%d]: %#x\n", + i, data->bank_state[i]); + } printf("\tImage Info\n"); for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { - img_entry = &mdata->img_entry[i]; + img_entry = &data->fwu_images[i]; printf("\nImage Type Guid: %pUL\n", - &img_entry->image_type_uuid); - printf("Location Guid: %pUL\n", &img_entry->location_uuid); + &img_entry->image_type_guid); + printf("Location Guid: %pUL\n", &img_entry->location_guid); for (j = 0; j < CONFIG_FWU_NUM_BANKS; j++) { img_info = &img_entry->img_bank_info[j]; - printf("Image Guid: %pUL\n", &img_info->image_uuid); + printf("Image Guid: %pUL\n", &img_info->image_guid); printf("Image Acceptance: %s\n", img_info->accepted == 0x1 ? "yes" : "no"); } @@ -43,20 +49,11 @@ static void print_mdata(struct fwu_mdata *mdata) int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) { - int ret = CMD_RET_SUCCESS, res; - struct fwu_mdata mdata; + struct fwu_data *data = fwu_get_data(); - res = fwu_get_mdata(&mdata); - if (res < 0) { - log_err("Unable to get valid FWU metadata\n"); - ret = CMD_RET_FAILURE; - goto out; - } + print_mdata(data); - print_mdata(&mdata); - -out: - return ret; + return CMD_RET_SUCCESS; } U_BOOT_CMD( From df42d684961fbb9a79e6ae81234d97799d3efbbb Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:28 +0530 Subject: [PATCH 15/20] tools: mkfwumdata: add support for metadata version 2 Add support for generating the FWU metadata version 2. The tool now requires the version to be provided as a command-line option. Make corresponding changes to the tool's manpage. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- doc/mkfwumdata.1 | 9 ++- tools/mkfwumdata.c | 148 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 127 insertions(+), 30 deletions(-) diff --git a/doc/mkfwumdata.1 b/doc/mkfwumdata.1 index 7dd718b26e2..5e61c615ead 100644 --- a/doc/mkfwumdata.1 +++ b/doc/mkfwumdata.1 @@ -6,6 +6,7 @@ mkfwumdata \- create FWU metadata image . .SH SYNOPSIS .SY mkfwumdata +.OP \-v version .OP \-a activeidx .OP \-p previousidx .OP \-g @@ -28,6 +29,12 @@ creates metadata info to be used with FWU. Print usage information and exit. . .TP +.B \-v +Set +.IR version +as the metadata version to generate. Valid values 1 or 2. +. +.TP .B \-a Set .IR activeidx @@ -81,7 +88,7 @@ Create a metadata image with 2 banks and 1 image/bank, BankAct=0, BankPrev=1: .EX .in +4 $ \c -.B mkfwumdata \-a 0 \-p 1 \-b 2 \-i 1 \\\\\& +.B mkfwumdata \-v 2 \-a 0 \-p 1 \-b 2 \-i 1 \\\\\& .in +6 .B 17e86d77-41f9-4fd7-87ec-a55df9842de5,\\\\\& .B 10c36d7d-ca52-b843-b7b9-f9d6c501d108,\\\\\& diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index b2d90ca7c94..634453d421e 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -10,28 +10,35 @@ #include #include #include -#include #include +#include +#include #include -/* This will dynamically allocate the fwu_mdata */ -#define CONFIG_FWU_NUM_BANKS 0 -#define CONFIG_FWU_NUM_IMAGES_PER_BANK 0 - -/* Since we can not include fwu.h, redefine version here. */ -#define FWU_MDATA_VERSION 1 - typedef uint8_t u8; typedef int16_t s16; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; +#undef CONFIG_FWU_NUM_BANKS +#undef CONFIG_FWU_NUM_IMAGES_PER_BANK + +/* This will dynamically allocate the fwu_mdata */ +#define CONFIG_FWU_NUM_BANKS 0 +#define CONFIG_FWU_NUM_IMAGES_PER_BANK 0 + +/* version 2 supports maximum of 4 banks */ +#define MAX_BANKS_V2 4 + +#define BANK_INVALID (u8)0xFF +#define BANK_ACCEPTED (u8)0xFC + #include /* TODO: Endianness conversion may be required for some arch. */ -static const char *opts_short = "b:i:a:p:gh"; +static const char *opts_short = "b:i:a:p:v:gh"; static struct option options[] = { {"banks", required_argument, NULL, 'b'}, @@ -39,6 +46,7 @@ static struct option options[] = { {"guid", required_argument, NULL, 'g'}, {"active-bank", required_argument, NULL, 'a'}, {"previous-bank", required_argument, NULL, 'p'}, + {"version", required_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -49,6 +57,7 @@ static void print_usage(void) fprintf(stderr, "Options:\n" "\t-i, --images Number of images (mandatory)\n" "\t-b, --banks Number of banks (mandatory)\n" + "\t-v, --version Metadata version (mandatory)\n" "\t-a, --active-bank Active bank (default=0)\n" "\t-p, --previous-bank Previous active bank (default=active_bank - 1)\n" "\t-g, --guid Use GUID instead of UUID\n" @@ -70,13 +79,26 @@ struct fwu_mdata_object { size_t images; size_t banks; size_t size; + u8 version; struct fwu_mdata *mdata; }; static int previous_bank, active_bank; static bool __use_guid; -static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) +static bool supported_mdata_version(unsigned long version) +{ + switch (version) { + case 1: + case 2: + return true; + default: + return false; + } +} + +static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, + u8 version) { struct fwu_mdata_object *mobj; @@ -84,11 +106,20 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) if (!mobj) return NULL; - mobj->size = sizeof(struct fwu_mdata) + - (sizeof(struct fwu_image_entry) + - sizeof(struct fwu_image_bank_info) * banks) * images; + if (version == 1) { + mobj->size = sizeof(struct fwu_mdata) + + (sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * banks) * images; + } else { + mobj->size = sizeof(struct fwu_mdata) + + sizeof(struct fwu_fw_store_desc) + + (sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * banks) * images; + } + mobj->images = images; mobj->banks = banks; + mobj->version = version; mobj->mdata = calloc(1, mobj->size); if (!mobj->mdata) { @@ -104,9 +135,18 @@ fwu_get_image(struct fwu_mdata_object *mobj, size_t idx) { size_t offset; - offset = sizeof(struct fwu_mdata) + - (sizeof(struct fwu_image_entry) + - sizeof(struct fwu_image_bank_info) * mobj->banks) * idx; + if (mobj->version == 1) { + offset = sizeof(struct fwu_mdata) + + (sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * mobj->banks) * + idx; + } else { + offset = sizeof(struct fwu_mdata) + + sizeof(struct fwu_fw_store_desc) + + (sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * mobj->banks) * + idx; + } return (struct fwu_image_entry *)((char *)mobj->mdata + offset); } @@ -116,11 +156,20 @@ fwu_get_bank(struct fwu_mdata_object *mobj, size_t img_idx, size_t bnk_idx) { size_t offset; - offset = sizeof(struct fwu_mdata) + - (sizeof(struct fwu_image_entry) + - sizeof(struct fwu_image_bank_info) * mobj->banks) * img_idx + - sizeof(struct fwu_image_entry) + - sizeof(struct fwu_image_bank_info) * bnk_idx; + if (mobj->version == 1) { + offset = sizeof(struct fwu_mdata) + + (sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * mobj->banks) * + img_idx + sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * bnk_idx; + } else { + offset = sizeof(struct fwu_mdata) + + sizeof(struct fwu_fw_store_desc) + + (sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * mobj->banks) * + img_idx + sizeof(struct fwu_image_entry) + + sizeof(struct fwu_image_bank_info) * bnk_idx; + } return (struct fwu_image_bank_info *)((char *)mobj->mdata + offset); } @@ -188,7 +237,7 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, return -EINVAL; if (strcmp(uuid, "0") && - uuid_guid_parse(uuid, (unsigned char *)&image->location_uuid) < 0) + uuid_guid_parse(uuid, (unsigned char *)&image->location_guid) < 0) return -EINVAL; /* Image type UUID */ @@ -196,7 +245,7 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, if (!uuid) return -EINVAL; - if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_uuid) < 0) + if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_guid) < 0) return -EINVAL; /* Fill bank image-UUID */ @@ -210,22 +259,52 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, return -EINVAL; if (strcmp(uuid, "0") && - uuid_guid_parse(uuid, (unsigned char *)&bank->image_uuid) < 0) + uuid_guid_parse(uuid, (unsigned char *)&bank->image_guid) < 0) return -EINVAL; } return 0; } +#if defined(CONFIG_FWU_MDATA_V1) +static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj) +{ +} +#else +static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj) +{ + int i; + struct fwu_fw_store_desc *fw_desc; + struct fwu_mdata *mdata = mobj->mdata; + + mdata->metadata_size = mobj->size; + mdata->desc_offset = sizeof(struct fwu_mdata); + + for (i = 0; i < MAX_BANKS_V2; i++) + mdata->bank_state[i] = i < mobj->banks ? + BANK_ACCEPTED : BANK_INVALID; + + fw_desc = (struct fwu_fw_store_desc *)((u8 *)mdata + sizeof(*mdata)); + fw_desc->num_banks = mobj->banks; + fw_desc->num_images = mobj->images; + fw_desc->img_entry_size = sizeof(struct fwu_image_entry) + + (sizeof(struct fwu_image_bank_info) * mobj->banks); + fw_desc->bank_info_entry_size = + sizeof(struct fwu_image_bank_info); +} +#endif /* CONFIG_FWU_MDATA_V1 */ + /* Caller must ensure that @uuids[] has @mobj->images entries. */ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) { struct fwu_mdata *mdata = mobj->mdata; int i, ret; - mdata->version = FWU_MDATA_VERSION; + mdata->version = mobj->version; mdata->active_index = active_bank; mdata->previous_active_index = previous_bank; + fwu_fill_version_specific_mdata(mobj); + for (i = 0; i < mobj->images; i++) { ret = fwu_parse_fill_image_uuid(mobj, i, uuids[i]); if (ret < 0) @@ -239,13 +318,14 @@ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) } static int -fwu_make_mdata(size_t images, size_t banks, char *uuids[], char *output) +fwu_make_mdata(size_t images, size_t banks, u8 version, char *uuids[], + char *output) { struct fwu_mdata_object *mobj; FILE *file; int ret; - mobj = fwu_alloc_mdata(images, banks); + mobj = fwu_alloc_mdata(images, banks, version); if (!mobj) return -ENOMEM; @@ -276,7 +356,7 @@ done_make: int main(int argc, char *argv[]) { - unsigned long banks = 0, images = 0; + unsigned long banks = 0, images = 0, version = 0; int c, ret; /* Explicitly initialize defaults */ @@ -305,6 +385,9 @@ int main(int argc, char *argv[]) case 'a': active_bank = strtoul(optarg, NULL, 0); break; + case 'v': + version = strtoul(optarg, NULL, 0); + break; } } while (c != -1); @@ -313,6 +396,12 @@ int main(int argc, char *argv[]) return -EINVAL; } + if (!version || !supported_mdata_version(version)) { + fprintf(stderr, "Error: Version value can only be either 1 or 2, not %ld.\n", + version); + return -EINVAL; + } + /* This command takes UUIDs * images and output file. */ if (optind + images + 1 != argc) { fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n"); @@ -325,7 +414,8 @@ int main(int argc, char *argv[]) previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1; } - ret = fwu_make_mdata(images, banks, argv + optind, argv[argc - 1]); + ret = fwu_make_mdata(images, banks, (u8)version, argv + optind, + argv[argc - 1]); if (ret < 0) fprintf(stderr, "Error: Failed to parse and write image: %s\n", strerror(-ret)); From cb9ae40a16f0e9adae594526435de976afeedaf2 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:29 +0530 Subject: [PATCH 16/20] tools: mkfwumdata: add logic to append vendor data to the FWU metadata The version 2 of the FWU metadata allows for appending opaque vendor specific data to the metadata structure. Add support for appending this data to the metadata. The vendor specific data needs to be provided through a file, passed through a command-line parameter. Make corresponding changes to the tool's manpage. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- doc/mkfwumdata.1 | 7 ++++ tools/mkfwumdata.c | 101 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 16 deletions(-) diff --git a/doc/mkfwumdata.1 b/doc/mkfwumdata.1 index 5e61c615ead..2ed0fb100b8 100644 --- a/doc/mkfwumdata.1 +++ b/doc/mkfwumdata.1 @@ -10,6 +10,7 @@ mkfwumdata \- create FWU metadata image .OP \-a activeidx .OP \-p previousidx .OP \-g +.OP \-V vendor-file .BI \-i\~ imagecount .BI \-b\~ bankcount .I UUIDs @@ -57,6 +58,12 @@ Convert the as GUIDs before use. . .TP +.B \-V +Pass +.IR vendor-file +for appending vendor data to the metadata. Supported only with version 2. +. +.TP .B \-i Specify there are .IR imagecount diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index 634453d421e..fbc2067bc12 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -36,9 +38,7 @@ typedef uint64_t u64; #include -/* TODO: Endianness conversion may be required for some arch. */ - -static const char *opts_short = "b:i:a:p:v:gh"; +static const char *opts_short = "b:i:a:p:v:V:gh"; static struct option options[] = { {"banks", required_argument, NULL, 'b'}, @@ -47,6 +47,7 @@ static struct option options[] = { {"active-bank", required_argument, NULL, 'a'}, {"previous-bank", required_argument, NULL, 'p'}, {"version", required_argument, NULL, 'v'}, + {"vendor-file", required_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -61,6 +62,7 @@ static void print_usage(void) "\t-a, --active-bank Active bank (default=0)\n" "\t-p, --previous-bank Previous active bank (default=active_bank - 1)\n" "\t-g, --guid Use GUID instead of UUID\n" + "\t-V, --vendor-file Vendor data file to append to the metadata\n" "\t-h, --help print a help message\n" ); fprintf(stderr, " UUIDs list syntax:\n" @@ -80,6 +82,8 @@ struct fwu_mdata_object { size_t banks; size_t size; u8 version; + size_t vsize; + void *vbuf; struct fwu_mdata *mdata; }; @@ -98,7 +102,7 @@ static bool supported_mdata_version(unsigned long version) } static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, - u8 version) + u8 version, size_t vendor_size) { struct fwu_mdata_object *mobj; @@ -115,6 +119,9 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, sizeof(struct fwu_fw_store_desc) + (sizeof(struct fwu_image_entry) + sizeof(struct fwu_image_bank_info) * banks) * images; + + mobj->size += vendor_size; + mobj->vsize = vendor_size; } mobj->images = images; @@ -122,12 +129,21 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, mobj->version = version; mobj->mdata = calloc(1, mobj->size); - if (!mobj->mdata) { - free(mobj); - return NULL; + if (!mobj->mdata) + goto alloc_err; + + if (vendor_size) { + mobj->vbuf = calloc(1, mobj->vsize); + if (!mobj->vbuf) + goto alloc_err; } return mobj; + +alloc_err: + free(mobj->mdata); + free(mobj); + return NULL; } static struct fwu_image_entry * @@ -297,6 +313,7 @@ static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj) static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) { struct fwu_mdata *mdata = mobj->mdata; + char *vdata; int i, ret; mdata->version = mobj->version; @@ -311,24 +328,65 @@ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) return ret; } + if (mobj->vsize) { + vdata = (char *)mobj->mdata + (mobj->size - mobj->vsize); + memcpy(vdata, mobj->vbuf, mobj->vsize); + } + mdata->crc32 = crc32(0, (const unsigned char *)&mdata->version, mobj->size - sizeof(uint32_t)); return 0; } -static int -fwu_make_mdata(size_t images, size_t banks, u8 version, char *uuids[], - char *output) +static int fwu_read_vendor_data(struct fwu_mdata_object *mobj, + const char *vendor_file) { - struct fwu_mdata_object *mobj; - FILE *file; - int ret; + int ret = 0; + FILE *vfile = NULL; - mobj = fwu_alloc_mdata(images, banks, version); + vfile = fopen(vendor_file, "r"); + if (!vfile) { + ret = -1; + goto out; + } + + if (fread(mobj->vbuf, 1, mobj->vsize, vfile) != mobj->vsize) + ret = -1; + +out: + fclose(vfile); + return ret; +} + +static int fwu_make_mdata(size_t images, size_t banks, u8 version, + const char *vendor_file, char *uuids[], + char *output) +{ + int ret; + FILE *file; + struct stat sbuf; + size_t vendor_size = 0; + struct fwu_mdata_object *mobj; + + if (vendor_file) { + ret = stat(vendor_file, &sbuf); + if (ret) + return -errno; + + vendor_size = sbuf.st_size; + } + + mobj = fwu_alloc_mdata(images, banks, version, vendor_size); if (!mobj) return -ENOMEM; + if (vendor_file) { + ret = fwu_read_vendor_data(mobj, vendor_file); + if (ret) + goto done_make; + } + ret = fwu_parse_fill_uuids(mobj, uuids); if (ret < 0) goto done_make; @@ -349,6 +407,7 @@ fwu_make_mdata(size_t images, size_t banks, u8 version, char *uuids[], done_make: free(mobj->mdata); + free(mobj->vbuf); free(mobj); return ret; @@ -358,11 +417,13 @@ int main(int argc, char *argv[]) { unsigned long banks = 0, images = 0, version = 0; int c, ret; + const char *vendor_file; /* Explicitly initialize defaults */ active_bank = 0; __use_guid = false; previous_bank = INT_MAX; + vendor_file = NULL; do { c = getopt_long(argc, argv, opts_short, options, NULL); @@ -388,6 +449,9 @@ int main(int argc, char *argv[]) case 'v': version = strtoul(optarg, NULL, 0); break; + case 'V': + vendor_file = optarg; + break; } } while (c != -1); @@ -402,6 +466,11 @@ int main(int argc, char *argv[]) return -EINVAL; } + if (version == 1 && vendor_file) { + fprintf(stderr, "Error: Vendor Data can only be appended in version 2 of FWU Metadata.\n"); + return -EINVAL; + } + /* This command takes UUIDs * images and output file. */ if (optind + images + 1 != argc) { fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n"); @@ -414,8 +483,8 @@ int main(int argc, char *argv[]) previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1; } - ret = fwu_make_mdata(images, banks, (u8)version, argv + optind, - argv[argc - 1]); + ret = fwu_make_mdata(images, banks, (u8)version, vendor_file, + argv + optind, argv[argc - 1]); if (ret < 0) fprintf(stderr, "Error: Failed to parse and write image: %s\n", strerror(-ret)); From cdc4b465021da17cb2a375411f8b5408088a8893 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:30 +0530 Subject: [PATCH 17/20] test: fwu: make changes to the FWU metadata access test Make changes to the FWU metadata access tests corresponding to the changes in the FWU metadata access code. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- test/dm/fwu_mdata.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/dm/fwu_mdata.c b/test/dm/fwu_mdata.c index 52018f610fe..621ba647d96 100644 --- a/test/dm/fwu_mdata.c +++ b/test/dm/fwu_mdata.c @@ -93,6 +93,10 @@ static int dm_test_fwu_mdata_read(struct unit_test_state *uts) struct udevice *dev; struct fwu_mdata mdata = { 0 }; + ut_assertok(setup_blk_device(uts)); + ut_assertok(populate_mmc_disk_image(uts)); + ut_assertok(write_mmc_blk_device(uts)); + /* * Trigger lib/fwu_updates/fwu.c fwu_boottime_checks() * to populate g_dev global pointer in that library. @@ -100,9 +104,7 @@ static int dm_test_fwu_mdata_read(struct unit_test_state *uts) event_notify_null(EVT_MAIN_LOOP); ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev)); - ut_assertok(setup_blk_device(uts)); - ut_assertok(populate_mmc_disk_image(uts)); - ut_assertok(write_mmc_blk_device(uts)); + ut_assertok(fwu_init()); ut_assertok(fwu_get_mdata(&mdata)); @@ -118,18 +120,20 @@ static int dm_test_fwu_mdata_write(struct unit_test_state *uts) struct udevice *dev; struct fwu_mdata mdata = { 0 }; + ut_assertok(setup_blk_device(uts)); + ut_assertok(populate_mmc_disk_image(uts)); + ut_assertok(write_mmc_blk_device(uts)); + /* * Trigger lib/fwu_updates/fwu.c fwu_boottime_checks() * to populate g_dev global pointer in that library. */ event_notify_null(EVT_MAIN_LOOP); - ut_assertok(setup_blk_device(uts)); - ut_assertok(populate_mmc_disk_image(uts)); - ut_assertok(write_mmc_blk_device(uts)); ut_assertok(uclass_first_device_err(UCLASS_FWU_MDATA, &dev)); + ut_assertok(fwu_init()); ut_assertok(fwu_get_mdata(&mdata)); active_idx = (mdata.active_index + 1) % CONFIG_FWU_NUM_BANKS; From 7ef84369708993aeb523ae6a6abd5e5aab66196b Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:31 +0530 Subject: [PATCH 18/20] doc: fwu: make changes to reflect support for FWU metadata v2 The FWU Update Agent in U-Boot supports both versions of the FWU metadata. Make changes in the documentation to reflect this. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- doc/board/socionext/developerbox.rst | 7 +++++-- doc/develop/uefi/fwu_updates.rst | 20 +++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/doc/board/socionext/developerbox.rst b/doc/board/socionext/developerbox.rst index 46712c379b6..863761c6e27 100644 --- a/doc/board/socionext/developerbox.rst +++ b/doc/board/socionext/developerbox.rst @@ -116,6 +116,7 @@ configs/synquacer_developerbox_defconfig enables default FWU configuration :: CONFIG_FWU_NUM_BANKS=2 CONFIG_FWU_NUM_IMAGES_PER_BANK=1 CONFIG_CMD_FWU_METADATA=y + CONFIG_FWU_MDATA_V2=y And build it:: @@ -129,7 +130,9 @@ And build it:: By default, the CONFIG_FWU_NUM_BANKS and CONFIG_FWU_NUM_IMAGES_PER_BANKS are set to 2 and 1 respectively. This uses FIP (Firmware Image Package) type image which contains TF-A, U-Boot and OP-TEE (the OP-TEE is optional). -You can use fiptool to compose the FIP image from those firmware images. +You can use fiptool to compose the FIP image from those firmware +images. There are two versions of the FWU metadata, of which the +platform enables version 2 by default. Rebuild SCP firmware -------------------- @@ -194,7 +197,7 @@ following UUIDs. These UUIDs are used for making a FWU metadata image. -u-boot$ ./tools/mkfwumdata -i 1 -b 2 \ +u-boot$ ./tools/mkfwumdata -v 2 -i 1 -b 2 \ 17e86d77-41f9-4fd7-87ec-a55df9842de5,10c36d7d-ca52-b843-b7b9-f9d6c501d108,5a66a702-99fd-4fef-a392-c26e261a2828,a8f868a1-6e5c-4757-878d-ce63375ef2c0 \ ../devbox-fwu-mdata.img diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst index e4709d82b41..51e8a28efe1 100644 --- a/doc/develop/uefi/fwu_updates.rst +++ b/doc/develop/uefi/fwu_updates.rst @@ -46,6 +46,8 @@ The feature can be enabled by specifying the following configs:: CONFIG_FWU_NUM_BANKS= CONFIG_FWU_NUM_IMAGES_PER_BANK= + CONFIG_FWU_MDATA_V1=y or CONFIG_FWU_MDATA_V2=y + in the .config file By enabling the CONFIG_CMD_FWU_METADATA config option, the @@ -58,6 +60,14 @@ enable the FWU Multi Bank Update functionality. Please refer to the section :ref:`uefi_capsule_update_ref` for more details on generation of the UEFI capsule. +FWU Metadata +------------ + +U-Boot supports both versions(1 and 2) of the FWU metadata defined in +the two revisions of the specification. Support can be enabled for +either of the two versions through a config flag. The mkfwumdata tool +can generate metadata for both the supported versions. + Setting up the device for GPT partitioned storage ------------------------------------------------- @@ -94,12 +104,12 @@ of. Each GPT partition entry in the GPT header has two GUIDs:: * UniquePartitionGUID The PartitionTypeGUID value should correspond to the -``image_type_uuid`` field of the FWU metadata. This field is used to +``image_type_guid`` field of the FWU metadata. This field is used to identify a given type of updatable firmware image, e.g. U-Boot, OP-TEE, FIP etc. This GUID should also be used for specifying the `--guid` parameter when generating the capsule. -The UniquePartitionGUID value should correspond to the ``image_uuid`` +The UniquePartitionGUID value should correspond to the ``image_guid`` field in the FWU metadata. This GUID is used to identify images of a given image type in different banks. @@ -108,8 +118,8 @@ metadata partitions. This would be the PartitionTypeGUID for the metadata partitions. Similarly, the UEFI specification defines the ESP GUID to be be used. -When generating the metadata, the ``image_type_uuid`` and the -``image_uuid`` values should match the *PartitionTypeGUID* and the +When generating the metadata, the ``image_type_guid`` and the +``image_guid`` values should match the *PartitionTypeGUID* and the *UniquePartitionGUID* values respectively. Performing the Update @@ -181,5 +191,5 @@ empty capsule would be:: Links ----- -* [1] https://developer.arm.com/documentation/den0118/a/ - FWU Specification +* [1] https://developer.arm.com/documentation/den0118/ - FWU Specification * [2] https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf - Dependable Boot Specification From 7b98f1e617f8d06897f85a87817e9bfde3067e1a Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:32 +0530 Subject: [PATCH 19/20] MAINTAINERS: add entry for FWU multi bank update feature Add an entry for the FWU Multi Bank Update feature. Signed-off-by: Sughosh Ganu Reviewed-by: Ilias Apalodimas Tested-by: Michal Simek --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8b316c8550e..860725bef78 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1149,6 +1149,14 @@ T: git https://source.denx.de/u-boot/custodians/u-boot-fsl-qoriq.git F: drivers/watchdog/sp805_wdt.c F: drivers/watchdog/sbsa_gwdt.c +FWU Multi Bank Update +M: Sughosh Ganu +S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-efi.git +F: lib/fwu_updates/* +F: drivers/fwu-mdata/* +F: tools/mkfwumdata.c + GATEWORKS_SC M: Tim Harvey S: Maintained From e32c15d6041e9298673c75b26cc6af1266046dc5 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:33 +0530 Subject: [PATCH 20/20] configs: fwu: re-enable FWU configs Now that support for FWU metadata version 2 has been added, the feature can be enabled on platforms which had enabled it. A new config symbol for selecting the metadata version for the platform is also being added. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- configs/corstone1000_defconfig | 3 +++ configs/sandbox64_defconfig | 2 ++ configs/synquacer_developerbox_defconfig | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig index 29d7550afb6..ab4e0fefc90 100644 --- a/configs/corstone1000_defconfig +++ b/configs/corstone1000_defconfig @@ -24,6 +24,7 @@ CONFIG_LOGLEVEL=7 CONFIG_BOARD_LATE_INIT=y CONFIG_SYS_PROMPT="corstone1000# " # CONFIG_CMD_CONSOLE is not set +CONFIG_CMD_FWU_METADATA=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_XIMG is not set CONFIG_CMD_GPT=y @@ -66,3 +67,5 @@ CONFIG_FFA_SHARED_MM_BUF_OFFSET=0 CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000 CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_IGNORE_OSINDICATIONS=y +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_FWU_MDATA_V1=y diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 7e8200e70cb..7b316f0d80b 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -272,6 +272,8 @@ CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_FWU_MDATA_V1=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y diff --git a/configs/synquacer_developerbox_defconfig b/configs/synquacer_developerbox_defconfig index 616d4100744..7e1aeac217c 100644 --- a/configs/synquacer_developerbox_defconfig +++ b/configs/synquacer_developerbox_defconfig @@ -17,6 +17,7 @@ CONFIG_SYS_BOOTM_LEN=0x800000 CONFIG_BOOTSTAGE_STASH_SIZE=4096 CONFIG_HUSH_PARSER=y CONFIG_SYS_MAXARGS=128 +CONFIG_CMD_FWU_METADATA=y CONFIG_CMD_IMLS=y CONFIG_CMD_ERASEENV=y CONFIG_CMD_NVEDIT_EFI=y @@ -51,6 +52,7 @@ CONFIG_DFU_TFTP=y CONFIG_DFU_MTD=y CONFIG_DFU_RAM=y CONFIG_DFU_SF=y +CONFIG_FWU_MDATA_MTD=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_SYNQUACER=y CONFIG_MMC_SDHCI=y @@ -93,3 +95,5 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_IGNORE_OSINDICATIONS=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_FWU_MDATA_V2=y