[PATCH v7 4/7] cmd: rng: Add support for selecting RNG device
The 'rng' u-boot command is used for printing a select number of random bytes on the console. Currently, the RNG device from which the random bytes are read is fixed. However, a platform can have multiple RNG devices, one example being qemu, which has a virtio RNG device and the RNG pseudo device through the TPM chip. Extend the 'rng' command so that the user can provide the RNG device number from which the random bytes are to be read. This will be the device index under the RNG uclass. Signed-off-by: Sughosh Ganu Tested-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- Changes since V6: None cmd/rng.c | 31 +++ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cmd/rng.c b/cmd/rng.c index 1ad5a096c0..2ddf27545f 100644 --- a/cmd/rng.c +++ b/cmd/rng.c @@ -13,19 +13,34 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - size_t n = 0x40; + size_t n; struct udevice *dev; void *buf; + int devnum; int ret = CMD_RET_SUCCESS; - if (uclass_get_device(UCLASS_RNG, 0, ) || !dev) { + switch (argc) { + case 1: + devnum = 0; + n = 0x40; + break; + case 2: + devnum = hextoul(argv[1], NULL); + n = 0x40; + break; + case 3: + devnum = hextoul(argv[1], NULL); + n = hextoul(argv[2], NULL); + break; + default: + return CMD_RET_USAGE; + } + + if (uclass_get_device_by_seq(UCLASS_RNG, devnum, ) || !dev) { printf("No RNG device\n"); return CMD_RET_FAILURE; } - if (argc >= 2) - n = hextoul(argv[1], NULL); - buf = malloc(n); if (!buf) { printf("Out of memory\n"); @@ -46,12 +61,12 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_LONGHELP static char rng_help_text[] = - "[n]\n" - " - print n random bytes\n"; + "[dev [n]]\n" + " - print n random bytes read from dev\n"; #endif U_BOOT_CMD( - rng, 2, 0, do_rng, + rng, 3, 0, do_rng, "print bytes from the hardware random number generator", rng_help_text ); -- 2.34.1
[PATCH v7 3/7] tpm: Add the RNG child device
The TPM device comes with the random number generator(RNG) functionality which is built into the TPM device. Add logic to add the RNG child device in the TPM uclass post probe callback. The RNG device can then be used to pass a set of random bytes to the linux kernel, need for address space randomisation through the EFI_RNG_PROTOCOL interface. Signed-off-by: Sughosh Ganu --- Changes since V6: None drivers/tpm/tpm-uclass.c | 37 + 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c index f67fe1019b..e1f1ef01e1 100644 --- a/drivers/tpm/tpm-uclass.c +++ b/drivers/tpm/tpm-uclass.c @@ -11,10 +11,15 @@ #include #include #include +#include #include #include #include "tpm_internal.h" +#include + +#define TPM_RNG_DRV_NAME "tpm-rng" + int tpm_open(struct udevice *dev) { struct tpm_ops *ops = tpm_get_ops(dev); @@ -136,12 +141,36 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, return 0; } +static int tpm_uclass_post_probe(struct udevice *dev) +{ + int ret; + const char *drv = TPM_RNG_DRV_NAME; + struct udevice *child; + + if (CONFIG_IS_ENABLED(TPM_RNG)) { + ret = device_find_first_child_by_uclass(dev, UCLASS_RNG, + ); + + if (ret != -ENODEV) { + log_debug("RNG child already added to the TPM device\n"); + return ret; + } + + ret = device_bind_driver(dev, drv, "tpm-rng0", ); + if (ret) + return log_msg_ret("bind", ret); + } + + return 0; +} + UCLASS_DRIVER(tpm) = { - .id = UCLASS_TPM, - .name = "tpm", - .flags = DM_UC_FLAG_SEQ_ALIAS, + .id = UCLASS_TPM, + .name = "tpm", + .flags = DM_UC_FLAG_SEQ_ALIAS, #if CONFIG_IS_ENABLED(OF_REAL) - .post_bind = dm_scan_fdt_dev, + .post_bind = dm_scan_fdt_dev, #endif + .post_probe = tpm_uclass_post_probe, .per_device_auto= sizeof(struct tpm_chip_priv), }; -- 2.34.1
[PATCH v7 2/7] tpm: rng: Add driver model interface for TPM RNG device
The TPM device has a builtin random number generator(RNG) functionality. Expose the RNG functions of the TPM device to the driver model so that they can be used by the EFI_RNG_PROTOCOL if the protocol is installed. Also change the function arguments and return type of the random number functions to comply with the driver model api. Signed-off-by: Sughosh Ganu --- Changes since V6: * Remove the changes made in tpm-v[12].c to return -EIO instead of TPM_LIB_ERROR as suggested by Simon drivers/rng/Kconfig | 9 + drivers/rng/Makefile | 1 + drivers/rng/tpm_rng.c | 23 +++ lib/Kconfig | 1 + lib/tpm_api.c | 6 +++--- 5 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 drivers/rng/tpm_rng.c diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index 21a9ff0195..16143681da 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -74,4 +74,13 @@ config RNG_SMCCC_TRNG Enable random number generator for platforms that support Arm SMCCC TRNG interface. +config TPM_RNG + bool "Enable random number generator on TPM device" + depends on TPM + default y + help + The TPM device has an inbuilt random number generator + functionality. Enable random number generator on TPM + devices. + endif diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 2494717d7c..78f61051ac 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o +obj-$(CONFIG_TPM_RNG) += tpm_rng.o diff --git a/drivers/rng/tpm_rng.c b/drivers/rng/tpm_rng.c new file mode 100644 index 00..1a5e9e2e4b --- /dev/null +++ b/drivers/rng/tpm_rng.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include + +static int rng_tpm_random_read(struct udevice *dev, void *data, size_t count) +{ + return tpm_get_random(dev_get_parent(dev), data, count); +} + +static const struct dm_rng_ops tpm_rng_ops = { + .read = rng_tpm_random_read, +}; + +U_BOOT_DRIVER(tpm_rng) = { + .name = "tpm-rng", + .id = UCLASS_RNG, + .ops= _rng_ops, +}; diff --git a/lib/Kconfig b/lib/Kconfig index 7dd777b56a..e888c29245 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -360,6 +360,7 @@ source lib/crypt/Kconfig config TPM bool "Trusted Platform Module (TPM) Support" depends on DM + imply DM_RNG help This enables support for TPMs which can be used to provide security features for your board. The TPM can be connected via LPC or I2C diff --git a/lib/tpm_api.c b/lib/tpm_api.c index 4ac4612c81..032f383ca0 100644 --- a/lib/tpm_api.c +++ b/lib/tpm_api.c @@ -269,7 +269,7 @@ u32 tpm_get_random(struct udevice *dev, void *data, u32 count) if (tpm_is_v1(dev)) return tpm1_get_random(dev, data, count); else if (tpm_is_v2(dev)) - return -ENOSYS; /* not implemented yet */ - else - return -ENOSYS; + return tpm2_get_random(dev, data, count); + + return -ENOSYS; } -- 2.34.1
[PATCH v7 1/7] tpm: Export the TPM-version functions
From: Simon Glass These functions should really be available outside the TPM code, so that other callers can find out which version the TPM is. Rename them to have a tpm_ prefix() and add them to the header file. Signed-off-by: Simon Glass --- Changes since V6: None include/tpm_api.h | 10 ++ lib/tpm_api.c | 92 +-- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/include/tpm_api.h b/include/tpm_api.h index ef45b43a8f..11aa14eb79 100644 --- a/include/tpm_api.h +++ b/include/tpm_api.h @@ -319,4 +319,14 @@ u32 tpm_write_lock(struct udevice *dev, u32 index); */ u32 tpm_resume(struct udevice *dev); +static inline bool tpm_is_v1(struct udevice *dev) +{ + return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1; +} + +static inline bool tpm_is_v2(struct udevice *dev) +{ + return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2; +} + #endif /* __TPM_API_H */ diff --git a/lib/tpm_api.c b/lib/tpm_api.c index 4c662640a9..4ac4612c81 100644 --- a/lib/tpm_api.c +++ b/lib/tpm_api.c @@ -11,21 +11,11 @@ #include #include -static bool is_tpm1(struct udevice *dev) -{ - return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1; -} - -static bool is_tpm2(struct udevice *dev) -{ - return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2; -} - u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) { - if (is_tpm1(dev)) { + if (tpm_is_v1(dev)) { return tpm1_startup(dev, mode); - } else if (is_tpm2(dev)) { + } else if (tpm_is_v2(dev)) { enum tpm2_startup_types type; switch (mode) { @@ -47,9 +37,9 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) u32 tpm_resume(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_startup(dev, TPM_ST_STATE); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_startup(dev, TPM2_SU_STATE); else return -ENOSYS; @@ -57,9 +47,9 @@ u32 tpm_resume(struct udevice *dev) u32 tpm_self_test_full(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_self_test_full(dev); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_self_test(dev, TPMI_YES); else return -ENOSYS; @@ -67,9 +57,9 @@ u32 tpm_self_test_full(struct udevice *dev) u32 tpm_continue_self_test(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_continue_self_test(dev); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_self_test(dev, TPMI_NO); else return -ENOSYS; @@ -86,7 +76,7 @@ u32 tpm_clear_and_reenable(struct udevice *dev) return ret; } - if (is_tpm1(dev)) { + if (tpm_is_v1(dev)) { ret = tpm1_physical_enable(dev); if (ret != TPM_SUCCESS) { log_err("TPM: Can't set enabled state\n"); @@ -105,9 +95,9 @@ u32 tpm_clear_and_reenable(struct udevice *dev) u32 tpm_nv_enable_locking(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return -ENOSYS; else return -ENOSYS; @@ -115,9 +105,9 @@ u32 tpm_nv_enable_locking(struct udevice *dev) u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_nv_read_value(dev, index, data, count); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_nv_read_value(dev, index, data, count); else return -ENOSYS; @@ -126,9 +116,9 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, u32 count) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_nv_write_value(dev, index, data, count); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_nv_write_value(dev, index, data, count); else return -ENOSYS; @@ -141,9 +131,9 @@ u32 tpm_set_global_lock(struct udevice *dev) u32 tpm_write_lock(struct udevice *dev, u32 index) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return -ENOSYS; - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_write_lock(dev, index); else return -ENOSYS; @@ -152,9 +142,9 @@ u32 tpm_write_lock(struct udevice *dev, u32 index) u32
[PATCH v7 0/7] tpm: rng: Move TPM RNG functionality to driver model
The TPM device provides the random number generator(RNG) functionality, whereby sending a command to the TPM device results in the TPM device responding with random bytes. There was a discussion on the mailing list earlier[1], where it was explained that platforms with a TPM device can install the EFI_RNG_PROTOCOL for getting the random bytes instead of populating the dtb with the kaslr-seed property. That would make it possible to measure the dtb. The TPM uclass driver adds the RNG child device as part of it's post_probe function. Some additional changes have also been made to facilitate the use of the RNG devices, including extending the 'rng' command to take the RNG device as one of the command-line parameters. This series depends on a patch[2] from Simon Glass for moving the TPM device version detection functions to the tpm_api.h header as static inline functions. These patches were under discussion earlier, specifically the patch to add the RNG functionality under the TPM device as a child, either through manual binding or through the device tree. Ilias had commented on the discussion last[3]. The discussion can be resumed through this version. I have dropped certain patches which were changing some of the TPM API functions to return an int instead of the current u32. These patches have been dropped due to review comments from Simon[4]. This work can be taken up separately, if desired. [1] - https://lore.kernel.org/u-boot/20220103120738.47835-1-ilias.apalodi...@linaro.org/ [2] - https://lore.kernel.org/u-boot/20220301001125.1554442-2-...@chromium.org/T/#u [3] - https://lists.denx.de/pipermail/u-boot/2022-April/481708.html [4] - https://lists.denx.de/pipermail/u-boot/2022-March/477883.html Simon Glass (1): tpm: Export the TPM-version functions Sughosh Ganu (6): tpm: rng: Add driver model interface for TPM RNG device tpm: Add the RNG child device cmd: rng: Add support for selecting RNG device cmd: rng: Use a statically allocated array for random bytes doc: rng: Add documentation for the rng command test: rng: Add a UT testcase for the rng command cmd/Kconfig | 1 + cmd/rng.c| 42 +++-- doc/usage/cmd/rng.rst| 26 +++ doc/usage/index.rst | 1 + drivers/rng/Kconfig | 9 drivers/rng/Makefile | 1 + drivers/rng/tpm_rng.c| 23 ++ drivers/tpm/tpm-uclass.c | 37 +-- include/tpm_api.h| 10 lib/Kconfig | 1 + lib/tpm_api.c| 98 ++-- test/dm/rng.c| 29 12 files changed, 205 insertions(+), 73 deletions(-) create mode 100644 doc/usage/cmd/rng.rst create mode 100644 drivers/rng/tpm_rng.c -- 2.34.1
Re: [PATCH v7 12/13] mkeficapsule: Add support for setting OEM flags in capsule header
hi Ilias, On Fri, 15 Jul 2022 at 22:11, Ilias Apalodimas wrote: > > Hi Sughosh, > > On Thu, 14 Jul 2022 at 21:40, Sughosh Ganu wrote: > > > > Add support for setting OEM flags in the capsule header. As per the > > UEFI specification, bits 0-15 of the flags member of the capsule > > header can be defined per capsule GUID. > > > > The oemflags will be used for the FWU Multi Bank update feature, as > > specified by the Dependable Boot specification[1]. Bit > > 15 of the flags member will be used to determine if the > > acceptance/rejection of the updated images is to be done by the > > firmware or an external component like the OS. > > Have we documented bit15 in the documentation? If not please add it. Yes, the use of bit15 has been added in the documentation for this feature. I will incorporate all your review comments, and in case I hit any issues while incorporating any review comment, I will respond to that. Thanks for the review. -sughosh > > > > > [1] - > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf > > > > Signed-off-by: Sughosh Ganu > > --- > > Changes since V6: None > > > > doc/mkeficapsule.1 | 4 > > tools/mkeficapsule.c | 17 ++--- > > 2 files changed, 18 insertions(+), 3 deletions(-) > > > > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 > > index 77ca061efd..6fb2dd0810 100644 > > --- a/doc/mkeficapsule.1 > > +++ b/doc/mkeficapsule.1 > > @@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule > > .BI "-R\fR,\fB --fw-revert " > > Generate a firmware revert empty capsule > > > > +.TP > > +.BI "-o\fR,\fB --capoemflag " > > +Capsule OEM flag, value between 0x to 0x > > + > > .TP > > .BR -h ", " --help > > Print a help message > > diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c > > index 244c80e1f7..237c1218fd 100644 > > --- a/tools/mkeficapsule.c > > +++ b/tools/mkeficapsule.c > > @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule"; > > efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; > > efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; > > > > -static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; > > +static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR"; > > > > enum { > > CAPSULE_NORMAL_BLOB = 0, > > @@ -47,6 +47,7 @@ static struct option options[] = { > > {"dump-sig", no_argument, NULL, 'd'}, > > {"fw-accept", no_argument, NULL, 'A'}, > > {"fw-revert", no_argument, NULL, 'R'}, > > + {"capoemflag", required_argument, NULL, 'o'}, > > {"help", no_argument, NULL, 'h'}, > > {NULL, 0, NULL, 0}, > > }; > > @@ -65,6 +66,7 @@ static void print_usage(void) > > "\t-d, --dump_sig dump signature (*.p7)\n" > > "\t-A, --fw-accept firmware accept capsule, requires GUID, > > no image blob\n" > > "\t-R, --fw-revert firmware revert capsule, takes no GUID, > > no image blob\n" > > + "\t-o, --capoemflag Capsule OEM Flag, an integer between > > 0x and 0x\n" > > "\t-h, --help print a help message\n", > > tool_name); > > } > > @@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx) > > * @mcount:Monotonic count in authentication information > > * @private_file: Path to a private key file > > * @cert_file: Path to a certificate file > > + * @oemflags: Capsule OEM Flags, bits 0-15 > > * > > * This function actually does the job of creating an uefi capsule file. > > * All the arguments must be supplied. > > @@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx) > > */ > > static int create_fwbin(char *path, char *bin, efi_guid_t *guid, > > unsigned long index, unsigned long instance, > > - uint64_t mcount, char *privkey_file, char > > *cert_file) > > + uint64_t mcount, char *privkey_file, char > > *cert_file, > > + uint16_t oemflags) > > { > > struct efi_capsule_header header; > > struct efi_firmware_management_capsule_header capsule; > > @@ -464,6 +468,8 @@ static int create_fwbin
Re: [PATCH v7 01/13] dt/bindings: Add bindings for FWU Metadata storage device
On Sun, 17 Jul 2022 at 02:43, Jassi Brar wrote: > > On Thu, 14 Jul 2022 at 13:39, Sughosh Ganu wrote: > > > > Add bindings needed for accessing the FWU metadata partitions. These > > include the compatible string which point to the access method and the > > actual device which stores the FWU metadata. > > > > The current patch adds basic bindings needed for accessing the > > metadata structure on GPT partitioned block devices. > > > > Signed-off-by: Sughosh Ganu > > --- > > Changes since V6: None > > > > .../firmware/fwu-mdata.yaml | 32 +++ > > 1 file changed, 32 insertions(+) > > create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.yaml > > > > diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.yaml > > b/doc/device-tree-bindings/firmware/fwu-mdata.yaml > > new file mode 100644 > > index 00..97d30bd1c1 > > --- /dev/null > > +++ b/doc/device-tree-bindings/firmware/fwu-mdata.yaml > > > I think we want to call it fwu-mdata-gpt.yaml ? Yes, makes sense. Will rename it. Thanks. -sughosh
[PATCH v7 13/13] FWU: doc: Add documentation for the FWU feature
Add documentattion for the FWU Multi Bank Update feature. The document describes the steps needed for setting up the platform for the feature, as well as steps for enabling the feature on the platform. Signed-off-by: Sughosh Ganu --- Changes since V6: None doc/develop/uefi/fwu_updates.rst | 156 +++ doc/develop/uefi/index.rst | 1 + doc/develop/uefi/uefi.rst| 2 + 3 files changed, 159 insertions(+) create mode 100644 doc/develop/uefi/fwu_updates.rst diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst new file mode 100644 index 00..57d1b5b703 --- /dev/null +++ b/doc/develop/uefi/fwu_updates.rst @@ -0,0 +1,156 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (c) 2022 Linaro Limited + +FWU Multi Bank Updates in U-Boot + + +The FWU Multi Bank Update feature implements the firmware update +mechanism described in the PSA Firmware Update for A-profile Arm +Architecture specification[1]. Certain aspects of the Dependable +Boot specification[2] are also implemented. The feature provides a +mechanism to have multiple banks of updatable firmware images and for +updating the firmware images on the non-booted bank. On a successful +update, the platform boots from the updated bank on subsequent +boot. The UEFI capsule-on-disk update feature is used for performing +the actual updates of the updatable firmware images. + +The bookkeeping of the updatable images is done through a structure +called metadata. Currently, the FWU metadata supports identification +of images based on image GUIDs stored on a GPT partitioned storage +media. There are plans to extend the metadata structure for non GPT +partitioned devices as well. + +Accessing the FWU metadata is done through generic API's which are +defined in a driver which complies with the u-boot's driver model. A +new uclass UCLASS_FWU_MDATA has been added for accessing the FWU +metadata. Individual drivers can be added based on the type of storage +media, and it's partitioning method. Details of the storage device +containing the FWU metadata partitions are specified through a U-Boot +specific device tree property `fwu-mdata-store`. Please refer to +U-Boot `doc `__ for +the device tree bindings. + +Enabling the FWU Multi Bank Update feature +-- + +The feature can be enabled by specifying the following configs:: + +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y +CONFIG_EFI_CAPSULE_FIRMWARE=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y + +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_CMD_FWU_METADATA=y +CONFIG_DM_FWU_MDATA=y +CONFIG_FWU_MDATA_GPT_BLK=y +CONFIG_FWU_NUM_BANKS= +CONFIG_FWU_NUM_IMAGES_PER_BANK= + +in the .config file + +The first group of configs enable the UEFI capsule-on-disk update +functionality. The second group of configs 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. + +Setting up the device for GPT partitioned storage +- + +Before enabling the functionality in U-Boot, certain changes are +required to be done on the storage device. Assuming a GPT partitioned +storage device, the storage media needs to be partitioned with the +correct number of partitions, given the number of banks and number of +images per bank that the platform is going to support. Each updatable +firmware image will be stored on an separate partition. In addition, +the two copies of the FWU metadata will be stored on two separate +partitions. + +As an example, a platform supporting two banks with each bank +containing three images would need to have 2 * 3 = 6 parititions plus +the two metadata partitions, or 8 partitions. In addition the storage +media can have additional partitions of non-updatable images, like the +EFI System Partition(ESP), a partition for the root file system etc. + +When generating the partitions, a few aspects need to be taken care +of. Each GPT partition entry in the GPT header has two GUIDs:: + +*PartitionTypeGUID* +*UniquePartitionGUID* + +The PartitionTypeGUID value should correspond to the *image_type_uuid* +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* +field in the FWU metadata. This GUID is used to identify images of a +given image type in different banks. + +Similarly, the FWU specifications defines the GUID value to be used +for the metadata partitions. This would be the PartitionTypeGUID for +the metadata partitions. + +When generating the metadata, the *image_type_uuid* and the +*image_uuid* values should match
[PATCH v7 12/13] mkeficapsule: Add support for setting OEM flags in capsule header
Add support for setting OEM flags in the capsule header. As per the UEFI specification, bits 0-15 of the flags member of the capsule header can be defined per capsule GUID. The oemflags will be used for the FWU Multi Bank update feature, as specified by the Dependable Boot specification[1]. Bit 15 of the flags member will be used to determine if the acceptance/rejection of the updated images is to be done by the firmware or an external component like the OS. [1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Signed-off-by: Sughosh Ganu --- Changes since V6: None doc/mkeficapsule.1 | 4 tools/mkeficapsule.c | 17 ++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 77ca061efd..6fb2dd0810 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule .BI "-R\fR,\fB --fw-revert " Generate a firmware revert empty capsule +.TP +.BI "-o\fR,\fB --capoemflag " +Capsule OEM flag, value between 0x to 0x + .TP .BR -h ", " --help Print a help message diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 244c80e1f7..237c1218fd 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; -static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; +static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR"; enum { CAPSULE_NORMAL_BLOB = 0, @@ -47,6 +47,7 @@ static struct option options[] = { {"dump-sig", no_argument, NULL, 'd'}, {"fw-accept", no_argument, NULL, 'A'}, {"fw-revert", no_argument, NULL, 'R'}, + {"capoemflag", required_argument, NULL, 'o'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -65,6 +66,7 @@ static void print_usage(void) "\t-d, --dump_sig dump signature (*.p7)\n" "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n" "\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n" + "\t-o, --capoemflag Capsule OEM Flag, an integer between 0x and 0x\n" "\t-h, --help print a help message\n", tool_name); } @@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx) * @mcount:Monotonic count in authentication information * @private_file: Path to a private key file * @cert_file: Path to a certificate file + * @oemflags: Capsule OEM Flags, bits 0-15 * * This function actually does the job of creating an uefi capsule file. * All the arguments must be supplied. @@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx) */ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, unsigned long index, unsigned long instance, - uint64_t mcount, char *privkey_file, char *cert_file) + uint64_t mcount, char *privkey_file, char *cert_file, + uint16_t oemflags) { struct efi_capsule_header header; struct efi_firmware_management_capsule_header capsule; @@ -464,6 +468,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, header.header_size = sizeof(header); /* TODO: The current implementation ignores flags */ header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + if (oemflags) + header.flags |= oemflags; header.capsule_image_size = sizeof(header) + sizeof(capsule) + sizeof(uint64_t) + sizeof(image) @@ -635,6 +641,7 @@ int main(int argc, char **argv) unsigned char uuid_buf[16]; unsigned long index, instance; uint64_t mcount; + uint16_t oemflags; char *privkey_file, *cert_file; int c, idx; @@ -646,6 +653,7 @@ int main(int argc, char **argv) cert_file = NULL; dump_sig = 0; capsule_type = CAPSULE_NORMAL_BLOB; + oemflags = 0; for (;;) { c = getopt_long(argc, argv, opts_short, options, ); if (c == -1) @@ -699,6 +707,9 @@ int main(int argc, char **argv) case 'R': capsule_type |= CAPSULE_REVERT; break; + case 'o': + oemflags = strtoul(optarg, NULL, 0); + break; default: print_usage();
[PATCH v7 11/13] mkeficapsule: Add support for generating empty capsules
The Dependable Boot specification[1] describes the structure of the firmware accept and revert capsules. These are empty capsules which are used for signalling the acceptance or rejection of the updated firmware by the OS. Add support for generating these empty capsules. [1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Signed-off-by: Sughosh Ganu --- Changes since V6: None doc/mkeficapsule.1 | 29 ++ tools/eficapsule.h | 8 tools/mkeficapsule.c | 92 3 files changed, 115 insertions(+), 14 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 09bdc24295..77ca061efd 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot .SH SYNOPSIS .B mkeficapsule -.RI [ options "] " image-blob " " capsule-file +.RI [ options ] " " [ image-blob ] " " capsule-file .SH "DESCRIPTION" .B mkeficapsule @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given private key. In this case, the update will be authenticated by verifying the signature before applying. +Additionally, an empty capsule file can be generated for acceptance or +rejection of firmware images by a governing component like an Operating +System. The empty capsules do not require an image-blob input file. + + .B mkeficapsule -takes any type of image files, including: +takes any type of image files when generating non empty capsules, including: .TP .I raw image format is a single binary blob of any type of firmware. @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file. This type of image file can be generated by .BR mkimage . -.PP -If you want to use other types than above two, you should explicitly -specify a guid for the FMP driver. - .SH "OPTIONS" + .TP .BI "-g\fR,\fB --guid " guid-string Specify guid for image blob type. The format is: ---- The first three elements are in little endian, while the rest -is in big endian. +is in big endian. The option must be specified for all non empty and +image acceptance capsules .TP .BI "-i\fR,\fB --index " index @@ -57,6 +60,18 @@ Specify an image index .BI "-I\fR,\fB --instance " instance Specify a hardware instance +.PP +For generation of firmware accept empty capsule +.BR --guid +is mandatory +.TP +.BI "-A\fR,\fB --fw-accept " +Generate a firmware acceptance empty capsule + +.TP +.BI "-R\fR,\fB --fw-revert " +Generate a firmware revert empty capsule + .TP .BR -h ", " --help Print a help message diff --git a/tools/eficapsule.h b/tools/eficapsule.h index d63b831443..072a4b5598 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -41,6 +41,14 @@ typedef struct { EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \ 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) +#define FW_ACCEPT_OS_GUID \ + EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) + +#define FW_REVERT_OS_GUID \ + EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \ +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0) + /* flags */ #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x0001 diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 5f74d23b9e..244c80e1f7 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,13 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; -static const char *opts_short = "g:i:I:v:p:c:m:dh"; +static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; + +enum { + CAPSULE_NORMAL_BLOB = 0, + CAPSULE_ACCEPT, + CAPSULE_REVERT, +} capsule_type; static struct option options[] = { {"guid", required_argument, NULL, 'g'}, @@ -39,6 +45,8 @@ static struct option options[] = { {"certificate", required_argument, NULL, 'c'}, {"monotonic-count", required_argument, NULL, 'm'}, {"dump-sig", no_argument, NULL, 'd'}, + {"fw-accept", no_argument, NULL, 'A'}, + {"fw-revert", no_argument, NULL, 'R'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -55,6 +63,8 @@ static void print_usage(void) "\t-c, --certificate signer's certificate file\n" "\t-m, --monotonic-count monotonic count\n" "\t-d, --dump_sig dump signature (*.p7)\n" + "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n" + "\t-R, --fw-revert
[PATCH v7 10/13] FWU: cmd: Add a command to read FWU metadata
Add a command to read the metadata as specified in the FWU specification and print the fields of the metadata. Signed-off-by: Sughosh Ganu --- Changes since V6: None cmd/Kconfig | 7 + cmd/Makefile| 1 + cmd/fwu_mdata.c | 80 + 3 files changed, 88 insertions(+) create mode 100644 cmd/fwu_mdata.c diff --git a/cmd/Kconfig b/cmd/Kconfig index d5f842136c..2110f59f6a 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -161,6 +161,13 @@ config CMD_CPU internal name) and clock frequency. Other information may be available depending on the CPU driver. +config CMD_FWU_METADATA + bool "fwu metadata read" + depends on FWU_MULTI_BANK_UPDATE + default y + help + Command to read the metadata and dump it's contents + config CMD_LICENSE bool "license" select BUILD_BIN2C diff --git a/cmd/Makefile b/cmd/Makefile index 5e43a1e022..259a93bc65 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_FPGA) += fpga.o obj-$(CONFIG_CMD_FPGAD) += fpgad.o obj-$(CONFIG_CMD_FS_GENERIC) += fs.o obj-$(CONFIG_CMD_FUSE) += fuse.o +obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o obj-$(CONFIG_CMD_GETTIME) += gettime.o obj-$(CONFIG_CMD_GPIO) += gpio.o obj-$(CONFIG_CMD_HVC) += smccc.o diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c new file mode 100644 index 00..ee9d035374 --- /dev/null +++ b/cmd/fwu_mdata.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static void print_mdata(struct fwu_mdata *mdata) +{ + 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("\tImage Info\n"); + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { + img_entry = >img_entry[i]; + printf("\nImage Type Guid: %pUL\n", + _entry->image_type_uuid); + printf("Location Guid: %pUL\n", _entry->location_uuid); + for (j = 0; j < CONFIG_FWU_NUM_BANKS; j++) { + img_info = _entry->img_bank_info[j]; + printf("Image Guid: %pUL\n", _info->image_uuid); + printf("Image Acceptance: %s\n", + img_info->accepted == 0x1 ? "yes" : "no"); + } + } +} + +int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, +int argc, char * const argv[]) +{ + struct udevice *dev; + int ret = CMD_RET_SUCCESS, res; + struct fwu_mdata *mdata = NULL; + + if (uclass_get_device(UCLASS_FWU_MDATA, 0, ) || !dev) { + log_err("Unable to get FWU metadata device\n"); + return CMD_RET_FAILURE; + } + + res = fwu_mdata_check(); + if (res < 0) { + log_err("FWU Metadata check failed\n"); + ret = CMD_RET_FAILURE; + goto out; + } + + res = fwu_get_mdata(); + if (res < 0) { + log_err("Unable to get valid FWU metadata\n"); + ret = CMD_RET_FAILURE; + goto out; + } + + print_mdata(mdata); + +out: + free(mdata); + return ret; +} + +U_BOOT_CMD( + fwu_mdata_read, 1, 1, do_fwu_mdata_read, + "Read and print FWU metadata", + "" +); -- 2.34.1
[PATCH v7 09/13] FWU: Add support for the FWU Multi Bank Update feature
The FWU Multi Bank Update feature supports updation of firmware images to one of multiple sets(also called banks) of images. The firmware images are clubbed together in banks, with the system booting images from the active bank. Information on the images such as which bank they belong to is stored as part of the metadata structure, which is stored on the same storage media as the firmware images on a dedicated partition. At the time of update, the metadata is read to identify the bank to which the images need to be flashed(update bank). On a successful update, the metadata is modified to set the updated bank as active bank to subsequently boot from. Signed-off-by: Sughosh Ganu --- Changes since V6: None include/fwu.h| 10 ++ lib/Kconfig | 6 + lib/Makefile | 1 + lib/efi_loader/efi_capsule.c | 231 ++- lib/efi_loader/efi_setup.c | 3 +- lib/fwu_updates/Kconfig | 31 + lib/fwu_updates/Makefile | 3 +- lib/fwu_updates/fwu.c| 26 8 files changed, 304 insertions(+), 7 deletions(-) create mode 100644 lib/fwu_updates/Kconfig diff --git a/include/fwu.h b/include/fwu.h index b374fd1179..7ff1cd75d3 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -32,13 +32,23 @@ struct fwu_mdata_ops { }; #define FWU_MDATA_VERSION 0x1 +#define FWU_IMAGE_ACCEPTED 0x1 #define FWU_MDATA_GUID \ EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) +#define FWU_OS_REQUEST_FW_REVERT_GUID \ + EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \ +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0) + +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \ + EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) + u8 fwu_update_checks_pass(void); int fwu_boottime_checks(void); +int fwu_trial_state_ctr_start(void); int fwu_get_mdata(struct fwu_mdata **mdata); int fwu_update_mdata(struct fwu_mdata *mdata); diff --git a/lib/Kconfig b/lib/Kconfig index 7dd777b56a..0e5390597c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -967,3 +967,9 @@ config LMB_RESERVED_REGIONS memory blocks. endmenu + +menu "FWU Multi Bank Updates" + +source lib/fwu_updates/Kconfig + +endmenu diff --git a/lib/Makefile b/lib/Makefile index e3deb15287..f2cfd1e428 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_EFI_LOADER) += efi_driver/ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/ obj-$(CONFIG_LZMA) += lzma/ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_FIT) += libfdt/ diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index a6b98f066a..18a356ba08 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,17 @@ static const efi_guid_t efi_guid_firmware_management_capsule_id = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; const efi_guid_t efi_guid_firmware_management_protocol = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; +const efi_guid_t fwu_guid_os_request_fw_revert = + FWU_OS_REQUEST_FW_REVERT_GUID; +const efi_guid_t fwu_guid_os_request_fw_accept = + FWU_OS_REQUEST_FW_ACCEPT_GUID; + +#define FW_ACCEPT_OS (u32)0x8000 + +__maybe_unused static u32 update_index; +__maybe_unused static bool capsule_update; +__maybe_unused static bool fw_accept_os; +static bool image_index_check = true; #ifdef CONFIG_EFI_CAPSULE_ON_DISK /* for file system access */ @@ -205,7 +217,8 @@ efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance, log_debug("+++ desc[%d] index: %d, name: %ls\n", j, desc->image_index, desc->image_id_name); if (!guidcmp(>image_type_id, image_type) && - (desc->image_index == image_index) && + (!image_index_check || +desc->image_index == image_index) && (!instance || !desc->hardware_instance || desc->hardware_instance == instance)) @@ -388,6 +401,87 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s } #endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */ +static bool fwu_empty_capsule(struct efi_capsule_header *capsule) +{ + return !guidcmp(>capsule_guid, + _guid_os_request_fw_revert) || + !guidcmp(>capsule_guid, +_guid_os_request_fw_accept); +} + +static efi_status_t fwu_empty_capsule_process( + struct efi_capsule_header *capsule)
[PATCH v7 08/13] FWU: Add boot time checks as highlighted by the FWU specification
The FWU Multi Bank Update specification requires the Update Agent to carry out certain checks at the time of platform boot. The Update Agent is the component which is responsible for updating the firmware components and maintaining and keeping the metadata in sync. The spec requires that the Update Agent perform the following checks at the time of boot * Sanity check of both the metadata copies maintained by the platform. * Get the boot index passed to U-Boot by the prior stage bootloader and use this value for metadata bookkeeping. * Check if the system is booting in Trial State. If the system boots in the Trial State for more than a specified number of boot counts, change the Active Bank to be booting the platform from. Add these checks in the board initialisation sequence, invoked after relocation. Signed-off-by: Sughosh Ganu --- Changes since V6: None common/board_r.c | 5 ++ include/fwu.h | 3 + lib/fwu_updates/fwu.c | 165 ++ 3 files changed, 173 insertions(+) create mode 100644 lib/fwu_updates/fwu.c diff --git a/common/board_r.c b/common/board_r.c index ed29069d2d..5210ed6f32 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -785,6 +786,10 @@ static init_fnc_t init_sequence_r[] = { #if defined(CONFIG_PRAM) initr_mem, #endif + +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE + fwu_boottime_checks, +#endif run_main_loop, }; diff --git a/include/fwu.h b/include/fwu.h index edb28c9659..b374fd1179 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -37,6 +37,9 @@ struct fwu_mdata_ops { EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) +u8 fwu_update_checks_pass(void); +int fwu_boottime_checks(void); + int fwu_get_mdata(struct fwu_mdata **mdata); int fwu_update_mdata(struct fwu_mdata *mdata); int fwu_get_active_index(u32 *active_idx); diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c new file mode 100644 index 00..10a0522333 --- /dev/null +++ b/lib/fwu_updates/fwu.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static u8 trial_state; +static u8 boottime_check; + +static int fwu_trial_state_check(void) +{ + int ret, i; + efi_status_t status; + efi_uintn_t var_size; + u16 trial_state_ctr; + u32 nimages, active_bank, var_attributes, active_idx; + struct fwu_mdata *mdata = NULL; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_bank_info; + + ret = fwu_get_mdata(); + if (ret) + return ret; + + ret = 0; + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; + active_bank = mdata->active_index; + img_entry = >img_entry[0]; + for (i = 0; i < nimages; i++) { + img_bank_info = _entry[i].img_bank_info[active_bank]; + if (!img_bank_info->accepted) { + trial_state = 1; + break; + } + } + + if (trial_state) { + var_size = (efi_uintn_t)sizeof(trial_state_ctr); + log_info("System booting in Trial State\n"); + var_attributes = EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS; + status = efi_get_variable_int(u"TrialStateCtr", + _global_variable_guid, + _attributes, + _size, _state_ctr, + NULL); + if (status != EFI_SUCCESS) { + log_err("Unable to read TrialStateCtr variable\n"); + ret = -1; + goto out; + } + + ++trial_state_ctr; + if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) { + log_info("Trial State count exceeded. Revert back to previous_active_index\n"); + active_idx = mdata->active_index; + ret = fwu_revert_boot_index(); + if (ret) { + log_err("Unable to revert active_index\n"); + goto out; + } + + /* Delete the TrialStateCtr variable */ + status = efi_set_variable_int(u"TrialStateCtr", + _global_variable_guid, + var_attributes, +
[PATCH v7 07/13] FWU: STM32MP1: Add support to read boot index from backup register
The FWU Multi Bank Update feature allows the platform to boot the firmware images from one of the partitions(banks). The first stage bootloader(fsbl) passes the value of the boot index, i.e. the bank from which the firmware images were booted from to U-Boot. On the STM32MP157C-DK2 board, this value is passed through one of the SoC's backup register. Add a function to read the boot index value from the backup register. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V6: None arch/arm/mach-stm32mp/include/mach/stm32.h | 5 + board/st/stm32mp1/stm32mp1.c | 8 include/fwu.h | 1 + 3 files changed, 14 insertions(+) diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index c70375a723..c85ae6a34e 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -112,11 +112,16 @@ enum boot_device { #ifdef CONFIG_STM32MP15x #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) +#define TAMP_FWU_BOOT_INFO_REG TAMP_BACKUP_REGISTER(10) #define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) #define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) #define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21) +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) + +#define TAMP_FWU_BOOT_IDX_OFFSET 0 + #define TAMP_COPRO_STATE_OFF 0 #define TAMP_COPRO_STATE_INIT 1 #define TAMP_COPRO_STATE_CRUN 2 diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 44c7943f1d..ddf5053601 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -1001,4 +1001,12 @@ int fwu_plat_get_update_index(u32 *update_idx) return ret; } + +void fwu_plat_get_bootidx(void *boot_idx) +{ + u32 *bootidx = boot_idx; + + *bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >> + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; +} #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/include/fwu.h b/include/fwu.h index 38dceca9c5..edb28c9659 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -49,6 +49,7 @@ int fwu_revert_boot_index(void); int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); +void fwu_plat_get_bootidx(void *boot_idx); int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, int *alt_num); int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, -- 2.34.1
[PATCH v7 06/13] FWU: stm32mp1: Add helper functions for accessing FWU metadata
Add helper functions needed for accessing the FWU metadata which contains information on the updatable images. These functions have been added for the STM32MP157C-DK2 board which has the updatable images on the uSD card, formatted as GPT partitions. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V6: None board/st/stm32mp1/stm32mp1.c | 40 include/fwu.h| 3 ++ lib/fwu_updates/Makefile | 6 +++ lib/fwu_updates/fwu_gpt.c| 88 4 files changed, 137 insertions(+) create mode 100644 lib/fwu_updates/Makefile create mode 100644 lib/fwu_updates/fwu_gpt.c diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index e3a04f8d8a..44c7943f1d 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -25,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -962,3 +966,39 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size) } U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); + +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) + +#include +#include + +int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, +int *alt_num) +{ + struct blk_desc *desc; + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); + + desc = dev_get_uclass_plat(priv->blk_dev); + if (!desc) { + log_err("Block device not found\n"); + return -ENODEV; + } + + return fwu_gpt_get_alt_num(desc, image_guid, alt_num, DFU_DEV_MMC); +} + +int fwu_plat_get_update_index(u32 *update_idx) +{ + int ret; + u32 active_idx; + + ret = fwu_get_active_index(_idx); + + if (ret < 0) + return -1; + + *update_idx = active_idx ^= 0x1; + + return ret; +} +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/include/fwu.h b/include/fwu.h index 8259c75d12..38dceca9c5 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -51,4 +51,7 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, int *alt_num); +int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, + int *alt_num, unsigned char dfu_dev); +int fwu_plat_get_update_index(u32 *update_idx); #endif /* _FWU_H_ */ diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile new file mode 100644 index 00..5a59e4a833 --- /dev/null +++ b/lib/fwu_updates/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2022, Linaro Limited +# + +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c new file mode 100644 index 00..434ec76bde --- /dev/null +++ b/lib/fwu_updates/fwu_gpt.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include + +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t *image_guid) +{ + int i; + struct disk_partition info; + efi_guid_t unique_part_guid; + + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { + if (part_get_info(desc, i, )) + continue; + uuid_str_to_bin(info.uuid, unique_part_guid.b, + UUID_STR_FORMAT_GUID); + + if (!guidcmp(_part_guid, image_guid)) + return i; + } + + log_err("No partition found with image_guid %pUs\n", image_guid); + return -ENOENT; +} + +int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, + int *alt_num, unsigned char dfu_dev) +{ + int ret = -1; + int i, part, dev_num; + int nalt; + struct dfu_entity *dfu; + + dev_num = desc->devnum; + part = get_gpt_dfu_identifier(desc, image_guid); + if (part < 0) + return -ENOENT; + + dfu_init_env_entities(NULL, NULL); + + nalt = 0; + list_for_each_entry(dfu, _list, list) { + nalt++; + } + + if (!nalt) { + log_warning("No entities in dfu_alt_info\n"); + dfu_free_entities(); + return -ENOENT; + } + + for (i = 0; i < nalt; i++) { + dfu = dfu_get_entity(i); + + if (!dfu) + continue; + + /* +* Currently, Multi Bank update +* feature is being supported +* only on GPT partitioned +* MMC/SD devi
[PATCH v7 05/13] stm32mp1: dk2: Add image information for capsule updates
Enabling capsule update functionality on the platform requires populating information on the images that are to be updated using the functionality. Do so for the DK2 board. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V6: * s/STM32MP1/STM32MP15/ as suggested by Patrick board/st/stm32mp1/stm32mp1.c | 19 +++ include/configs/stm32mp15_common.h | 4 2 files changed, 23 insertions(+) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 9496890d16..e3a04f8d8a 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,16 @@ #define USB_START_LOW_THRESHOLD_UV 123 #define USB_START_HIGH_THRESHOLD_UV215 +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) +struct efi_fw_image fw_images[1]; + +struct efi_capsule_update_info update_info = { + .images = fw_images, +}; + +u8 num_image_type_guids = ARRAY_SIZE(fw_images); +#endif /* EFI_HAVE_CAPSULE_SUPPORT */ + int board_early_init_f(void) { /* nothing to do, only used in SPL */ @@ -670,6 +681,14 @@ int board_init(void) setup_led(LEDST_ON); +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) + if (board_is_stm32mp15x_dk2()) { + efi_guid_t image_type_guid = STM32MP15_DK2_FIP_IMAGE_GUID; + guidcpy(_images[0].image_type_id, _type_guid); + fw_images[0].fw_name = u"STM32MP15-DK2-FIP"; + fw_images[0].image_index = 5; + } +#endif return 0; } diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h index c5412ffeb3..6ab10d8ce5 100644 --- a/include/configs/stm32mp15_common.h +++ b/include/configs/stm32mp15_common.h @@ -34,6 +34,10 @@ #define CONFIG_SERVERIP 192.168.1.1 #endif +#define STM32MP15_DK2_FIP_IMAGE_GUID \ + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \ +0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) + /*/ #ifdef CONFIG_DISTRO_DEFAULTS /*/ -- 2.34.1
[PATCH v7 04/13] stm32mp1: dk2: Add a node for the FWU metadata device
The FWU metadata structure is accessed through the driver model interface. On the stm32mp157c-dk2 board, the FWU metadata is stored on the uSD card. Add the fwu-mdata node on the u-boot specifc dtsi file for accessing the metadata structure. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V6: None arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi index 06ef3a4095..24f86209db 100644 --- a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi @@ -4,3 +4,10 @@ */ #include "stm32mp157a-dk1-u-boot.dtsi" + +/ { + fwu-mdata { + compatible = "u-boot,fwu-mdata-gpt"; + fwu-mdata-store = <>; + }; +}; -- 2.34.1
[PATCH v7 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
In the FWU Multi Bank Update feature, the information about the updatable images is stored as part of the metadata, on a separate partition. Add a driver for reading from and writing to the metadata when the updatable images and the metadata are stored on a block device which is formated with GPT based partition scheme. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V6: * Define the LOG_CATEGORY macro as suggested by Patrick drivers/fwu-mdata/Kconfig | 9 + drivers/fwu-mdata/Makefile| 1 + drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410 ++ include/fwu.h | 5 + 4 files changed, 425 insertions(+) create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig index d6a21c8e19..d5edef19d6 100644 --- a/drivers/fwu-mdata/Kconfig +++ b/drivers/fwu-mdata/Kconfig @@ -5,3 +5,12 @@ config DM_FWU_MDATA Enable support for accessing FWU Metadata partitions. The FWU Metadata partitions reside on the same storage device which contains the other FWU updatable firmware images. + +config FWU_MDATA_GPT_BLK + bool "FWU Metadata access for GPT partitioned Block devices" + select PARTITION_TYPE_GUID + select PARTITION_UUIDS + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION + help + Enable support for accessing FWU Metadata on GPT partitioned + block devices. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile index e53a8c9983..313049f67a 100644 --- a/drivers/fwu-mdata/Makefile +++ b/drivers/fwu-mdata/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c new file mode 100644 index 00..f694c4369b --- /dev/null +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#define LOG_CATEGORY UCLASS_FWU_MDATA + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PRIMARY_PART BIT(0) +#define SECONDARY_PART BIT(1) +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) + +#define MDATA_READ BIT(0) +#define MDATA_WRITEBIT(1) + +static int gpt_get_mdata_partitions(struct blk_desc *desc, + u16 *primary_mpart, + u16 *secondary_mpart) +{ + int i, ret; + u32 mdata_parts; + efi_guid_t part_type_guid; + struct disk_partition info; + const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID; + + mdata_parts = 0; + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { + if (part_get_info(desc, i, )) + continue; + uuid_str_to_bin(info.type_guid, part_type_guid.b, + UUID_STR_FORMAT_GUID); + + if (!guidcmp(_mdata_guid, _type_guid)) { + ++mdata_parts; + if (!*primary_mpart) + *primary_mpart = i; + else + *secondary_mpart = i; + } + } + + if (mdata_parts != 2) { + log_err("Expect two copies of the FWU metadata instead of %d\n", + mdata_parts); + ret = -EINVAL; + } else { + ret = 0; + } + + return ret; +} + +static int gpt_get_mdata_disk_part(struct blk_desc *desc, + struct disk_partition *info, + u32 part_num) +{ + int ret; + char *mdata_guid_str = "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23"; + + ret = part_get_info(desc, part_num, info); + if (ret < 0) { + log_err("Unable to get the partition info for the FWU metadata part %d", + part_num); + return -1; + } + + /* Check that it is indeed the FWU metadata partition */ + if (!strncmp(info->type_guid, mdata_guid_str, UUID_STR_LEN)) { + /* Found the FWU metadata partition */ + return 0; + } + + return -1; +} + +static int gpt_read_write_mdata(struct blk_desc *desc, + struct fwu_mdata *mdata, + u8 access, u32 part_num) +{ + int ret; + u32 len, blk_start, blkcnt; + struct disk_partition info; + + ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1, +desc->blksz); + + ret = gpt_get_mdata_disk_p
[PATCH v7 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
In the FWU Multi Bank Update feature, the information about the updatable images is stored as part of the metadata, which is stored on a dedicated partition. Add the metadata structure, and a driver model uclass which provides functions to access the metadata. These are generic API's, and implementations can be added based on parameters like how the metadata partition is accessed and what type of storage device houses the metadata. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V6: * Define the LOG_CATEGORY macro as suggested by Patrick * Add some documentation in the fwu_get_mdata and fwu_update_mdata functions to describe the sequence of calls to be made for modifying the metadata, as suggested by Etienne drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/fwu-mdata/Kconfig| 7 + drivers/fwu-mdata/Makefile | 6 + drivers/fwu-mdata/fwu-mdata-uclass.c | 469 +++ include/dm/uclass-id.h | 1 + include/fwu.h| 49 +++ include/fwu_mdata.h | 67 8 files changed, 602 insertions(+) create mode 100644 drivers/fwu-mdata/Kconfig create mode 100644 drivers/fwu-mdata/Makefile create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c create mode 100644 include/fwu.h create mode 100644 include/fwu_mdata.h diff --git a/drivers/Kconfig b/drivers/Kconfig index 8b6fead351..75ac149d31 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -44,6 +44,8 @@ source "drivers/fuzz/Kconfig" source "drivers/fpga/Kconfig" +source "drivers/fwu-mdata/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/hwspinlock/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index d63fd1c04d..7710f18236 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -83,6 +83,7 @@ obj-y += cache/ obj-$(CONFIG_CPU) += cpu/ obj-y += crypto/ obj-$(CONFIG_FASTBOOT) += fastboot/ +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/ obj-y += misc/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_NVME) += nvme/ diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig new file mode 100644 index 00..d6a21c8e19 --- /dev/null +++ b/drivers/fwu-mdata/Kconfig @@ -0,0 +1,7 @@ +config DM_FWU_MDATA + bool "Driver support for accessing FWU Metadata" + depends on DM + help + Enable support for accessing FWU Metadata partitions. The + FWU Metadata partitions reside on the same storage device + which contains the other FWU updatable firmware images. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile new file mode 100644 index 00..e53a8c9983 --- /dev/null +++ b/drivers/fwu-mdata/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2022, Linaro Limited +# + +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c new file mode 100644 index 00..4ba102ff81 --- /dev/null +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#define LOG_CATEGORY UCLASS_FWU_MDATA + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define IMAGE_ACCEPT_SET BIT(0) +#define IMAGE_ACCEPT_CLEAR BIT(1) + +static int fwu_get_dev_ops(struct udevice **dev, + const struct fwu_mdata_ops **ops) +{ + int ret; + + ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev); + if (ret) { + log_debug("Cannot find fwu device\n"); + return ret; + } + + if ((*ops = device_get_ops(*dev)) == NULL) { + log_debug("Cannot get fwu device ops\n"); + return -ENOSYS; + } + + return 0; +} + +/** + * fwu_verify_mdata() - Verify the FWU metadata + * @mdata: FWU metadata structure + * @pri_part: FWU metadata partition is primary or secondary + * + * Verify the FWU metadata by computing the CRC32 for the metadata + * structure and comparing it against the CRC32 value stored as part + * of the structure. + * + * Return: 0 if OK, -ve on error + * + */ +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part) +{ + u32 calc_crc32; + void *buf; + + buf = >version; + calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + + if (calc_crc32 != mdata->crc32) { + log_err("crc32 check failed for %s FWU metadata partition\n", + pri_part ? "primary" : "secondary"); + return -1; + } + + return 0; +} + +/** + * fwu_get_active_index() - Get active_index from the FWU metadata + * @active_idx: active_index value to be read + * + * Re
[PATCH v7 01/13] dt/bindings: Add bindings for FWU Metadata storage device
Add bindings needed for accessing the FWU metadata partitions. These include the compatible string which point to the access method and the actual device which stores the FWU metadata. The current patch adds basic bindings needed for accessing the metadata structure on GPT partitioned block devices. Signed-off-by: Sughosh Ganu --- Changes since V6: None .../firmware/fwu-mdata.yaml | 32 +++ 1 file changed, 32 insertions(+) create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.yaml diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.yaml b/doc/device-tree-bindings/firmware/fwu-mdata.yaml new file mode 100644 index 00..97d30bd1c1 --- /dev/null +++ b/doc/device-tree-bindings/firmware/fwu-mdata.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/firmware/fwu-mdata.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: FWU metadata on device with GPT partitioned layout + +maintainers: + - Sughosh Ganu + +properties: + compatible: +items: + - const: u-boot,fwu-mdata-gpt + + fwu-mdata-store: +maxItems: 1 +description: Phandle of the device which contains the FWU medatata partition. + +required: + - compatible + - fwu-mdata-store + +additionalProperties: false + +examples: + - | +fwu-mdata { +compatible = "u-boot,fwu-mdata-gpt"; +fwu-mdata-store = <>; +}; -- 2.34.1
[PATCH v7 00/13] FWU: Add FWU Multi Bank Update feature support
The patchset adds support for the FWU Multi Bank Update[1] feature. Certain aspects of the Dependable Boot[2] specification have also been implemented. The FWU multi bank update feature is used for supporting multiple sets(also called banks) of firmware image(s), allowing the platform to boot from a different bank, in case it fails to boot from the active bank. This functionality is supported by keeping the relevant information in a structure called metadata, which provides information on the images. Among other parameters, the metadata structure contains information on the currect active bank that is being used to boot image(s). Functionality is being added to work with the UEFI capsule driver in u-boot. The metadata is read to gather information on the update bank, which is the bank to which the firmware images would be flashed to. On a successful completion of the update of all components, the active bank field in the metadata is updated, to reflect the bank from which the platform will boot on the subsequent boots. Currently, the feature is being enabled on the STM32MP157C-DK2 and Synquacer boards. The DK2 board boots a FIP image from a uSD card partitioned with the GPT partioning scheme, while the Synquacer board boots a FIP image from a MTD partitioned SPI NOR flash device. This feature also requires changes in a previous stage of bootloader, which parses the metadata and selects the bank to boot the image(s) from. Support has being added in tf-a(BL2 stage) for the STM32MP157C-DK2 board to boot the active bank images. These changes have been merged to the upstream tf-a repository. The earlier patchset contained patches for both the DK2 and the Synquacer platforms. The handling of review comments for the Synquacer platform is to be taken up by a different engineer, and has not been done yet. After discussion with Tom Rini and Heinrich, it was decided to send the patches for the DK2 platform separately for review. The patch for adding a python test for the feature has been developed, and was sent in the version 5 of the patches[3]. However, the test script depends on adding support for the feature on MTD SPI NOR devices, and that is being done as part of the Synquacer patches. Hence these set of patches do not have the test script for the feature. That will be added through the patches for adding support for the feauture on Synquacer platform. [1] - https://developer.arm.com/documentation/den0118/a [2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf [3] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html Changes since V6: * Define the LOG_CATEGORY macro as suggested by Patrick * Add some documentation in the fwu_get_mdata and fwu_update_mdata functions to describe the sequence of calls to be made for modifying the metadata, as suggested by Etienn * Define the LOG_CATEGORY macro as suggested by Patrick * s/STM32MP1/STM32MP15/ as suggested by Patrick Sughosh Ganu (13): dt/bindings: Add bindings for FWU Metadata storage device FWU: Add FWU metadata structure and driver for accessing metadata FWU: Add FWU metadata access driver for GPT partitioned block devices stm32mp1: dk2: Add a node for the FWU metadata device stm32mp1: dk2: Add image information for capsule updates FWU: stm32mp1: Add helper functions for accessing FWU metadata FWU: STM32MP1: Add support to read boot index from backup register FWU: Add boot time checks as highlighted by the FWU specification FWU: Add support for the FWU Multi Bank Update feature FWU: cmd: Add a command to read FWU metadata mkeficapsule: Add support for generating empty capsules mkeficapsule: Add support for setting OEM flags in capsule header FWU: doc: Add documentation for the FWU feature arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 + arch/arm/mach-stm32mp/include/mach/stm32.h| 5 + board/st/stm32mp1/stm32mp1.c | 67 +++ cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/fwu_mdata.c | 80 +++ common/board_r.c | 5 + doc/develop/uefi/fwu_updates.rst | 156 ++ doc/develop/uefi/index.rst| 1 + doc/develop/uefi/uefi.rst | 2 + .../firmware/fwu-mdata.yaml | 32 ++ doc/mkeficapsule.1| 33 +- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/fwu-mdata/Kconfig | 16 + drivers/fwu-mdata/Makefile| 7 + drivers/fwu-mdata/fwu-mdata-uclass.c | 469 ++ drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410 +++ include/configs/stm32mp15_common.h| 4 + include/dm/uclass-id.h| 1 + include/fwu.h
Re: [PATCH v6 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
hi Patrick, On Wed, 13 Jul 2022 at 18:42, Patrick DELAUNAY wrote: > > Hi, > > On 7/4/22 07:16, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > > updatable images is stored as part of the metadata, which is stored on > > a dedicated partition. Add the metadata structure, and a driver model > > uclass which provides functions to access the metadata. These are > > generic API's, and implementations can be added based on parameters > > like how the metadata partition is accessed and what type of storage > > device houses the metadata. > > > > Signed-off-by: Sughosh Ganu > > --- > > Changes since V5: > > * Change the parameter to the function fwu_plat_get_alt_num to pass > >the FWU udevice pointer instead of passing the metadata device > >directly. > > > > drivers/Kconfig | 2 + > > drivers/Makefile | 1 + > > drivers/fwu-mdata/Kconfig| 7 + > > drivers/fwu-mdata/Makefile | 6 + > > drivers/fwu-mdata/fwu-mdata-uclass.c | 458 +++ > > include/dm/uclass-id.h | 1 + > > include/fwu.h| 49 +++ > > include/fwu_mdata.h | 67 > > 8 files changed, 591 insertions(+) > > create mode 100644 drivers/fwu-mdata/Kconfig > > create mode 100644 drivers/fwu-mdata/Makefile > > create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c > > create mode 100644 include/fwu.h > > create mode 100644 include/fwu_mdata.h > > > > diff --git a/drivers/Kconfig b/drivers/Kconfig > > index b26ca8cf70..adc6079ecf 100644 > > --- a/drivers/Kconfig > > +++ b/drivers/Kconfig > > @@ -42,6 +42,8 @@ source "drivers/firmware/Kconfig" > > > > source "drivers/fpga/Kconfig" > > > > +source "drivers/fwu-mdata/Kconfig" > > + > > source "drivers/gpio/Kconfig" > > > > source "drivers/hwspinlock/Kconfig" > > diff --git a/drivers/Makefile b/drivers/Makefile > > index 67c8af7442..901150bb35 100644 > > --- a/drivers/Makefile > > +++ b/drivers/Makefile > > @@ -83,6 +83,7 @@ obj-y += cache/ > > obj-$(CONFIG_CPU) += cpu/ > > obj-y += crypto/ > > obj-$(CONFIG_FASTBOOT) += fastboot/ > > +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/ > > obj-y += misc/ > > obj-$(CONFIG_MMC) += mmc/ > > obj-$(CONFIG_NVME) += nvme/ > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > > new file mode 100644 > > index 00..d6a21c8e19 > > --- /dev/null > > +++ b/drivers/fwu-mdata/Kconfig > > @@ -0,0 +1,7 @@ > > +config DM_FWU_MDATA > > + bool "Driver support for accessing FWU Metadata" > > + depends on DM > > + help > > + Enable support for accessing FWU Metadata partitions. The > > + FWU Metadata partitions reside on the same storage device > > + which contains the other FWU updatable firmware images. > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > > new file mode 100644 > > index 00..e53a8c9983 > > --- /dev/null > > +++ b/drivers/fwu-mdata/Makefile > > @@ -0,0 +1,6 @@ > > +# SPDX-License-Identifier: GPL-2.0-or-later > > +# > > +# Copyright (c) 2022, Linaro Limited > > +# > > + > > +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > > b/drivers/fwu-mdata/fwu-mdata-uclass.c > > new file mode 100644 > > index 00..2092fcfc23 > > --- /dev/null > > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > > @@ -0,0 +1,458 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > #define LOG_CATEGORY UCLASS_FWU_MDATA Will add. Thanks. -sughosh > > > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#define IMAGE_ACCEPT_SET BIT(0) > > +#define IMAGE_ACCEPT_CLEAR BIT(1) > > + > > +static int fwu_get_dev_ops(struct udevice **dev, > > +const struct fwu_mdata_ops **ops) > > +{ > > + int ret; > > + > > + ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev); > > + if (ret) { > > + log_debug("Cannot find fwu device\n"); > > + return ret; > > + } > > + > > + if ((*ops = device_get_ops(*dev)) == NULL) { > > + log_debug("Cannot get fwu device ops\n"); > > + return -ENOSYS; > > + } > > + > > + return 0; > > +} > > + > > (...) > > with this minor update > > Reviewed-by: Patrick Delaunay > > Thanks > Patrick >
Re: [PATCH v6 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
hi Patrick, On Wed, 13 Jul 2022 at 18:47, Patrick DELAUNAY wrote: > > Hi, > > On 7/4/22 07:16, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > > updatable images is stored as part of the metadata, on a separate > > partition. Add a driver for reading from and writing to the metadata > > when the updatable images and the metadata are stored on a block > > device which is formated with GPT based partition scheme. > > > > Signed-off-by: Sughosh Ganu > > --- > > Changes since V5: > > * Changed the logic to store the GPT partitioned block device through > >a priv structure as suggested by Patrick > > * Used dev_read_prop() to get the phandle_p instead of > >ofnode_get_property() used earlier as suggested by Patrick > > * Make relevant functions static as suggested by Etienne > > > > drivers/fwu-mdata/Kconfig | 9 + > > drivers/fwu-mdata/Makefile| 1 + > > drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 408 ++ > > include/fwu.h | 5 + > > 4 files changed, 423 insertions(+) > > create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > > index d6a21c8e19..d5edef19d6 100644 > > --- a/drivers/fwu-mdata/Kconfig > > +++ b/drivers/fwu-mdata/Kconfig > > @@ -5,3 +5,12 @@ config DM_FWU_MDATA > > Enable support for accessing FWU Metadata partitions. The > > FWU Metadata partitions reside on the same storage device > > which contains the other FWU updatable firmware images. > > + > > +config FWU_MDATA_GPT_BLK > > + bool "FWU Metadata access for GPT partitioned Block devices" > > + select PARTITION_TYPE_GUID > > + select PARTITION_UUIDS > > + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION > > + help > > + Enable support for accessing FWU Metadata on GPT partitioned > > + block devices. > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > > index e53a8c9983..313049f67a 100644 > > --- a/drivers/fwu-mdata/Makefile > > +++ b/drivers/fwu-mdata/Makefile > > @@ -4,3 +4,4 @@ > > # > > > > obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o > > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o > > diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > new file mode 100644 > > index 00..d904c9492d > > --- /dev/null > > +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > @@ -0,0 +1,408 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > #define LOG_CATEGORY UCLASS_FWU_MDATA I think you had mentioned this in your earlier review as well. Sorry, I missed out on this. Will add in the next version. > > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#define PRIMARY_PART BIT(0) > > +#define SECONDARY_PART BIT(1) > > +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) > > + > > +#define MDATA_READ BIT(0) > > +#define MDATA_WRITE BIT(1) > > + > > (...) > > > > + > > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = { > > + .mdata_check = fwu_gpt_mdata_check, > > + .get_mdata = fwu_gpt_get_mdata, > > + .update_mdata = fwu_gpt_update_mdata, > > +};UCLASS_FWU_MDATA > > > > + > > +static const struct udevice_id fwu_mdata_ids[] = { > > + { .compatible = "u-boot,fwu-mdata-gpt" }, > > + { } > > +}; > > + > > +U_BOOT_DRIVER(fwu_mdata_gpt_blk) = { > > + .name = "fwu-mdata-gpt-blk", > > + .id = UCLASS_FWU_MDATA, > > + .of_match = fwu_mdata_ids, > > + .ops= _gpt_blk_ops, > > + .probe = fwu_mdata_gpt_blk_probe, > > + .priv_auto = sizeof(struct fwu_mdata_gpt_blk_priv), > > +}; > > diff --git a/include/fwu.h b/include/fwu.h > > index e03cfff800..8259c75d12 100644 > > --- a/include/fwu.h > > +++ b/include/fwu.h > > @@ -14,6 +14,10 @@ > > struct fwu_mdata; > > struct udevice; > > &
Re: [PATCH v6 2/7] tpm: rng: Add driver model interface for TPM RNG device
hi Simon, On Tue, 5 Jul 2022 at 15:17, Simon Glass wrote: > > Hi Sughosh, > > On Mon, 4 Jul 2022 at 07:35, Sughosh Ganu wrote: > > > > The TPM device has a builtin random number generator(RNG) > > functionality. Expose the RNG functions of the TPM device to the > > driver model so that they can be used by the EFI_RNG_PROTOCOL if the > > protocol is installed. > > > > Also change the function arguments and return type of the random > > number functions to comply with the driver model api. > > > > Signed-off-by: Sughosh Ganu > > --- > > Changes since V5: > > * Use the dev_get_parent() interface for getting the TPM device when > > calling the tpm_get_random() function > > > > drivers/rng/Kconfig | 11 +++ > > drivers/rng/Makefile | 1 + > > drivers/rng/tpm_rng.c | 23 +++ > > lib/Kconfig | 1 + > > lib/tpm-v1.c | 13 +++-- > > lib/tpm-v2.c | 6 +++--- > > lib/tpm_api.c | 6 +++--- > > 7 files changed, 49 insertions(+), 12 deletions(-) > > create mode 100644 drivers/rng/tpm_rng.c > > The API change should not be needed. The code that calls the TPM > routines should adapt for that. Are you referring to the changes made in tpm[1,2]_get_random functions? If so, those changes in the return values have been made based on review comments from Heinrich[1]. If you are referring to some other changes, please let me know. Thanks. -sughosh [1] - https://lists.denx.de/pipermail/u-boot/2022-February/476085.html > > Regards, > Simon
[PATCH v6 7/7] test: rng: Add a UT testcase for the rng command
The 'rng' command dumps a number of random bytes on the console. Add a set of tests for the 'rng' command. The test function performs basic sanity testing of the command. Since a unit test is being added for the command, enable it by default in the sandbox platforms. Reviewed-by: Simon Glass Signed-off-by: Sughosh Ganu --- cmd/Kconfig | 1 + test/dm/rng.c | 29 + 2 files changed, 30 insertions(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index 09193b61b9..eee5d44348 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1916,6 +1916,7 @@ config CMD_GETTIME config CMD_RNG bool "rng command" depends on DM_RNG + default y if SANDBOX select HEXDUMP help Print bytes from the hardware random number generator. diff --git a/test/dm/rng.c b/test/dm/rng.c index 5b34c93ed6..6d1f68848d 100644 --- a/test/dm/rng.c +++ b/test/dm/rng.c @@ -25,3 +25,32 @@ static int dm_test_rng_read(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_rng_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test the rng command */ +static int dm_test_rng_cmd(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_RNG, 0, )); + ut_assertnonnull(dev); + + ut_assertok(console_record_reset_enable()); + + run_command("rng", 0); + ut_assert_nextlinen(":"); + ut_assert_nextlinen("0010:"); + ut_assert_nextlinen("0020:"); + ut_assert_nextlinen("0030:"); + ut_assert_console_end(); + + run_command("rng 0 10", 0); + ut_assert_nextlinen(":"); + ut_assert_console_end(); + + run_command("rng 20", 0); + ut_assert_nextlinen("No RNG device"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_rng_cmd, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); -- 2.25.1
[PATCH v6 6/7] doc: rng: Add documentation for the rng command
Add a usage document for the 'rng' u-boot command. Reviewed-by: Ilias Apalodimas Reviewed-by: Simon Glass Signed-off-by: Sughosh Ganu --- Changes since V5: None doc/usage/cmd/rng.rst | 26 ++ doc/usage/index.rst | 1 + 2 files changed, 27 insertions(+) create mode 100644 doc/usage/cmd/rng.rst diff --git a/doc/usage/cmd/rng.rst b/doc/usage/cmd/rng.rst new file mode 100644 index 00..1a352da41a --- /dev/null +++ b/doc/usage/cmd/rng.rst @@ -0,0 +1,26 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +rng command +=== + +Synopsis + + +:: + +rng [devnum [n]] + +Description +--- + +The *rng* command reads the random number generator(RNG) device and +prints the random bytes read on the console. A maximum of 64 bytes can +be read in one invocation of the command. + +devnum +The RNG device from which the random bytes are to be +read. Defaults to 0. + +n +Number of random bytes to be read and displayed on the +console. Default value is 0x40. Max value is 0x40. diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 770418434a..ed3a78aa14 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -53,6 +53,7 @@ Shell commands cmd/pstore cmd/qfw cmd/reset + cmd/rng cmd/sbi cmd/sf cmd/scp03 -- 2.25.1
[PATCH v6 5/7] cmd: rng: Use a statically allocated array for random bytes
Use a statically allocated buffer on stack instead of using malloc for reading the random bytes. Using a local array is faster than allocating heap memory on every initiation of the command. Signed-off-by: Sughosh Ganu --- Changes since V5: None cmd/rng.c | 17 +++-- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/cmd/rng.c b/cmd/rng.c index 2ddf27545f..81a23964b8 100644 --- a/cmd/rng.c +++ b/cmd/rng.c @@ -14,9 +14,9 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { size_t n; - struct udevice *dev; - void *buf; + u8 buf[64]; int devnum; + struct udevice *dev; int ret = CMD_RET_SUCCESS; switch (argc) { @@ -41,11 +41,10 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_FAILURE; } - buf = malloc(n); - if (!buf) { - printf("Out of memory\n"); - return CMD_RET_FAILURE; - } + if (!n) + return 0; + + n = min(n, sizeof(buf)); if (dm_rng_read(dev, buf, n)) { printf("Reading RNG failed\n"); @@ -54,15 +53,13 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n); } - free(buf); - return ret; } #ifdef CONFIG_SYS_LONGHELP static char rng_help_text[] = "[dev [n]]\n" - " - print n random bytes read from dev\n"; + " - print n random bytes(max 64) read from dev\n"; #endif U_BOOT_CMD( -- 2.25.1
[PATCH v6 4/7] cmd: rng: Add support for selecting RNG device
The 'rng' u-boot command is used for printing a select number of random bytes on the console. Currently, the RNG device from which the random bytes are read is fixed. However, a platform can have multiple RNG devices, one example being qemu, which has a virtio RNG device and the RNG pseudo device through the TPM chip. Extend the 'rng' command so that the user can provide the RNG device number from which the random bytes are to be read. This will be the device index under the RNG uclass. Tested-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas Signed-off-by: Sughosh Ganu --- Changes since V5: None cmd/rng.c | 31 +++ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cmd/rng.c b/cmd/rng.c index 1ad5a096c0..2ddf27545f 100644 --- a/cmd/rng.c +++ b/cmd/rng.c @@ -13,19 +13,34 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - size_t n = 0x40; + size_t n; struct udevice *dev; void *buf; + int devnum; int ret = CMD_RET_SUCCESS; - if (uclass_get_device(UCLASS_RNG, 0, ) || !dev) { + switch (argc) { + case 1: + devnum = 0; + n = 0x40; + break; + case 2: + devnum = hextoul(argv[1], NULL); + n = 0x40; + break; + case 3: + devnum = hextoul(argv[1], NULL); + n = hextoul(argv[2], NULL); + break; + default: + return CMD_RET_USAGE; + } + + if (uclass_get_device_by_seq(UCLASS_RNG, devnum, ) || !dev) { printf("No RNG device\n"); return CMD_RET_FAILURE; } - if (argc >= 2) - n = hextoul(argv[1], NULL); - buf = malloc(n); if (!buf) { printf("Out of memory\n"); @@ -46,12 +61,12 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_LONGHELP static char rng_help_text[] = - "[n]\n" - " - print n random bytes\n"; + "[dev [n]]\n" + " - print n random bytes read from dev\n"; #endif U_BOOT_CMD( - rng, 2, 0, do_rng, + rng, 3, 0, do_rng, "print bytes from the hardware random number generator", rng_help_text ); -- 2.25.1
[PATCH v6 3/7] tpm: Add the RNG child device
The TPM device comes with the random number generator(RNG) functionality which is built into the TPM device. Add logic to add the RNG child device in the TPM uclass post probe callback. The RNG device can then be used to pass a set of random bytes to the linux kernel, need for address space randomisation through the EFI_RNG_PROTOCOL interface. Signed-off-by: Sughosh Ganu --- Changes since V5: * Check if the TPM RNG device has already been added, through a call to device_find_first_child_by_uclass() drivers/tpm/tpm-uclass.c | 37 + 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c index f67fe1019b..e1f1ef01e1 100644 --- a/drivers/tpm/tpm-uclass.c +++ b/drivers/tpm/tpm-uclass.c @@ -11,10 +11,15 @@ #include #include #include +#include #include #include #include "tpm_internal.h" +#include + +#define TPM_RNG_DRV_NAME "tpm-rng" + int tpm_open(struct udevice *dev) { struct tpm_ops *ops = tpm_get_ops(dev); @@ -136,12 +141,36 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, return 0; } +static int tpm_uclass_post_probe(struct udevice *dev) +{ + int ret; + const char *drv = TPM_RNG_DRV_NAME; + struct udevice *child; + + if (CONFIG_IS_ENABLED(TPM_RNG)) { + ret = device_find_first_child_by_uclass(dev, UCLASS_RNG, + ); + + if (ret != -ENODEV) { + log_debug("RNG child already added to the TPM device\n"); + return ret; + } + + ret = device_bind_driver(dev, drv, "tpm-rng0", ); + if (ret) + return log_msg_ret("bind", ret); + } + + return 0; +} + UCLASS_DRIVER(tpm) = { - .id = UCLASS_TPM, - .name = "tpm", - .flags = DM_UC_FLAG_SEQ_ALIAS, + .id = UCLASS_TPM, + .name = "tpm", + .flags = DM_UC_FLAG_SEQ_ALIAS, #if CONFIG_IS_ENABLED(OF_REAL) - .post_bind = dm_scan_fdt_dev, + .post_bind = dm_scan_fdt_dev, #endif + .post_probe = tpm_uclass_post_probe, .per_device_auto= sizeof(struct tpm_chip_priv), }; -- 2.25.1
[PATCH v6 2/7] tpm: rng: Add driver model interface for TPM RNG device
The TPM device has a builtin random number generator(RNG) functionality. Expose the RNG functions of the TPM device to the driver model so that they can be used by the EFI_RNG_PROTOCOL if the protocol is installed. Also change the function arguments and return type of the random number functions to comply with the driver model api. Signed-off-by: Sughosh Ganu --- Changes since V5: * Use the dev_get_parent() interface for getting the TPM device when calling the tpm_get_random() function drivers/rng/Kconfig | 11 +++ drivers/rng/Makefile | 1 + drivers/rng/tpm_rng.c | 23 +++ lib/Kconfig | 1 + lib/tpm-v1.c | 13 +++-- lib/tpm-v2.c | 6 +++--- lib/tpm_api.c | 6 +++--- 7 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 drivers/rng/tpm_rng.c diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index c10f7d345b..67c65311c7 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -58,4 +58,15 @@ config RNG_IPROC200 depends on DM_RNG help Enable random number generator for RPI4. + +config TPM_RNG + bool "Enable random number generator on TPM device" + depends on TPM + default y + help + The TPM device has an inbuilt random number generator + functionality. Enable random number generator on TPM + devices. + + endif diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 435b3b965a..e4ca9c4149 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_RNG_OPTEE) += optee_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o +obj-$(CONFIG_TPM_RNG) += tpm_rng.o diff --git a/drivers/rng/tpm_rng.c b/drivers/rng/tpm_rng.c new file mode 100644 index 00..1a5e9e2e4b --- /dev/null +++ b/drivers/rng/tpm_rng.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include + +static int rng_tpm_random_read(struct udevice *dev, void *data, size_t count) +{ + return tpm_get_random(dev_get_parent(dev), data, count); +} + +static const struct dm_rng_ops tpm_rng_ops = { + .read = rng_tpm_random_read, +}; + +U_BOOT_DRIVER(tpm_rng) = { + .name = "tpm-rng", + .id = UCLASS_RNG, + .ops= _rng_ops, +}; diff --git a/lib/Kconfig b/lib/Kconfig index acc0ac081a..17efaa4c80 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -358,6 +358,7 @@ source lib/crypt/Kconfig config TPM bool "Trusted Platform Module (TPM) Support" depends on DM + imply DM_RNG help This enables support for TPMs which can be used to provide security features for your board. The TPM can be connected via LPC or I2C diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c index 22a769c587..f7091e5bc7 100644 --- a/lib/tpm-v1.c +++ b/lib/tpm-v1.c @@ -9,12 +9,13 @@ #include #include #include -#include -#include #include #include #include "tpm-utils.h" +#include +#include + #ifdef CONFIG_TPM_AUTH_SESSIONS #ifndef CONFIG_SHA1 @@ -892,19 +893,19 @@ u32 tpm1_get_random(struct udevice *dev, void *data, u32 count) if (pack_byte_string(buf, sizeof(buf), "sd", 0, command, sizeof(command), length_offset, this_bytes)) - return TPM_LIB_ERROR; + return -EIO; err = tpm_sendrecv_command(dev, buf, response, _length); if (err) return err; if (unpack_byte_string(response, response_length, "d", data_size_offset, _size)) - return TPM_LIB_ERROR; + return -EIO; if (data_size > count) - return TPM_LIB_ERROR; + return -EIO; if (unpack_byte_string(response, response_length, "s", data_offset, out, data_size)) - return TPM_LIB_ERROR; + return -EIO; count -= data_size; out += data_size; diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 1bf627853a..abca9a14b0 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -585,19 +585,19 @@ u32 tpm2_get_random(struct udevice *dev, void *data, u32 count) if (pack_byte_string(buf, sizeof(buf), "sw", 0, command_v2, sizeof(command_v2), sizeof(command_v2), this_bytes)) - return TPM_LIB_ERROR; + return -EIO; err = tpm_send
[PATCH v6 0/7] tpm: rng: Move TPM RNG functionality to driver model
The TPM device provides the random number generator(RNG) functionality, whereby sending a command to the TPM device results in the TPM device responding with random bytes. There was a discussion on the mailing list earlier[1], where it was explained that platforms with a TPM device can install the EFI_RNG_PROTOCOL for getting the random bytes instead of populating the dtb with the kaslr-seed property. That would make it possible to measure the dtb. The TPM uclass driver adds the RNG child device as part of it's post_probe function. Some additional changes have also been made to facilitate the use of the RNG devices, including extending the 'rng' command to take the RNG device as one of the command-line parameters. This series depends on a patch[2] from Simon Glass for moving the TPM device version detection functions to the tpm_api.h header as static inline functions. These patches were under discussion earlier, specifically the patch to add the RNG functionality under the TPM device as a child, either through manual binding or through the device tree. Ilias had commented on the discussion last[3]. The discussion can be resumed through this version. I have dropped certain patches which were changing some of the TPM API functions to return an int instead of the current u32. These patches have been dropped due to review comments from Simon[4]. This work can be taken up separately, if desired. [1] - https://lore.kernel.org/u-boot/20220103120738.47835-1-ilias.apalodi...@linaro.org/ [2] - https://lore.kernel.org/u-boot/20220301001125.1554442-2-...@chromium.org/T/#u [3] - https://lists.denx.de/pipermail/u-boot/2022-April/481708.html [4] - https://lists.denx.de/pipermail/u-boot/2022-March/477883.html Simon Glass (1): tpm: Export the TPM-version functions Sughosh Ganu (6): tpm: rng: Add driver model interface for TPM RNG device tpm: Add the RNG child device cmd: rng: Add support for selecting RNG device cmd: rng: Use a statically allocated array for random bytes doc: rng: Add documentation for the rng command test: rng: Add a UT testcase for the rng command cmd/Kconfig | 1 + cmd/rng.c| 42 +++-- doc/usage/cmd/rng.rst| 26 +++ doc/usage/index.rst | 1 + drivers/rng/Kconfig | 11 + drivers/rng/Makefile | 1 + drivers/rng/tpm_rng.c| 23 ++ drivers/tpm/tpm-uclass.c | 37 +-- include/tpm_api.h| 10 lib/Kconfig | 1 + lib/tpm-v1.c | 13 +++--- lib/tpm-v2.c | 6 +-- lib/tpm_api.c| 98 ++-- test/dm/rng.c| 29 14 files changed, 217 insertions(+), 82 deletions(-) create mode 100644 doc/usage/cmd/rng.rst create mode 100644 drivers/rng/tpm_rng.c -- 2.25.1
[PATCH v6 1/7] tpm: Export the TPM-version functions
From: Simon Glass These functions should really be available outside the TPM code, so that other callers can find out which version the TPM is. Rename them to have a tpm_ prefix() and add them to the header file. Signed-off-by: Simon Glass --- Changes since V5: None include/tpm_api.h | 10 ++ lib/tpm_api.c | 92 +-- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/include/tpm_api.h b/include/tpm_api.h index ef45b43a8f..11aa14eb79 100644 --- a/include/tpm_api.h +++ b/include/tpm_api.h @@ -319,4 +319,14 @@ u32 tpm_write_lock(struct udevice *dev, u32 index); */ u32 tpm_resume(struct udevice *dev); +static inline bool tpm_is_v1(struct udevice *dev) +{ + return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1; +} + +static inline bool tpm_is_v2(struct udevice *dev) +{ + return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2; +} + #endif /* __TPM_API_H */ diff --git a/lib/tpm_api.c b/lib/tpm_api.c index 4c662640a9..4ac4612c81 100644 --- a/lib/tpm_api.c +++ b/lib/tpm_api.c @@ -11,21 +11,11 @@ #include #include -static bool is_tpm1(struct udevice *dev) -{ - return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1; -} - -static bool is_tpm2(struct udevice *dev) -{ - return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2; -} - u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) { - if (is_tpm1(dev)) { + if (tpm_is_v1(dev)) { return tpm1_startup(dev, mode); - } else if (is_tpm2(dev)) { + } else if (tpm_is_v2(dev)) { enum tpm2_startup_types type; switch (mode) { @@ -47,9 +37,9 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) u32 tpm_resume(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_startup(dev, TPM_ST_STATE); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_startup(dev, TPM2_SU_STATE); else return -ENOSYS; @@ -57,9 +47,9 @@ u32 tpm_resume(struct udevice *dev) u32 tpm_self_test_full(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_self_test_full(dev); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_self_test(dev, TPMI_YES); else return -ENOSYS; @@ -67,9 +57,9 @@ u32 tpm_self_test_full(struct udevice *dev) u32 tpm_continue_self_test(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_continue_self_test(dev); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_self_test(dev, TPMI_NO); else return -ENOSYS; @@ -86,7 +76,7 @@ u32 tpm_clear_and_reenable(struct udevice *dev) return ret; } - if (is_tpm1(dev)) { + if (tpm_is_v1(dev)) { ret = tpm1_physical_enable(dev); if (ret != TPM_SUCCESS) { log_err("TPM: Can't set enabled state\n"); @@ -105,9 +95,9 @@ u32 tpm_clear_and_reenable(struct udevice *dev) u32 tpm_nv_enable_locking(struct udevice *dev) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return -ENOSYS; else return -ENOSYS; @@ -115,9 +105,9 @@ u32 tpm_nv_enable_locking(struct udevice *dev) u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_nv_read_value(dev, index, data, count); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_nv_read_value(dev, index, data, count); else return -ENOSYS; @@ -126,9 +116,9 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, u32 count) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return tpm1_nv_write_value(dev, index, data, count); - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_nv_write_value(dev, index, data, count); else return -ENOSYS; @@ -141,9 +131,9 @@ u32 tpm_set_global_lock(struct udevice *dev) u32 tpm_write_lock(struct udevice *dev, u32 index) { - if (is_tpm1(dev)) + if (tpm_is_v1(dev)) return -ENOSYS; - else if (is_tpm2(dev)) + else if (tpm_is_v2(dev)) return tpm2_write_lock(dev, index); else return -ENOSYS; @@ -152,9 +142,9 @@ u32 tpm_write_lock(struct udevice *dev, u32 index) u32
[PATCH v6 13/13] FWU: doc: Add documentation for the FWU feature
Add documentattion for the FWU Multi Bank Update feature. The document describes the steps needed for setting up the platform for the feature, as well as steps for enabling the feature on the platform. Signed-off-by: Sughosh Ganu --- Changes since V5: * Add some description about the reasoning for accept capsule needing image GUID as suggested by Takahiro doc/develop/uefi/fwu_updates.rst | 156 +++ doc/develop/uefi/index.rst | 1 + doc/develop/uefi/uefi.rst| 2 + 3 files changed, 159 insertions(+) create mode 100644 doc/develop/uefi/fwu_updates.rst diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst new file mode 100644 index 00..57d1b5b703 --- /dev/null +++ b/doc/develop/uefi/fwu_updates.rst @@ -0,0 +1,156 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (c) 2022 Linaro Limited + +FWU Multi Bank Updates in U-Boot + + +The FWU Multi Bank Update feature implements the firmware update +mechanism described in the PSA Firmware Update for A-profile Arm +Architecture specification[1]. Certain aspects of the Dependable +Boot specification[2] are also implemented. The feature provides a +mechanism to have multiple banks of updatable firmware images and for +updating the firmware images on the non-booted bank. On a successful +update, the platform boots from the updated bank on subsequent +boot. The UEFI capsule-on-disk update feature is used for performing +the actual updates of the updatable firmware images. + +The bookkeeping of the updatable images is done through a structure +called metadata. Currently, the FWU metadata supports identification +of images based on image GUIDs stored on a GPT partitioned storage +media. There are plans to extend the metadata structure for non GPT +partitioned devices as well. + +Accessing the FWU metadata is done through generic API's which are +defined in a driver which complies with the u-boot's driver model. A +new uclass UCLASS_FWU_MDATA has been added for accessing the FWU +metadata. Individual drivers can be added based on the type of storage +media, and it's partitioning method. Details of the storage device +containing the FWU metadata partitions are specified through a U-Boot +specific device tree property `fwu-mdata-store`. Please refer to +U-Boot `doc `__ for +the device tree bindings. + +Enabling the FWU Multi Bank Update feature +-- + +The feature can be enabled by specifying the following configs:: + +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y +CONFIG_EFI_CAPSULE_FIRMWARE=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y + +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_CMD_FWU_METADATA=y +CONFIG_DM_FWU_MDATA=y +CONFIG_FWU_MDATA_GPT_BLK=y +CONFIG_FWU_NUM_BANKS= +CONFIG_FWU_NUM_IMAGES_PER_BANK= + +in the .config file + +The first group of configs enable the UEFI capsule-on-disk update +functionality. The second group of configs 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. + +Setting up the device for GPT partitioned storage +- + +Before enabling the functionality in U-Boot, certain changes are +required to be done on the storage device. Assuming a GPT partitioned +storage device, the storage media needs to be partitioned with the +correct number of partitions, given the number of banks and number of +images per bank that the platform is going to support. Each updatable +firmware image will be stored on an separate partition. In addition, +the two copies of the FWU metadata will be stored on two separate +partitions. + +As an example, a platform supporting two banks with each bank +containing three images would need to have 2 * 3 = 6 parititions plus +the two metadata partitions, or 8 partitions. In addition the storage +media can have additional partitions of non-updatable images, like the +EFI System Partition(ESP), a partition for the root file system etc. + +When generating the partitions, a few aspects need to be taken care +of. Each GPT partition entry in the GPT header has two GUIDs:: + +*PartitionTypeGUID* +*UniquePartitionGUID* + +The PartitionTypeGUID value should correspond to the *image_type_uuid* +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* +field in the FWU metadata. This GUID is used to identify images of a +given image type in different banks. + +Similarly, the FWU specifications defines the GUID value to be used +for the metadata partitions. This would be the PartitionTypeGUID for +the metadata partitions. + +When
[PATCH v6 12/13] mkeficapsule: Add support for setting OEM flags in capsule header
Add support for setting OEM flags in the capsule header. As per the UEFI specification, bits 0-15 of the flags member of the capsule header can be defined per capsule GUID. The oemflags will be used for the FWU Multi Bank update feature, as specified by the Dependable Boot specification[1]. Bit 15 of the flags member will be used to determine if the acceptance/rejection of the updated images is to be done by the firmware or an external component like the OS. [1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Signed-off-by: Sughosh Ganu --- Changes since V5: None doc/mkeficapsule.1 | 4 tools/mkeficapsule.c | 17 ++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 77ca061efd..6fb2dd0810 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule .BI "-R\fR,\fB --fw-revert " Generate a firmware revert empty capsule +.TP +.BI "-o\fR,\fB --capoemflag " +Capsule OEM flag, value between 0x to 0x + .TP .BR -h ", " --help Print a help message diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 244c80e1f7..237c1218fd 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; -static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; +static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR"; enum { CAPSULE_NORMAL_BLOB = 0, @@ -47,6 +47,7 @@ static struct option options[] = { {"dump-sig", no_argument, NULL, 'd'}, {"fw-accept", no_argument, NULL, 'A'}, {"fw-revert", no_argument, NULL, 'R'}, + {"capoemflag", required_argument, NULL, 'o'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -65,6 +66,7 @@ static void print_usage(void) "\t-d, --dump_sig dump signature (*.p7)\n" "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n" "\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n" + "\t-o, --capoemflag Capsule OEM Flag, an integer between 0x and 0x\n" "\t-h, --help print a help message\n", tool_name); } @@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx) * @mcount:Monotonic count in authentication information * @private_file: Path to a private key file * @cert_file: Path to a certificate file + * @oemflags: Capsule OEM Flags, bits 0-15 * * This function actually does the job of creating an uefi capsule file. * All the arguments must be supplied. @@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx) */ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, unsigned long index, unsigned long instance, - uint64_t mcount, char *privkey_file, char *cert_file) + uint64_t mcount, char *privkey_file, char *cert_file, + uint16_t oemflags) { struct efi_capsule_header header; struct efi_firmware_management_capsule_header capsule; @@ -464,6 +468,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, header.header_size = sizeof(header); /* TODO: The current implementation ignores flags */ header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + if (oemflags) + header.flags |= oemflags; header.capsule_image_size = sizeof(header) + sizeof(capsule) + sizeof(uint64_t) + sizeof(image) @@ -635,6 +641,7 @@ int main(int argc, char **argv) unsigned char uuid_buf[16]; unsigned long index, instance; uint64_t mcount; + uint16_t oemflags; char *privkey_file, *cert_file; int c, idx; @@ -646,6 +653,7 @@ int main(int argc, char **argv) cert_file = NULL; dump_sig = 0; capsule_type = CAPSULE_NORMAL_BLOB; + oemflags = 0; for (;;) { c = getopt_long(argc, argv, opts_short, options, ); if (c == -1) @@ -699,6 +707,9 @@ int main(int argc, char **argv) case 'R': capsule_type |= CAPSULE_REVERT; break; + case 'o': + oemflags = strtoul(optarg, NULL, 0); + break; default: print_usage();
[PATCH v6 11/13] mkeficapsule: Add support for generating empty capsules
The Dependable Boot specification[1] describes the structure of the firmware accept and revert capsules. These are empty capsules which are used for signalling the acceptance or rejection of the updated firmware by the OS. Add support for generating these empty capsules. [1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Signed-off-by: Sughosh Ganu --- Changes since V5: * Use capsule_type instead of capsule variable that was created earlier to check for the type of capsule * Remove use of payload variable in create_empty_capsule() as suggested by Etienne * Initialise the struct efi_capsule_header as suggested by Etienne doc/mkeficapsule.1 | 29 ++ tools/eficapsule.h | 8 tools/mkeficapsule.c | 92 3 files changed, 115 insertions(+), 14 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 09bdc24295..77ca061efd 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot .SH SYNOPSIS .B mkeficapsule -.RI [ options "] " image-blob " " capsule-file +.RI [ options ] " " [ image-blob ] " " capsule-file .SH "DESCRIPTION" .B mkeficapsule @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given private key. In this case, the update will be authenticated by verifying the signature before applying. +Additionally, an empty capsule file can be generated for acceptance or +rejection of firmware images by a governing component like an Operating +System. The empty capsules do not require an image-blob input file. + + .B mkeficapsule -takes any type of image files, including: +takes any type of image files when generating non empty capsules, including: .TP .I raw image format is a single binary blob of any type of firmware. @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file. This type of image file can be generated by .BR mkimage . -.PP -If you want to use other types than above two, you should explicitly -specify a guid for the FMP driver. - .SH "OPTIONS" + .TP .BI "-g\fR,\fB --guid " guid-string Specify guid for image blob type. The format is: ---- The first three elements are in little endian, while the rest -is in big endian. +is in big endian. The option must be specified for all non empty and +image acceptance capsules .TP .BI "-i\fR,\fB --index " index @@ -57,6 +60,18 @@ Specify an image index .BI "-I\fR,\fB --instance " instance Specify a hardware instance +.PP +For generation of firmware accept empty capsule +.BR --guid +is mandatory +.TP +.BI "-A\fR,\fB --fw-accept " +Generate a firmware acceptance empty capsule + +.TP +.BI "-R\fR,\fB --fw-revert " +Generate a firmware revert empty capsule + .TP .BR -h ", " --help Print a help message diff --git a/tools/eficapsule.h b/tools/eficapsule.h index d63b831443..072a4b5598 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -41,6 +41,14 @@ typedef struct { EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \ 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) +#define FW_ACCEPT_OS_GUID \ + EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) + +#define FW_REVERT_OS_GUID \ + EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \ +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0) + /* flags */ #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x0001 diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 5f74d23b9e..244c80e1f7 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,13 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; -static const char *opts_short = "g:i:I:v:p:c:m:dh"; +static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; + +enum { + CAPSULE_NORMAL_BLOB = 0, + CAPSULE_ACCEPT, + CAPSULE_REVERT, +} capsule_type; static struct option options[] = { {"guid", required_argument, NULL, 'g'}, @@ -39,6 +45,8 @@ static struct option options[] = { {"certificate", required_argument, NULL, 'c'}, {"monotonic-count", required_argument, NULL, 'm'}, {"dump-sig", no_argument, NULL, 'd'}, + {"fw-accept", no_argument, NULL, 'A'}, + {"fw-revert", no_argument, NULL, 'R'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -55,6 +63,8 @@ static void print_usage(void) "\t-c, --certificate signer's certificate file\n" "\t-m, --monotonic-count m
[PATCH v6 10/13] FWU: cmd: Add a command to read FWU metadata
Add a command to read the metadata as specified in the FWU specification and print the fields of the metadata. Signed-off-by: Sughosh Ganu --- Changes since V5: * Do a metadata validity check by calling fwu_mdata_check() before printing the FWU metadata as suggested by Michal * Use ret and res variables in do_fwu_mdata_read() as suggested by Patrick * Change 'default y if FWU_MULTI_BANK_UPDATE' to default y as suggested by Patrick cmd/Kconfig | 7 + cmd/Makefile| 1 + cmd/fwu_mdata.c | 80 + 3 files changed, 88 insertions(+) create mode 100644 cmd/fwu_mdata.c diff --git a/cmd/Kconfig b/cmd/Kconfig index 09193b61b9..1a287d528f 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -144,6 +144,13 @@ config CMD_CPU internal name) and clock frequency. Other information may be available depending on the CPU driver. +config CMD_FWU_METADATA + bool "fwu metadata read" + depends on FWU_MULTI_BANK_UPDATE + default y + help + Command to read the metadata and dump it's contents + config CMD_LICENSE bool "license" select BUILD_BIN2C diff --git a/cmd/Makefile b/cmd/Makefile index 5e43a1e022..259a93bc65 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_FPGA) += fpga.o obj-$(CONFIG_CMD_FPGAD) += fpgad.o obj-$(CONFIG_CMD_FS_GENERIC) += fs.o obj-$(CONFIG_CMD_FUSE) += fuse.o +obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o obj-$(CONFIG_CMD_GETTIME) += gettime.o obj-$(CONFIG_CMD_GPIO) += gpio.o obj-$(CONFIG_CMD_HVC) += smccc.o diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c new file mode 100644 index 00..ee9d035374 --- /dev/null +++ b/cmd/fwu_mdata.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static void print_mdata(struct fwu_mdata *mdata) +{ + 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("\tImage Info\n"); + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { + img_entry = >img_entry[i]; + printf("\nImage Type Guid: %pUL\n", + _entry->image_type_uuid); + printf("Location Guid: %pUL\n", _entry->location_uuid); + for (j = 0; j < CONFIG_FWU_NUM_BANKS; j++) { + img_info = _entry->img_bank_info[j]; + printf("Image Guid: %pUL\n", _info->image_uuid); + printf("Image Acceptance: %s\n", + img_info->accepted == 0x1 ? "yes" : "no"); + } + } +} + +int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, +int argc, char * const argv[]) +{ + struct udevice *dev; + int ret = CMD_RET_SUCCESS, res; + struct fwu_mdata *mdata = NULL; + + if (uclass_get_device(UCLASS_FWU_MDATA, 0, ) || !dev) { + log_err("Unable to get FWU metadata device\n"); + return CMD_RET_FAILURE; + } + + res = fwu_mdata_check(); + if (res < 0) { + log_err("FWU Metadata check failed\n"); + ret = CMD_RET_FAILURE; + goto out; + } + + res = fwu_get_mdata(); + if (res < 0) { + log_err("Unable to get valid FWU metadata\n"); + ret = CMD_RET_FAILURE; + goto out; + } + + print_mdata(mdata); + +out: + free(mdata); + return ret; +} + +U_BOOT_CMD( + fwu_mdata_read, 1, 1, do_fwu_mdata_read, + "Read and print FWU metadata", + "" +); -- 2.25.1
[PATCH v6 09/13] FWU: Add support for the FWU Multi Bank Update feature
The FWU Multi Bank Update feature supports updation of firmware images to one of multiple sets(also called banks) of images. The firmware images are clubbed together in banks, with the system booting images from the active bank. Information on the images such as which bank they belong to is stored as part of the metadata structure, which is stored on the same storage media as the firmware images on a dedicated partition. At the time of update, the metadata is read to identify the bank to which the images need to be flashed(update bank). On a successful update, the metadata is modified to set the updated bank as active bank to subsequently boot from. Signed-off-by: Sughosh Ganu --- Changes since V5: * Use u"TrialStateCtr" as suggested by Patrick include/fwu.h| 10 ++ lib/Kconfig | 6 + lib/Makefile | 1 + lib/efi_loader/efi_capsule.c | 231 ++- lib/efi_loader/efi_setup.c | 3 +- lib/fwu_updates/Kconfig | 31 + lib/fwu_updates/Makefile | 3 +- lib/fwu_updates/fwu.c| 26 8 files changed, 304 insertions(+), 7 deletions(-) create mode 100644 lib/fwu_updates/Kconfig diff --git a/include/fwu.h b/include/fwu.h index b374fd1179..7ff1cd75d3 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -32,13 +32,23 @@ struct fwu_mdata_ops { }; #define FWU_MDATA_VERSION 0x1 +#define FWU_IMAGE_ACCEPTED 0x1 #define FWU_MDATA_GUID \ EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) +#define FWU_OS_REQUEST_FW_REVERT_GUID \ + EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \ +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0) + +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \ + EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) + u8 fwu_update_checks_pass(void); int fwu_boottime_checks(void); +int fwu_trial_state_ctr_start(void); int fwu_get_mdata(struct fwu_mdata **mdata); int fwu_update_mdata(struct fwu_mdata *mdata); diff --git a/lib/Kconfig b/lib/Kconfig index acc0ac081a..4ca6ea226b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -966,3 +966,9 @@ config PHANDLE_CHECK_SEQ phandles in fdtdec_get_alias_seq() function. endmenu + +menu "FWU Multi Bank Updates" + +source lib/fwu_updates/Kconfig + +endmenu diff --git a/lib/Makefile b/lib/Makefile index d9b1811f75..0cf8527c2d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_EFI_LOADER) += efi_driver/ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/ obj-$(CONFIG_LZMA) += lzma/ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_TIZEN) += tizen/ diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index a6b98f066a..18a356ba08 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,17 @@ static const efi_guid_t efi_guid_firmware_management_capsule_id = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; const efi_guid_t efi_guid_firmware_management_protocol = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; +const efi_guid_t fwu_guid_os_request_fw_revert = + FWU_OS_REQUEST_FW_REVERT_GUID; +const efi_guid_t fwu_guid_os_request_fw_accept = + FWU_OS_REQUEST_FW_ACCEPT_GUID; + +#define FW_ACCEPT_OS (u32)0x8000 + +__maybe_unused static u32 update_index; +__maybe_unused static bool capsule_update; +__maybe_unused static bool fw_accept_os; +static bool image_index_check = true; #ifdef CONFIG_EFI_CAPSULE_ON_DISK /* for file system access */ @@ -205,7 +217,8 @@ efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance, log_debug("+++ desc[%d] index: %d, name: %ls\n", j, desc->image_index, desc->image_id_name); if (!guidcmp(>image_type_id, image_type) && - (desc->image_index == image_index) && + (!image_index_check || +desc->image_index == image_index) && (!instance || !desc->hardware_instance || desc->hardware_instance == instance)) @@ -388,6 +401,87 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s } #endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */ +static bool fwu_empty_capsule(struct efi_capsule_header *capsule) +{ + return !guidcmp(>capsule_guid, + _guid_os_request_fw_revert) || + !guidcmp(>capsule_guid, +_guid_os_request_fw_accept); +} + +static e
[PATCH v6 08/13] FWU: Add boot time checks as highlighted by the FWU specification
The FWU Multi Bank Update specification requires the Update Agent to carry out certain checks at the time of platform boot. The Update Agent is the component which is responsible for updating the firmware components and maintaining and keeping the metadata in sync. The spec requires that the Update Agent perform the following checks at the time of boot * Sanity check of both the metadata copies maintained by the platform. * Get the boot index passed to U-Boot by the prior stage bootloader and use this value for metadata bookkeeping. * Check if the system is booting in Trial State. If the system boots in the Trial State for more than a specified number of boot counts, change the Active Bank to be booting the platform from. Add these checks in the board initialisation sequence, invoked after relocation. Signed-off-by: Sughosh Ganu --- Changes since V5: * Use u"TrialStateCtr" for the EFI variable name as suggested by Patrick * Dropped the call to uclass_get_device() in fwu_boottime_checks() as suggested by Patrick * Pass NULL instead of a pointer to trial_state_ctr variable when deleting the variable as suggested by Etienne common/board_r.c | 5 ++ include/fwu.h | 3 + lib/fwu_updates/fwu.c | 165 ++ 3 files changed, 173 insertions(+) create mode 100644 lib/fwu_updates/fwu.c diff --git a/common/board_r.c b/common/board_r.c index 6f4aca2077..33a600715d 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -797,6 +798,10 @@ static init_fnc_t init_sequence_r[] = { #if defined(CONFIG_PRAM) initr_mem, #endif + +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE + fwu_boottime_checks, +#endif run_main_loop, }; diff --git a/include/fwu.h b/include/fwu.h index edb28c9659..b374fd1179 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -37,6 +37,9 @@ struct fwu_mdata_ops { EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) +u8 fwu_update_checks_pass(void); +int fwu_boottime_checks(void); + int fwu_get_mdata(struct fwu_mdata **mdata); int fwu_update_mdata(struct fwu_mdata *mdata); int fwu_get_active_index(u32 *active_idx); diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c new file mode 100644 index 00..10a0522333 --- /dev/null +++ b/lib/fwu_updates/fwu.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static u8 trial_state; +static u8 boottime_check; + +static int fwu_trial_state_check(void) +{ + int ret, i; + efi_status_t status; + efi_uintn_t var_size; + u16 trial_state_ctr; + u32 nimages, active_bank, var_attributes, active_idx; + struct fwu_mdata *mdata = NULL; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_bank_info; + + ret = fwu_get_mdata(); + if (ret) + return ret; + + ret = 0; + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; + active_bank = mdata->active_index; + img_entry = >img_entry[0]; + for (i = 0; i < nimages; i++) { + img_bank_info = _entry[i].img_bank_info[active_bank]; + if (!img_bank_info->accepted) { + trial_state = 1; + break; + } + } + + if (trial_state) { + var_size = (efi_uintn_t)sizeof(trial_state_ctr); + log_info("System booting in Trial State\n"); + var_attributes = EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS; + status = efi_get_variable_int(u"TrialStateCtr", + _global_variable_guid, + _attributes, + _size, _state_ctr, + NULL); + if (status != EFI_SUCCESS) { + log_err("Unable to read TrialStateCtr variable\n"); + ret = -1; + goto out; + } + + ++trial_state_ctr; + if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) { + log_info("Trial State count exceeded. Revert back to previous_active_index\n"); + active_idx = mdata->active_index; + ret = fwu_revert_boot_index(); + if (ret) { + log_err("Unable to revert active_index\n"); + goto out; + } + + /* Delete the TrialStateCtr var
[PATCH v6 07/13] FWU: STM32MP1: Add support to read boot index from backup register
The FWU Multi Bank Update feature allows the platform to boot the firmware images from one of the partitions(banks). The first stage bootloader(fsbl) passes the value of the boot index, i.e. the bank from which the firmware images were booted from to U-Boot. On the STM32MP157C-DK2 board, this value is passed through one of the SoC's backup register. Add a function to read the boot index value from the backup register. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V5: * Shuffled the location of the TAMP_FWU_* macros as suggested by Patrick arch/arm/mach-stm32mp/include/mach/stm32.h | 5 + board/st/stm32mp1/stm32mp1.c | 8 include/fwu.h | 1 + 3 files changed, 14 insertions(+) diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 47e88fc3dc..0344de796e 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -100,11 +100,16 @@ enum boot_device { #define TAMP_BACKUP_REGISTER(x)(STM32_TAMP_BASE + 0x100 + 4 * x) #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) +#define TAMP_FWU_BOOT_INFO_REG TAMP_BACKUP_REGISTER(10) #define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) #define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) #define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21) +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) + +#define TAMP_FWU_BOOT_IDX_OFFSET 0 + #define TAMP_COPRO_STATE_OFF 0 #define TAMP_COPRO_STATE_INIT 1 #define TAMP_COPRO_STATE_CRUN 2 diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 3aa223d795..6b249fafbb 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -1006,4 +1006,12 @@ int fwu_plat_get_update_index(u32 *update_idx) return ret; } + +void fwu_plat_get_bootidx(void *boot_idx) +{ + u32 *bootidx = boot_idx; + + *bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >> + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; +} #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/include/fwu.h b/include/fwu.h index 38dceca9c5..edb28c9659 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -49,6 +49,7 @@ int fwu_revert_boot_index(void); int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); +void fwu_plat_get_bootidx(void *boot_idx); int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, int *alt_num); int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, -- 2.25.1
[PATCH v6 06/13] FWU: stm32mp1: Add helper functions for accessing FWU metadata
Add helper functions needed for accessing the FWU metadata which contains information on the updatable images. These functions have been added for the STM32MP157C-DK2 board which has the updatable images on the uSD card, formatted as GPT partitions. Signed-off-by: Sughosh Ganu --- Changes since V5: * Change the mechanism to get the block device descriptor in fwu_plat_get_alt_num() due to introduction of struct fwu_mdata_gpt_blk_priv in the earlier patch. board/st/stm32mp1/stm32mp1.c | 40 include/fwu.h| 3 ++ lib/fwu_updates/Makefile | 6 +++ lib/fwu_updates/fwu_gpt.c| 88 4 files changed, 137 insertions(+) create mode 100644 lib/fwu_updates/Makefile create mode 100644 lib/fwu_updates/fwu_gpt.c diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index c6bb7562f6..3aa223d795 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -25,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -967,3 +971,39 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size) } U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); + +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) + +#include +#include + +int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, +int *alt_num) +{ + struct blk_desc *desc; + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); + + desc = dev_get_uclass_plat(priv->blk_dev); + if (!desc) { + log_err("Block device not found\n"); + return -ENODEV; + } + + return fwu_gpt_get_alt_num(desc, image_guid, alt_num, DFU_DEV_MMC); +} + +int fwu_plat_get_update_index(u32 *update_idx) +{ + int ret; + u32 active_idx; + + ret = fwu_get_active_index(_idx); + + if (ret < 0) + return -1; + + *update_idx = active_idx ^= 0x1; + + return ret; +} +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/include/fwu.h b/include/fwu.h index 8259c75d12..38dceca9c5 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -51,4 +51,7 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, int *alt_num); +int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, + int *alt_num, unsigned char dfu_dev); +int fwu_plat_get_update_index(u32 *update_idx); #endif /* _FWU_H_ */ diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile new file mode 100644 index 00..5a59e4a833 --- /dev/null +++ b/lib/fwu_updates/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2022, Linaro Limited +# + +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c new file mode 100644 index 00..434ec76bde --- /dev/null +++ b/lib/fwu_updates/fwu_gpt.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include + +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t *image_guid) +{ + int i; + struct disk_partition info; + efi_guid_t unique_part_guid; + + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { + if (part_get_info(desc, i, )) + continue; + uuid_str_to_bin(info.uuid, unique_part_guid.b, + UUID_STR_FORMAT_GUID); + + if (!guidcmp(_part_guid, image_guid)) + return i; + } + + log_err("No partition found with image_guid %pUs\n", image_guid); + return -ENOENT; +} + +int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, + int *alt_num, unsigned char dfu_dev) +{ + int ret = -1; + int i, part, dev_num; + int nalt; + struct dfu_entity *dfu; + + dev_num = desc->devnum; + part = get_gpt_dfu_identifier(desc, image_guid); + if (part < 0) + return -ENOENT; + + dfu_init_env_entities(NULL, NULL); + + nalt = 0; + list_for_each_entry(dfu, _list, list) { + nalt++; + } + + if (!nalt) { + log_warning("No entities in dfu_alt_info\n"); + dfu_free_entities(); + return -ENOENT; + } + + for (i = 0; i < nalt; i++) { + dfu = dfu_get_entity(i); + + if (!dfu) + continue; + + /* +* Currently, Multi Bank upda
[PATCH v6 05/13] stm32mp1: dk2: Add image information for capsule updates
Enabling capsule update functionality on the platform requires populating information on the images that are to be updated using the functionality. Do so for the DK2 board. Signed-off-by: Sughosh Ganu --- Changes since V5: None board/st/stm32mp1/stm32mp1.c | 19 +++ include/configs/stm32mp15_common.h | 4 2 files changed, 23 insertions(+) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 07b1a63db7..c6bb7562f6 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,16 @@ DECLARE_GLOBAL_DATA_PTR; #define USB_START_LOW_THRESHOLD_UV 123 #define USB_START_HIGH_THRESHOLD_UV215 +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) +struct efi_fw_image fw_images[1]; + +struct efi_capsule_update_info update_info = { + .images = fw_images, +}; + +u8 num_image_type_guids = ARRAY_SIZE(fw_images); +#endif /* EFI_HAVE_CAPSULE_SUPPORT */ + int board_early_init_f(void) { /* nothing to do, only used in SPL */ @@ -675,6 +686,14 @@ int board_init(void) setup_led(LEDST_ON); +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) + if (board_is_dk2()) { + efi_guid_t image_type_guid = STM32MP1_DK2_FIP_IMAGE_GUID; + guidcpy(_images[0].image_type_id, _type_guid); + fw_images[0].fw_name = u"STM32MP1-DK2-FIP"; + fw_images[0].image_index = 5; + } +#endif return 0; } diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h index 6b40cdb017..6a1ae9788d 100644 --- a/include/configs/stm32mp15_common.h +++ b/include/configs/stm32mp15_common.h @@ -54,6 +54,10 @@ #define CONFIG_SYS_AUTOLOAD"no" #endif +#define STM32MP1_DK2_FIP_IMAGE_GUID \ + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \ +0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) + /*/ #ifdef CONFIG_DISTRO_DEFAULTS /*/ -- 2.25.1
[PATCH v6 04/13] stm32mp1: dk2: Add a node for the FWU metadata device
The FWU metadata structure is accessed through the driver model interface. On the stm32mp157c-dk2 board, the FWU metadata is stored on the uSD card. Add the fwu-mdata node on the u-boot specifc dtsi file for accessing the metadata structure. Signed-off-by: Sughosh Ganu Reviewed-by: Patrick Delaunay --- Changes since V5: None arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi index 06ef3a4095..24f86209db 100644 --- a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi @@ -4,3 +4,10 @@ */ #include "stm32mp157a-dk1-u-boot.dtsi" + +/ { + fwu-mdata { + compatible = "u-boot,fwu-mdata-gpt"; + fwu-mdata-store = <>; + }; +}; -- 2.25.1
[PATCH v6 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
In the FWU Multi Bank Update feature, the information about the updatable images is stored as part of the metadata, on a separate partition. Add a driver for reading from and writing to the metadata when the updatable images and the metadata are stored on a block device which is formated with GPT based partition scheme. Signed-off-by: Sughosh Ganu --- Changes since V5: * Changed the logic to store the GPT partitioned block device through a priv structure as suggested by Patrick * Used dev_read_prop() to get the phandle_p instead of ofnode_get_property() used earlier as suggested by Patrick * Make relevant functions static as suggested by Etienne drivers/fwu-mdata/Kconfig | 9 + drivers/fwu-mdata/Makefile| 1 + drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 408 ++ include/fwu.h | 5 + 4 files changed, 423 insertions(+) create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig index d6a21c8e19..d5edef19d6 100644 --- a/drivers/fwu-mdata/Kconfig +++ b/drivers/fwu-mdata/Kconfig @@ -5,3 +5,12 @@ config DM_FWU_MDATA Enable support for accessing FWU Metadata partitions. The FWU Metadata partitions reside on the same storage device which contains the other FWU updatable firmware images. + +config FWU_MDATA_GPT_BLK + bool "FWU Metadata access for GPT partitioned Block devices" + select PARTITION_TYPE_GUID + select PARTITION_UUIDS + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION + help + Enable support for accessing FWU Metadata on GPT partitioned + block devices. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile index e53a8c9983..313049f67a 100644 --- a/drivers/fwu-mdata/Makefile +++ b/drivers/fwu-mdata/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c new file mode 100644 index 00..d904c9492d --- /dev/null +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c @@ -0,0 +1,408 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PRIMARY_PART BIT(0) +#define SECONDARY_PART BIT(1) +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) + +#define MDATA_READ BIT(0) +#define MDATA_WRITEBIT(1) + +static int gpt_get_mdata_partitions(struct blk_desc *desc, + u16 *primary_mpart, + u16 *secondary_mpart) +{ + int i, ret; + u32 mdata_parts; + efi_guid_t part_type_guid; + struct disk_partition info; + const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID; + + mdata_parts = 0; + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { + if (part_get_info(desc, i, )) + continue; + uuid_str_to_bin(info.type_guid, part_type_guid.b, + UUID_STR_FORMAT_GUID); + + if (!guidcmp(_mdata_guid, _type_guid)) { + ++mdata_parts; + if (!*primary_mpart) + *primary_mpart = i; + else + *secondary_mpart = i; + } + } + + if (mdata_parts != 2) { + log_err("Expect two copies of the FWU metadata instead of %d\n", + mdata_parts); + ret = -EINVAL; + } else { + ret = 0; + } + + return ret; +} + +static int gpt_get_mdata_disk_part(struct blk_desc *desc, + struct disk_partition *info, + u32 part_num) +{ + int ret; + char *mdata_guid_str = "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23"; + + ret = part_get_info(desc, part_num, info); + if (ret < 0) { + log_err("Unable to get the partition info for the FWU metadata part %d", + part_num); + return -1; + } + + /* Check that it is indeed the FWU metadata partition */ + if (!strncmp(info->type_guid, mdata_guid_str, UUID_STR_LEN)) { + /* Found the FWU metadata partition */ + return 0; + } + + return -1; +} + +static int gpt_read_write_mdata(struct blk_desc *desc, + struct fwu_mdata *mdata, + u8 access, u32 part_num) +{ + int ret; + u32 len, blk_start, blkcnt; + struct disk_partition info; + +
[PATCH v6 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
In the FWU Multi Bank Update feature, the information about the updatable images is stored as part of the metadata, which is stored on a dedicated partition. Add the metadata structure, and a driver model uclass which provides functions to access the metadata. These are generic API's, and implementations can be added based on parameters like how the metadata partition is accessed and what type of storage device houses the metadata. Signed-off-by: Sughosh Ganu --- Changes since V5: * Change the parameter to the function fwu_plat_get_alt_num to pass the FWU udevice pointer instead of passing the metadata device directly. drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/fwu-mdata/Kconfig| 7 + drivers/fwu-mdata/Makefile | 6 + drivers/fwu-mdata/fwu-mdata-uclass.c | 458 +++ include/dm/uclass-id.h | 1 + include/fwu.h| 49 +++ include/fwu_mdata.h | 67 8 files changed, 591 insertions(+) create mode 100644 drivers/fwu-mdata/Kconfig create mode 100644 drivers/fwu-mdata/Makefile create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c create mode 100644 include/fwu.h create mode 100644 include/fwu_mdata.h diff --git a/drivers/Kconfig b/drivers/Kconfig index b26ca8cf70..adc6079ecf 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -42,6 +42,8 @@ source "drivers/firmware/Kconfig" source "drivers/fpga/Kconfig" +source "drivers/fwu-mdata/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/hwspinlock/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 67c8af7442..901150bb35 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -83,6 +83,7 @@ obj-y += cache/ obj-$(CONFIG_CPU) += cpu/ obj-y += crypto/ obj-$(CONFIG_FASTBOOT) += fastboot/ +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/ obj-y += misc/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_NVME) += nvme/ diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig new file mode 100644 index 00..d6a21c8e19 --- /dev/null +++ b/drivers/fwu-mdata/Kconfig @@ -0,0 +1,7 @@ +config DM_FWU_MDATA + bool "Driver support for accessing FWU Metadata" + depends on DM + help + Enable support for accessing FWU Metadata partitions. The + FWU Metadata partitions reside on the same storage device + which contains the other FWU updatable firmware images. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile new file mode 100644 index 00..e53a8c9983 --- /dev/null +++ b/drivers/fwu-mdata/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2022, Linaro Limited +# + +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c new file mode 100644 index 00..2092fcfc23 --- /dev/null +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c @@ -0,0 +1,458 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define IMAGE_ACCEPT_SET BIT(0) +#define IMAGE_ACCEPT_CLEAR BIT(1) + +static int fwu_get_dev_ops(struct udevice **dev, + const struct fwu_mdata_ops **ops) +{ + int ret; + + ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev); + if (ret) { + log_debug("Cannot find fwu device\n"); + return ret; + } + + if ((*ops = device_get_ops(*dev)) == NULL) { + log_debug("Cannot get fwu device ops\n"); + return -ENOSYS; + } + + return 0; +} + +/** + * fwu_verify_mdata() - Verify the FWU metadata + * @mdata: FWU metadata structure + * @pri_part: FWU metadata partition is primary or secondary + * + * Verify the FWU metadata by computing the CRC32 for the metadata + * structure and comparing it against the CRC32 value stored as part + * of the structure. + * + * Return: 0 if OK, -ve on error + * + */ +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part) +{ + u32 calc_crc32; + void *buf; + + buf = >version; + calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + + if (calc_crc32 != mdata->crc32) { + log_err("crc32 check failed for %s FWU metadata partition\n", + pri_part ? "primary" : "secondary"); + return -1; + } + + return 0; +} + +/** + * fwu_get_active_index() - Get active_index from the FWU metadata + * @active_idx: active_index value to be read + * + * Read the active_index field from the FWU metadata and place it in + * the variable pointed to be the function argument. + * + * Return: 0 if OK, -ve on
[PATCH v6 01/13] dt/bindings: Add bindings for FWU Metadata storage device
Add bindings needed for accessing the FWU metadata partitions. These include the compatible string which point to the access method and the actual device which stores the FWU metadata. The current patch adds basic bindings needed for accessing the metadata structure on GPT partitioned block devices. Signed-off-by: Sughosh Ganu --- Changes since V5: * Changed to yaml file from txt as per review comment .../firmware/fwu-mdata.yaml | 32 +++ 1 file changed, 32 insertions(+) create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.yaml diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.yaml b/doc/device-tree-bindings/firmware/fwu-mdata.yaml new file mode 100644 index 00..97d30bd1c1 --- /dev/null +++ b/doc/device-tree-bindings/firmware/fwu-mdata.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/firmware/fwu-mdata.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: FWU metadata on device with GPT partitioned layout + +maintainers: + - Sughosh Ganu + +properties: + compatible: +items: + - const: u-boot,fwu-mdata-gpt + + fwu-mdata-store: +maxItems: 1 +description: Phandle of the device which contains the FWU medatata partition. + +required: + - compatible + - fwu-mdata-store + +additionalProperties: false + +examples: + - | +fwu-mdata { +compatible = "u-boot,fwu-mdata-gpt"; +fwu-mdata-store = <>; +}; -- 2.25.1
[PATCH v6 00/13] FWU: Add FWU Multi Bank Update feature support
The patchset adds support for the FWU Multi Bank Update[1] feature. Certain aspects of the Dependable Boot[2] specification have also been implemented. The FWU multi bank update feature is used for supporting multiple sets(also called banks) of firmware image(s), allowing the platform to boot from a different bank, in case it fails to boot from the active bank. This functionality is supported by keeping the relevant information in a structure called metadata, which provides information on the images. Among other parameters, the metadata structure contains information on the currect active bank that is being used to boot image(s). Functionality is being added to work with the UEFI capsule driver in u-boot. The metadata is read to gather information on the update bank, which is the bank to which the firmware images would be flashed to. On a successful completion of the update of all components, the active bank field in the metadata is updated, to reflect the bank from which the platform will boot on the subsequent boots. Currently, the feature is being enabled on the STM32MP157C-DK2 and Synquacer boards. The DK2 board boots a FIP image from a uSD card partitioned with the GPT partioning scheme, while the Synquacer board boots a FIP image from a MTD partitioned SPI NOR flash device. This feature also requires changes in a previous stage of bootloader, which parses the metadata and selects the bank to boot the image(s) from. Support has being added in tf-a(BL2 stage) for the STM32MP157C-DK2 board to boot the active bank images. These changes have been merged to the upstream tf-a repository. The earlier patchset contained patches for both the DK2 and the Synquacer platforms. The handling of review comments for the Synquacer platform is to be taken up by a different engineer, and has not been done yet. After discussion with Tom Rini and Heinrich, it was decided to send the patches for the DK2 platform separately for review. The patch for adding a python test for the feature has been developed, and was sent in the version 5 of the patches[3]. However, the test script depends on adding support for the feature on MTD SPI NOR devices, and that is being done as part of the Synquacer patches. Hence these set of patches do not have the test script for the feature. That will be added through the patches for adding support for the feauture on Synquacer platform. [1] - https://developer.arm.com/documentation/den0118/a [2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf [3] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html Changes since V5: * Changed to yaml file from txt as per review comment * Change the parameter to the function fwu_plat_get_alt_num to pass the FWU udevice pointer instead of passing the metadata device directly. * Changed the logic to store the GPT partitioned block device through a priv structure as suggested by Patrick * Used dev_read_prop() to get the phandle_p instead of ofnode_get_property() used earlier as suggested by Patrick * Made relevant functions static as suggested by Etienne * Change the mechanism to get the block device descriptor in fwu_plat_get_alt_num() due to introduction of struct fwu_mdata_gpt_blk_priv in the earlier patch. * Shuffled the location of the TAMP_FWU_* macros as suggested by Patrick * Use u"TrialStateCtr" for the EFI variable name as suggested by Patrick * Dropped the call to uclass_get_device() in fwu_boottime_checks() as suggested by Patrick * Pass NULL instead of a pointer to trial_state_ctr variable when deleting the variable as suggested by Etienne * Use u"TrialStateCtr" as suggested by Patrick * Do a metadata validity check by calling fwu_mdata_check() before printing the FWU metadata as suggested by Michal * Use ret and res variables in do_fwu_mdata_read() as suggested by Patrick * Change 'default y if FWU_MULTI_BANK_UPDATE' to default y as suggested by Patrick * Use capsule_type instead of capsule variable that was created earlier to check for the type of capsule * Remove use of payload variable in create_empty_capsule() as suggested by Etienne * Initialise the struct efi_capsule_header as suggested by Etienne * Add some description about the reasoning for accept capsule needing image GUID as suggested by Takahiro Sughosh Ganu (13): dt/bindings: Add bindings for FWU Metadata storage device FWU: Add FWU metadata structure and driver for accessing metadata FWU: Add FWU metadata access driver for GPT partitioned block devices stm32mp1: dk2: Add a node for the FWU metadata device stm32mp1: dk2: Add image information for capsule updates FWU: stm32mp1: Add helper functions for accessing FWU metadata FWU: STM32MP1: Add support to read boot index from backup register FWU: Add boot time checks as highlighted by the FWU specification FWU: Add support for the FWU Multi Bank Update feature FWU: cmd: Add a command
Re: [PATCH v5 08/23] FWU: Add boot time checks as highlighted by the FWU specification
hi Etienne, On Thu, 23 Jun 2022 at 18:02, Etienne Carriere wrote: > > Hi Sughosh, > > On Thu, 23 Jun 2022 at 11:46, Sughosh Ganu wrote: > > > > hi Etienne, > > > > On Tue, 21 Jun 2022 at 16:26, Etienne Carriere > > wrote: > > > > > > Hi Sughosh, > > > > > > On Thu, 9 Jun 2022 at 14:31, Sughosh Ganu wrote: > > > > > > > > The FWU Multi Bank Update specification requires the Update Agent to > > > > carry out certain checks at the time of platform boot. The Update > > > > Agent is the component which is responsible for updating the firmware > > > > components and maintaining and keeping the metadata in sync. > > > > > > > > The spec requires that the Update Agent perform the following checks > > > > at the time of boot > > > > * Sanity check of both the metadata copies maintained by the platform. > > > > * Get the boot index passed to U-Boot by the prior stage bootloader > > > > and use this value for metadata bookkeeping. > > > > * Check if the system is booting in Trial State. If the system boots > > > > in the Trial State for more than a specified number of boot counts, > > > > change the Active Bank to be booting the platform from. > > > > > > > > Add these checks in the board initialisation sequence, invoked after > > > > relocation. > > > > > > > > Signed-off-by: Sughosh Ganu > > > > --- > > > > common/board_r.c | 5 ++ > > > > include/fwu.h | 3 + > > > > lib/fwu_updates/fwu.c | 170 ++ > > > > 3 files changed, 178 insertions(+) > > > > create mode 100644 lib/fwu_updates/fwu.c > > > > > > > > > > --- /dev/null > > > > +++ b/lib/fwu_updates/fwu.c > > > > @@ -0,0 +1,170 @@ > > > > +// SPDX-License-Identifier: GPL-2.0+ > > > > +/* > > > > + * Copyright (c) 2022, Linaro Limited > > > > + */ > > > > + > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > + > > > > +#include > > > > +#include > > > > + > > > > +static u8 trial_state; > > > > +static u8 boottime_check; > > > > + > > > > +static int fwu_trial_state_check(void) > > > > +{ > > > > + int ret, i; > > > > + efi_status_t status; > > > > + efi_uintn_t var_size; > > > > + u16 trial_state_ctr; > > > > + u32 nimages, active_bank, var_attributes, active_idx; > > > > + struct fwu_mdata *mdata = NULL; > > > > + struct fwu_image_entry *img_entry; > > > > + struct fwu_image_bank_info *img_bank_info; > > > > + > > > > + ret = fwu_get_mdata(); > > > > + if (ret) > > > > + return ret; > > > > + > > > > + ret = 0; > > > > + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; > > > > + active_bank = mdata->active_index; > > > > + img_entry = >img_entry[0]; > > > > + for (i = 0; i < nimages; i++) { > > > > + img_bank_info = > > > > _entry[i].img_bank_info[active_bank]; > > > > + if (!img_bank_info->accepted) { > > > > + trial_state = 1; > > > > + break; > > > > + } > > > > + } > > > > + > > > > + if (trial_state) { > > > > + var_size = (efi_uintn_t)sizeof(trial_state_ctr); > > > > + log_info("System booting in Trial State\n"); > > > > + var_attributes = EFI_VARIABLE_NON_VOLATILE | > > > > + EFI_VARIABLE_BOOTSERVICE_ACCESS; > > > > + status = efi_get_variable_int(L"TrialStateCtr", > > > > + _global_variable_guid, > > > > + _attributes, > > > > + _size, > > > > _state_ctr, > > > > + NULL); > >
Re: [PATCH v5 03/23] FWU: Add FWU metadata access driver for GPT partitioned block devices
hi Etienne, On Tue, 21 Jun 2022 at 16:26, Etienne Carriere wrote: > > Hello Sughosh, > > On Thu, 9 Jun 2022 at 14:30, Sughosh Ganu wrote: > > > > In the FWU Multi Bank Update feature, the information about the > > updatable images is stored as part of the metadata, on a separate > > partition. Add a driver for reading from and writing to the metadata > > when the updatable images and the metadata are stored on a block > > device which is formated with GPT based partition scheme. > > > > Signed-off-by: Sughosh Ganu > > --- > > drivers/fwu-mdata/Kconfig | 9 + > > drivers/fwu-mdata/Makefile| 1 + > > drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 404 ++ > > include/fwu.h | 2 + > > 4 files changed, 416 insertions(+) > > create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > > index d6a21c8e19..d5edef19d6 100644 > > --- a/drivers/fwu-mdata/Kconfig > > +++ b/drivers/fwu-mdata/Kconfig > > @@ -5,3 +5,12 @@ config DM_FWU_MDATA > > Enable support for accessing FWU Metadata partitions. The > > FWU Metadata partitions reside on the same storage device > > which contains the other FWU updatable firmware images. > > + > > +config FWU_MDATA_GPT_BLK > > + bool "FWU Metadata access for GPT partitioned Block devices" > > + select PARTITION_TYPE_GUID > > + select PARTITION_UUIDS > > + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION > > + help > > + Enable support for accessing FWU Metadata on GPT partitioned > > + block devices. > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > > index 7fec7171f4..12a5b4fe04 100644 > > --- a/drivers/fwu-mdata/Makefile > > +++ b/drivers/fwu-mdata/Makefile > > @@ -4,3 +4,4 @@ > > # > > > > obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o > > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o > > diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > new file mode 100644 > > index 00..329bd3779b > > --- /dev/null > > +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > @@ -0,0 +1,404 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#define PRIMARY_PART BIT(0) > > +#define SECONDARY_PART BIT(1) > > +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) > > + > > +#define MDATA_READ BIT(0) > > +#define MDATA_WRITEBIT(1) > > + > > + > > +static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata) > > +{ > > + int ret; > > + u16 primary_mpart = 0, secondary_mpart = 0; > > + > > + ret = gpt_get_mdata_partitions(desc, _mpart, > > + _mpart); > > + > > + if (ret < 0) { > > + log_err("Error getting the FWU metadata partitions\n"); > > + return -ENODEV; > > + } > > + > > + *mdata = malloc(sizeof(struct fwu_mdata)); > > + if (!*mdata) { > > + log_err("Unable to allocate memory for reading FWU > > metadata\n"); > > + return -ENOMEM; > > + } > > + > > + ret = gpt_read_mdata(desc, *mdata, primary_mpart); > > + if (ret < 0) { > > + log_err("Failed to read the FWU metadata from the > > device\n"); > > + return -EIO; > > + } > > + > > + ret = fwu_verify_mdata(*mdata, 1); > > + if (!ret) > > Upon success, I think this function should also either ensure > secondary_part contains a valid copy of primary part, > Maybe this function should call gpt_check_mdata_validity() and then > read mdata content. Okay > > > + return 0; > > + > > + /* > > +* Verification of the primary FWU metadata copy failed. > > +* Try to read the replica. > > +*/ >
Re: [PATCH v5 03/23] FWU: Add FWU metadata access driver for GPT partitioned block devices
hi Patrick, Apologies for the late reply. I had missed out replying to the review comments on this patch. There are some review comments on the Synquacer patches which need to be taken care of by another engineer. Once those review comments are taken care of, I will be sending the next version. On Tue, 21 Jun 2022 at 15:04, Patrick DELAUNAY wrote: > > Hi, > > On 6/9/22 14:29, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > > updatable images is stored as part of the metadata, on a separate > > partition. Add a driver for reading from and writing to the metadata > > when the updatable images and the metadata are stored on a block > > device which is formated with GPT based partition scheme. > > > > Signed-off-by: Sughosh Ganu > > --- > > drivers/fwu-mdata/Kconfig | 9 + > > drivers/fwu-mdata/Makefile| 1 + > > drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 404 ++ > > include/fwu.h | 2 + > > 4 files changed, 416 insertions(+) > > create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > > index 7fec7171f4..12a5b4fe04 100644 > > --- a/drivers/fwu-mdata/Makefile > > +++ b/drivers/fwu-mdata/Makefile > > @@ -4,3 +4,4 @@ > > # > > > > obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o > > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o > > > It is strange to have '_' and '-' in file name for the same directory > > => to be coherent = fwu-mdata-gpt-blk.c I see this kind of naming style in many other directories under drivers/. The uclass file is named using the foo-uclass.c, while the other driver files are named bar_driver.c > > > > diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > new file mode 100644 > > index 00..329bd3779b > > --- /dev/null > > +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c > > @@ -0,0 +1,404 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#define PRIMARY_PART BIT(0) > > +#define SECONDARY_PART BIT(1) > > +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) > > + > > +#define MDATA_READ BIT(0) > > +#define MDATA_WRITE BIT(1) > > + > > + > > > [...] > > > + > > +int fwu_gpt_mdata_check(struct udevice *dev) > > +{ > > + /* > > + * Check if both the copies of the FWU metadata are > > + * valid. If one has gone bad, restore it from the > > + * other good copy. > > + */ > > + return gpt_check_mdata_validity(dev); > > +} > > + > > +int fwu_gpt_get_mdata(struct udevice *dev, struct fwu_mdata **mdata) > > +{ > > + struct blk_desc *desc; > > + > > + desc = dev_get_uclass_plat(dev_get_priv(dev)); > > as dev = fwu_mdata_gpt_blk(UCLASS_FWU_MDATA) > > dev_get_priv(dev) => get value saved in dev_set_priv(dev, mdata_dev); > > even if it is OK, it not clear here. > > can you add a struct to prepare addition of other elements in privdata: > > struct fwu_mdata_gpt_blk_priv { > struct udevice *blk_dev; > } > > > + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > > + struct blk_desc *desc; > > + desc = dev_get_uclass_plat(priv->blk_dev); Okay. Will add a priv structure as you suggest. > > > > + if (!desc) { > > + log_err("Block device not found\n"); > > + return -ENODEV; > > + } > > + > > + return gpt_get_mdata(desc, mdata); > > +} > > + > > +int fwu_get_mdata_device(struct udevice *dev, struct udevice **mdata_dev) > > +{ > > + u32 phandle; > > + int ret, size; > > + struct udevice *parent, *child; > > + const fdt32_t *phandle_p = NULL; > > + > > + phandle_p = ofnode_get_property(dev_ofnode(dev), "fwu-mdata-store", > > + ); > > phandle_p = dev_read_prop(dev, "fwu-mdata-store", ); > > > it is more simple Okay > > > > + if (!phandle_
Re: [PATCH v5 08/23] FWU: Add boot time checks as highlighted by the FWU specification
hi Patrick, On Tue, 21 Jun 2022 at 17:16, Patrick DELAUNAY wrote: > > Hi, > > > On 6/9/22 14:29, Sughosh Ganu wrote: > > The FWU Multi Bank Update specification requires the Update Agent to > > carry out certain checks at the time of platform boot. The Update > > Agent is the component which is responsible for updating the firmware > > components and maintaining and keeping the metadata in sync. > > > > The spec requires that the Update Agent perform the following checks > > at the time of boot > > * Sanity check of both the metadata copies maintained by the platform. > > * Get the boot index passed to U-Boot by the prior stage bootloader > >and use this value for metadata bookkeeping. > > * Check if the system is booting in Trial State. If the system boots > >in the Trial State for more than a specified number of boot counts, > >change the Active Bank to be booting the platform from. > > > > Add these checks in the board initialisation sequence, invoked after > > relocation. > > > > Signed-off-by: Sughosh Ganu > > --- > > common/board_r.c | 5 ++ > > include/fwu.h | 3 + > > lib/fwu_updates/fwu.c | 170 ++ > > 3 files changed, 178 insertions(+) > > create mode 100644 lib/fwu_updates/fwu.c > > > > diff --git a/common/board_r.c b/common/board_r.c > > index 6f4aca2077..33a600715d 100644 > > --- a/common/board_r.c > > +++ b/common/board_r.c > > @@ -15,6 +15,7 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -797,6 +798,10 @@ static init_fnc_t init_sequence_r[] = { > > #if defined(CONFIG_PRAM) > > initr_mem, > > #endif > > + > > +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE > > + fwu_boottime_checks, > > +#endif > > run_main_loop, > > }; > > > > diff --git a/include/fwu.h b/include/fwu.h > > index 41774ff9e2..8fbd91b463 100644 > > --- a/include/fwu.h > > +++ b/include/fwu.h > > @@ -33,6 +33,9 @@ struct fwu_mdata_ops { > > EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ > >0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) > > > > +int fwu_boottime_checks(void); > > +u8 fwu_update_checks_pass(void); > > + > > int fwu_get_mdata(struct fwu_mdata **mdata); > > int fwu_update_mdata(struct fwu_mdata *mdata); > > int fwu_get_active_index(u32 *active_idx); > > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > > new file mode 100644 > > index 00..af884439fb > > --- /dev/null > > +++ b/lib/fwu_updates/fwu.c > > @@ -0,0 +1,170 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > + > > +static u8 trial_state; > > +static u8 boottime_check; > > + > > +static int fwu_trial_state_check(void) > > +{ > > + int ret, i; > > + efi_status_t status; > > + efi_uintn_t var_size; > > + u16 trial_state_ctr; > > + u32 nimages, active_bank, var_attributes, active_idx; > > + struct fwu_mdata *mdata = NULL; > > + struct fwu_image_entry *img_entry; > > + struct fwu_image_bank_info *img_bank_info; > > + > > + ret = fwu_get_mdata(); > > + if (ret) > > + return ret; > > + > > + ret = 0; > > + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; > > + active_bank = mdata->active_index; > > + img_entry = >img_entry[0]; > > + for (i = 0; i < nimages; i++) { > > + img_bank_info = _entry[i].img_bank_info[active_bank]; > > + if (!img_bank_info->accepted) { > > + trial_state = 1; > > + break; > > + } > > + } > > + > > + if (trial_state) { > > + var_size = (efi_uintn_t)sizeof(trial_state_ctr); > > + log_info("System booting in Trial State\n"); > > + var_attributes = EFI_VARIABLE_NON_VOLATILE | > > + EFI_VARIABLE_BOOTSERVICE_ACCESS; > > + status = efi_get_variable_int(L"TrialStateCtr", > > + _global_variable_guid, > > +
Re: [PATCH v5 08/23] FWU: Add boot time checks as highlighted by the FWU specification
hi Etienne, On Tue, 21 Jun 2022 at 16:26, Etienne Carriere wrote: > > Hi Sughosh, > > On Thu, 9 Jun 2022 at 14:31, Sughosh Ganu wrote: > > > > The FWU Multi Bank Update specification requires the Update Agent to > > carry out certain checks at the time of platform boot. The Update > > Agent is the component which is responsible for updating the firmware > > components and maintaining and keeping the metadata in sync. > > > > The spec requires that the Update Agent perform the following checks > > at the time of boot > > * Sanity check of both the metadata copies maintained by the platform. > > * Get the boot index passed to U-Boot by the prior stage bootloader > > and use this value for metadata bookkeeping. > > * Check if the system is booting in Trial State. If the system boots > > in the Trial State for more than a specified number of boot counts, > > change the Active Bank to be booting the platform from. > > > > Add these checks in the board initialisation sequence, invoked after > > relocation. > > > > Signed-off-by: Sughosh Ganu > > --- > > common/board_r.c | 5 ++ > > include/fwu.h | 3 + > > lib/fwu_updates/fwu.c | 170 ++ > > 3 files changed, 178 insertions(+) > > create mode 100644 lib/fwu_updates/fwu.c > > --- /dev/null > > +++ b/lib/fwu_updates/fwu.c > > @@ -0,0 +1,170 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > + > > +static u8 trial_state; > > +static u8 boottime_check; > > + > > +static int fwu_trial_state_check(void) > > +{ > > + int ret, i; > > + efi_status_t status; > > + efi_uintn_t var_size; > > + u16 trial_state_ctr; > > + u32 nimages, active_bank, var_attributes, active_idx; > > + struct fwu_mdata *mdata = NULL; > > + struct fwu_image_entry *img_entry; > > + struct fwu_image_bank_info *img_bank_info; > > + > > + ret = fwu_get_mdata(); > > + if (ret) > > + return ret; > > + > > + ret = 0; > > + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; > > + active_bank = mdata->active_index; > > + img_entry = >img_entry[0]; > > + for (i = 0; i < nimages; i++) { > > + img_bank_info = _entry[i].img_bank_info[active_bank]; > > + if (!img_bank_info->accepted) { > > + trial_state = 1; > > + break; > > + } > > + } > > + > > + if (trial_state) { > > + var_size = (efi_uintn_t)sizeof(trial_state_ctr); > > + log_info("System booting in Trial State\n"); > > + var_attributes = EFI_VARIABLE_NON_VOLATILE | > > + EFI_VARIABLE_BOOTSERVICE_ACCESS; > > + status = efi_get_variable_int(L"TrialStateCtr", > > + _global_variable_guid, > > + _attributes, > > + _size, _state_ctr, > > + NULL); > > + if (status != EFI_SUCCESS) { > > + log_err("Unable to read TrialStateCtr variable\n"); > > + ret = -1; > > + goto out; > > + } > > + > > + ++trial_state_ctr; > > + if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) { > > + log_info("Trial State count exceeded. Revert back > > to previous_active_index\n"); > > + active_idx = mdata->active_index; > > + ret = fwu_revert_boot_index(); > > + if (ret) { > > + log_err("Unable to revert active_index\n"); > > + goto out; > > + } > > + > > + trial_state_ctr = 0; > > + status = efi_set_variable_int(L"TrialStateCtr", > > + > > _global_variable_g
Re: [PATCH v5 07/23] FWU: STM32MP1: Add support to read boot index from backup register
On Tue, 21 Jun 2022 at 16:57, Patrick DELAUNAY wrote: > > Hi, > > On 6/9/22 14:29, Sughosh Ganu wrote: > > The FWU Multi Bank Update feature allows the platform to boot the > > firmware images from one of the partitions(banks). The first stage > > bootloader(fsbl) passes the value of the boot index, i.e. the bank > > from which the firmware images were booted from to U-Boot. On the > > STM32MP157C-DK2 board, this value is passed through one of the SoC's > > backup register. Add a function to read the boot index value from the > > backup register. > > > > Signed-off-by: Sughosh Ganu > > --- > > arch/arm/mach-stm32mp/include/mach/stm32.h | 4 > > board/st/stm32mp1/stm32mp1.c | 7 +++ > > include/fwu.h | 2 +- > > 3 files changed, 12 insertions(+), 1 deletion(-) > > > > diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h > > b/arch/arm/mach-stm32mp/include/mach/stm32.h > > index 47e88fc3dc..40995ee142 100644 > > --- a/arch/arm/mach-stm32mp/include/mach/stm32.h > > +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h > > @@ -100,6 +100,7 @@ enum boot_device { > > #define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 > > * x) > > #define TAMP_BACKUP_MAGIC_NUMBERTAMP_BACKUP_REGISTER(4) > > #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) > > +#define TAMP_FWU_BOOT_INFO_REG TAMP_BACKUP_REGISTER(10) > > #define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) > > #define TAMP_COPRO_STATETAMP_BACKUP_REGISTER(18) > > #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) > > @@ -118,6 +119,9 @@ enum boot_device { > > #define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0) > > #define TAMP_BOOT_FORCED_MASK GENMASK(7, 0) > > #define TAMP_BOOT_DEBUG_ON BIT(16) > > +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) > > + > > +#define TAMP_FWU_BOOT_IDX_OFFSET 0 > > > > > please don't mix the 2 TAMP_FWU defines with define and enum for TAMP_BOOT > > => move the 2 defines before TAMP_COPRO defines. > > > #define TAMP_BACKUP_MAGIC_NUMBERTAMP_BACKUP_REGISTER(4) > #define TAMP_BACKUP_BRANCH_ADDRESSTAMP_BACKUP_REGISTER(5) > + #define TAMP_FWU_BOOT_INFO_REGTAMP_BACKUP_REGISTER(10) > #define TAMP_COPRO_RSC_TBL_ADDRESSTAMP_BACKUP_REGISTER(17) > #define TAMP_COPRO_STATETAMP_BACKUP_REGISTER(18) > #define TAMP_BOOT_CONTEXTTAMP_BACKUP_REGISTER(20) > #define TAMP_BOOTCOUNTTAMP_BACKUP_REGISTER(21) > > + > > +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) > > + #define TAMP_FWU_BOOT_IDX_OFFSET 0 Will change as per your suggestion. Thanks. -sughosh > > > #define TAMP_COPRO_STATE_OFF0 > #define TAMP_COPRO_STATE_INIT1 > > > > enum forced_boot_mode { > > BOOT_NORMAL = 0x00, > > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > > index e68bf09955..dff41ed6f6 100644 > > --- a/board/st/stm32mp1/stm32mp1.c > > +++ b/board/st/stm32mp1/stm32mp1.c > > @@ -1081,4 +1081,11 @@ int fwu_plat_get_update_index(u32 *update_idx) > > return ret; > > } > > > > +void fwu_plat_get_bootidx(void *boot_idx) > > +{ > > + u32 *bootidx = boot_idx; > > + > > + *bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >> > > + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; > > +} > > #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ > > diff --git a/include/fwu.h b/include/fwu.h > > index 36e58afa29..41774ff9e2 100644 > > --- a/include/fwu.h > > +++ b/include/fwu.h > > @@ -46,7 +46,7 @@ int fwu_revert_boot_index(void); > > int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); > > int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); > > > > - > > +void fwu_plat_get_bootidx(void *boot_idx); > > int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, > >int *alt_num); > > int fwu_plat_get_update_index(u32 *update_idx); > > With the modifications: > > Reviewed-by: Patrick Delaunay > > Thanks > Patrick > >
Re: [PATCH v5 02/23] FWU: Add FWU metadata structure and driver for accessing metadata
hi Etienne, On Tue, 21 Jun 2022 at 16:24, Etienne Carriere wrote: > > Hello Sughosh, > > > > On Thu, 9 Jun 2022 at 14:30, Sughosh Ganu wrote: > > > > In the FWU Multi Bank Update feature, the information about the > > updatable images is stored as part of the metadata, which is stored on > > a dedicated partition. Add the metadata structure, and a driver model > > uclass which provides functions to access the metadata. These are > > generic API's, and implementations can be added based on parameters > > like how the metadata partition is accessed and what type of storage > > device houses the metadata. > > > > Signed-off-by: Sughosh Ganu > > --- > > drivers/Kconfig | 2 + > > drivers/Makefile | 1 + > > drivers/fwu-mdata/Kconfig| 7 + > > drivers/fwu-mdata/Makefile | 6 + > > drivers/fwu-mdata/fwu-mdata-uclass.c | 459 +++ > > include/dm/uclass-id.h | 1 + > > include/fwu.h| 49 +++ > > include/fwu_mdata.h | 67 > > 8 files changed, 592 insertions(+) > > create mode 100644 drivers/fwu-mdata/Kconfig > > create mode 100644 drivers/fwu-mdata/Makefile > > create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c > > create mode 100644 include/fwu.h > > create mode 100644 include/fwu_mdata.h > > > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > > b/drivers/fwu-mdata/fwu-mdata-uclass.c > > new file mode 100644 > > index 00..1530ceb01d > > --- /dev/null > > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > > @@ -0,0 +1,459 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#define IMAGE_ACCEPT_SET BIT(0) > > +#define IMAGE_ACCEPT_CLEAR BIT(1) > > + > > +static int fwu_get_dev_ops(struct udevice **dev, > > + const struct fwu_mdata_ops **ops) > > +{ > > + int ret; > > + > > + ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev); > > + if (ret) { > > + log_debug("Cannot find fwu device\n"); > > + return ret; > > + } > > + > > + if ((*ops = device_get_ops(*dev)) == NULL) { > > + log_debug("Cannot get fwu device ops\n"); > > + return -ENOSYS; > > + } > > + > > + return 0; > > +} > > + > > +/** > > + * fwu_verify_mdata() - Verify the FWU metadata > > + * @mdata: FWU metadata structure > > + * @pri_part: FWU metadata partition is primary or secondary > > + * > > + * Verify the FWU metadata by computing the CRC32 for the metadata > > + * structure and comparing it against the CRC32 value stored as part > > + * of the structure. > > + * > > + * Return: 0 if OK, -ve on error > > + * > > + */ > > +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part) > > +{ > > + u32 calc_crc32; > > + void *buf; > > + > > + buf = >version; > > + calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); > > + > > + if (calc_crc32 != mdata->crc32) { > > + log_err("crc32 check failed for %s FWU metadata > > partition\n", > > + pri_part ? "primary" : "secondary"); > > + return -1; > > + } > > + > > + return 0; > > +} > > + > > +/** > > + * fwu_get_active_index() - Get active_index from the FWU metadata > > + * @active_idx: active_index value to be read > > + * > > + * Read the active_index field from the FWU metadata and place it in > > + * the variable pointed to be the function argument. > > + * > > + * Return: 0 if OK, -ve on error > > + * > > + */ > > +int fwu_get_active_index(u32 *active_idx) > > +{ > > + int ret; > > + struct fwu_mdata *mdata = NULL; > > + > > + ret = fwu_get_mdata(); > > + if (ret < 0) { > > + log_err("Unable to get valid FWU metadata\n"); > > + goto out; > > + } > > + > > + /* > > +* Found the FWU metad
Re: [PATCH v5 06/23] FWU: stm32mp1: Add helper functions for accessing FWU metadata
On Tue, 21 Jun 2022 at 15:19, Patrick DELAUNAY wrote: > > Hi, > > On 6/9/22 14:29, Sughosh Ganu wrote: > > Add helper functions needed for accessing the FWU metadata which > > contains information on the updatable images. These functions have > > been added for the STM32MP157C-DK2 board which has the updatable > > images on the uSD card, formatted as GPT partitions. > > > > Signed-off-by: Sughosh Ganu > > --- > > board/st/stm32mp1/stm32mp1.c | 115 +++ > > include/fwu.h| 2 + > > 2 files changed, 117 insertions(+) > > > > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > > index 62d98ad776..e68bf09955 100644 > > --- a/board/st/stm32mp1/stm32mp1.c > > +++ b/board/st/stm32mp1/stm32mp1.c > > @@ -7,9 +7,11 @@ > > > > #include > > #include > > +#include > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -25,9 +27,11 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -967,3 +971,114 @@ static void board_copro_image_process(ulong fw_image, > > size_t fw_size) > > } > > > > U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); > > + > > +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) > > +#include > > +#include > > + > [...] > > + > > +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ > > diff --git a/include/fwu.h b/include/fwu.h > > index 3b1ee4e83e..36e58afa29 100644 > > --- a/include/fwu.h > > +++ b/include/fwu.h > > @@ -46,6 +46,8 @@ int fwu_revert_boot_index(void); > > int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); > > int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); > > > > + > > > Added empty line Will remove > > > > int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, > >int *alt_num); > > +int fwu_plat_get_update_index(u32 *update_idx); > > #endif /* _FWU_H_ */ > > > And I am agree with Ilias remark, should be generic > > => search on the current UCLASS_FWU_MDATA > > perhaps need a new ops in u-class ? as implementation can be > different for GPT and MTD. My understanding of Ilias's comments was that the function can be generic for all GPT based platforms. But I will check if this can be reused for both GPT and MTD devices, on the lines that you mention above. Thanks. -sughosh
Re: [PATCH v5 00/23] FWU: Add FWU Multi Bank Update feature support
hi, On Mon, 20 Jun 2022 at 23:42, Patrick DELAUNAY wrote: > > Hi, > > On 6/9/22 14:29, Sughosh Ganu wrote: > > The patchset adds support for the FWU Multi Bank Update[1] > > feature. Certain aspects of the Dependable Boot[2] specification have > > also been implemented. > > > > The FWU multi bank update feature is used for supporting multiple > > sets(also called banks) of firmware image(s), allowing the platform to > > boot from a different bank, in case it fails to boot from the active > > bank. This functionality is supported by keeping the relevant > > information in a structure called metadata, which provides information > > on the images. Among other parameters, the metadata structure contains > > information on the currect active bank that is being used to boot > > image(s). > > > > Functionality is being added to work with the UEFI capsule driver in > > u-boot. The metadata is read to gather information on the update bank, > > which is the bank to which the firmware images would be flashed to. On > > a successful completion of the update of all components, the active > > bank field in the metadata is updated, to reflect the bank from which > > the platform will boot on the subsequent boots. > > > > Currently, the feature is being enabled on the STM32MP157C-DK2 and > > Synquacer boards. The DK2 board boots a FIP image from a uSD card > > partitioned with the GPT partioning scheme, while the Synquacer board > > boots a FIP image from a MTD partitioned SPI NOR flash device. > > > > This feature also requires changes in a previous stage of > > bootloader, which parses the metadata and selects the bank to boot the > > image(s) from. Support has being added in tf-a(BL2 stage) for the > > STM32MP157C-DK2 board to boot the active bank images. These changes > > have been merged to the upstream tf-a repository. > > > > Earlier, two separate patchsets were being sent. The patchset sent by > > me was adding support for the feature, and enabling the feature on the > > ST board. The other set of patches were being sent by Masami > > Hiramatsu, which were enabling the feature on the Synquacer > > platform. This patchset contains both set of patches, along with the > > associated documentation and the python test script for testing the > > feature. > > > > The upstreaming effort for this feature had been put on a temporary > > hold to address the fixing of some issues in the capsule update code, > > primarily using a per platform image GUID for the updatable > > images. Now that the series has been merged, upstreaming effort for > > the FWU update feature is being resumed. Hence, this version does not > > have any review comments being addressed. > > > > > > [1] - https://developer.arm.com/documentation/den0118/a > > [2] - > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf > > > > Jassi Brar (1): > >developerbox: synquacer: Use FIP as the updatable image > > > > Masami Hiramatsu (9): > >FWU: Add FWU metadata access driver for non-GPT MTD devices > >dt/bindings: firmware: Add FWU metadata on MTD devices binding > >tools: Add mkfwumdata tool for FWU metadata image > >FWU: doc: Update documentation for the FWU non-GPT MTD > >synquacer: Update for TBBR (BL2) based new FIP layout > >FWU: synquacer: Add FWU Multi bank update support for DeveloperBox > >FWU: synquacer: Generate dfu_alt_info from devicetree partition > >doc: synquacer: Add how to enable FWU Multi Bank Update > >[TEMP]configs: synquacer: Add FWU support for DeveloperBox > > > > Sughosh Ganu (13): > >dt/bindings: Add bindings for FWU Metadata storage device > >FWU: Add FWU metadata structure and driver for accessing metadata > >FWU: Add FWU metadata access driver for GPT partitioned block devices > >stm32mp1: dk2: Add a node for the FWU metadata device > >stm32mp1: dk2: Add image information for capsule updates > >FWU: stm32mp1: Add helper functions for accessing FWU metadata > >FWU: STM32MP1: Add support to read boot index from backup register > >FWU: Add boot time checks as highlighted by the FWU specification > >FWU: Add support for the FWU Multi Bank Update feature > >FWU: cmd: Add a command to read FWU metadata > >mkeficapsule: Add support for generating empty capsules > >FWU: doc: Add documentation for the FWU feature > >sandbox: fwu: Add support for testing FWU feature on sandbox > > > > arch/arm/dts/
Re: [PATCH v5 11/23] mkeficapsule: Add support for generating empty capsules
Takahiro, On Fri, 17 Jun 2022 at 06:16, Takahiro Akashi wrote: > > Sughosh, > > On Thu, Jun 16, 2022 at 12:42:08PM +0530, Sughosh Ganu wrote: > > hi Takahiro, > > > > On Thu, 16 Jun 2022 at 06:31, Takahiro Akashi > > wrote: > > > > > > Sughosh, > > > > > > On Wed, Jun 15, 2022 at 04:19:56PM +0530, Sughosh Ganu wrote: > > > > On Wed, 15 Jun 2022 at 10:41, Takahiro Akashi > > > > wrote: > > > > > > > > > > On Thu, Jun 09, 2022 at 05:59:58PM +0530, Sughosh Ganu wrote: > > > > > > The Dependable Boot specification[1] describes the structure of the > > > > > > firmware accept and revert capsules. These are empty capsules which > > > > > > are used for signalling the acceptance or rejection of the updated > > > > > > firmware by the OS. Add support for generating these empty capsules. > > > > > > > > > > > > [1] - > > > > > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf > > > > > > > > > > > > Signed-off-by: Sughosh Ganu > > > > > > --- > > > > > > doc/mkeficapsule.1 | 29 ++--- > > > > > > tools/eficapsule.h | 8 +++ > > > > > > tools/mkeficapsule.c | 139 > > > > > > +-- > > > > > > 3 files changed, 151 insertions(+), 25 deletions(-) > > > > > > > > > > > > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 > > > > > > index 09bdc24295..77ca061efd 100644 > > > > > > --- a/doc/mkeficapsule.1 > > > > > > +++ b/doc/mkeficapsule.1 > > > > > > @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot > > > > > > > > > > > > .SH SYNOPSIS > > > > > > .B mkeficapsule > > > > > > -.RI [ options "] " image-blob " " capsule-file > > > > > > +.RI [ options ] " " [ image-blob ] " " capsule-file > > > > > > > > > > > > .SH "DESCRIPTION" > > > > > > .B mkeficapsule > > > > > > @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a > > > > > > given private key. > > > > > > In this case, the update will be authenticated by verifying the > > > > > > signature > > > > > > before applying. > > > > > > > > > > > > +Additionally, an empty capsule file can be generated for > > > > > > acceptance or > > > > > > +rejection of firmware images by a governing component like an > > > > > > Operating > > > > > > +System. The empty capsules do not require an image-blob input file. > > > > > > + > > > > > > + > > > > > > .B mkeficapsule > > > > > > -takes any type of image files, including: > > > > > > +takes any type of image files when generating non empty capsules, > > > > > > including: > > > > > > .TP > > > > > > .I raw image > > > > > > format is a single binary blob of any type of firmware. > > > > > > @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file. > > > > > > This type of image file can be generated by > > > > > > .BR mkimage . > > > > > > > > > > > > -.PP > > > > > > -If you want to use other types than above two, you should > > > > > > explicitly > > > > > > -specify a guid for the FMP driver. > > > > > > - > > > > > > .SH "OPTIONS" > > > > > > + > > > > > > .TP > > > > > > .BI "-g\fR,\fB --guid " guid-string > > > > > > Specify guid for image blob type. The format is: > > > > > > ---- > > > > > > > > > > > > The first three elements are in little endian, while the rest > > > > > > -is in big endian. > > > > > > +is in big endian. The option must be specified for all non empty > > > > > > and > > > > > > +image acceptance capsules > > > > > > > > &g
Re: [PATCH v5 23/23] sandbox: fwu: Add support for testing FWU feature on sandbox
On Fri, 17 Jun 2022 at 06:38, Takahiro Akashi wrote: > > Sughosh, > > On Wed, Jun 15, 2022 at 05:40:12PM +0530, Sughosh Ganu wrote: > > On Wed, 15 Jun 2022 at 11:07, Takahiro Akashi > > wrote: > > > > > > On Thu, Jun 09, 2022 at 06:00:10PM +0530, Sughosh Ganu wrote: > > > > Add a python test script for testing the FWU Multi Bank Update > > > > functionality on the sandbox platform. The script has test cases for > > > > updation of the u-boot binary and the u-boot environment image to the > > > > non active bank. > > > > > > > > The FWU metadata is being stored on the SPI NOR flash, along with the > > > > updatable images, and the FWU metadata driver for MTD devices is being > > > > used for accessing the metadata. Certain FWU boottime checks are > > > > bypassed due to the unavailability of the EFI variable access very > > > > early in the boot on the sandbox platform -- the variable access is > > > > only available once the block disk image has been bound through the > > > > host interface. > > > > > > > > The FWU Multi Bank feature being enabled on the sandbox64 platform is > > > > enabling the RAW Firmware Management Protocol(FMP) instance, therefore > > > > the FIT FMP instance is being removed -- the FIT FMP is already being > > > > tested on the sandbox flattree variant. > > > > > > IMO, > > > Thinking of the importance of this feature, FIT FMP should also be > > > tested *with FWU*. > > > > How will the FWU update feature work for FIT images? As I understand > > So are you deliberately designing and proposing a solution that is > incompatible with (or not applicable to) an existing interface (FIT FMP)? Heh, why would anyone do that? The very fact that we are introducing support on two platforms, one with a GPT layout, and another with MTD is because the idea is to encourage adoption on multiple platforms. Secondly, this is a specification from Arm which was driven by Jose Marinho, and I believe he has incorporated feedback from various engineers for drafting the specification -- this specification is not limited only to platforms booting with u-boot. The main issue, as I see it, is that the FWU metadata is doing the bookkeeping for images that are present on the platform's storage device, and this just does not map with FIT which is a packaging mechanism. However, this being software, you can make changes to the fit_update function and incorporate the information from the metadata to write to the relevant locations. However, this needs to be thought through. > > > FIT, it is a way of packaging different firmware images into a single > > package. At the time of writing the images, the FIT image parser would > > check the image configuration, and write the images to their > > respective locations. As you are aware, for the FWU feature, the > > information about the images, and the update bank is obtained from the > > structure called metadata. How does the FIT update mechanism map with > > the FWU metadata which is used to identify which bank needs to be > > updated. The bank to which the image is to be written translates into > > the DFU alt_num value for that image, and this gets computed at > > runtime. In the case of the FIT image, as per my understanding, the > > alt_num value is irrelevant. So my question is, how do we map the > > information obtained from the FWU metadata to tell the FIT image > > writing function(fit_update) which locations do the images need to be > > written to. I think this needs some more thought. > > > > > > > > > Signed-off-by: Sughosh Ganu > > > > --- > > > > arch/sandbox/Kconfig | 6 + > > > > arch/sandbox/dts/test.dts | 45 ++- > > > > board/sandbox/sandbox.c | 49 +++ > > > > configs/sandbox64_defconfig | 12 +- > > > > include/fwu.h | 2 + > > > > lib/fwu_updates/Kconfig | 2 +- > > > > lib/fwu_updates/fwu.c | 18 +- > > > > lib/fwu_updates/fwu_mtd.c | 10 +- > > > > .../test_capsule_firmware_fit.py | 1 - > > > > .../py/tests/test_fwu_updates/capsule_defs.py | 10 + > > > > test/py/tests/test_fwu_updates/conftest.py| 78 > > > > .../test_fwu_updates/test_fwu_updates.py | 367 ++ > > > > 12 files changed, 587 insertions(+), 13 deletions(
Re: [PATCH v5 01/23] dt/bindings: Add bindings for FWU Metadata storage device
On Thu, 16 Jun 2022 at 19:04, Michal Simek wrote: > > čt 9. 6. 2022 v 14:30 odesílatel Sughosh Ganu > napsal: > > > > Add bindings needed for accessing the FWU metadata partitions. These > > include the compatible string which point to the access method and the > > actual device which stores the FWU metadata. > > > > The current patch adds basic bindings needed for accessing the > > metadata structure on GPT partitioned block devices. > > > > Signed-off-by: Sughosh Ganu > > --- > > .../firmware/fwu-mdata.txt | 18 ++ > > Why is this in txt file when mtd one is in yaml. > doc/device-tree-bindings/firmware/uboot,fwu-mdata-mtd.yaml The above binding was written by me in txt, while the mtd one is authored by Masami Hiramatsu. I will change this to yaml in the next version. -sughosh > > Thanks, > Michal > > -- > Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 > w: www.monstr.eu p: +42-0-721842854 > Maintainer of Linux kernel - Xilinx Microblaze > Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs > U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs
Re: [PATCH v5 11/23] mkeficapsule: Add support for generating empty capsules
hi Takahiro, On Thu, 16 Jun 2022 at 06:31, Takahiro Akashi wrote: > > Sughosh, > > On Wed, Jun 15, 2022 at 04:19:56PM +0530, Sughosh Ganu wrote: > > On Wed, 15 Jun 2022 at 10:41, Takahiro Akashi > > wrote: > > > > > > On Thu, Jun 09, 2022 at 05:59:58PM +0530, Sughosh Ganu wrote: > > > > The Dependable Boot specification[1] describes the structure of the > > > > firmware accept and revert capsules. These are empty capsules which > > > > are used for signalling the acceptance or rejection of the updated > > > > firmware by the OS. Add support for generating these empty capsules. > > > > > > > > [1] - > > > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf > > > > > > > > Signed-off-by: Sughosh Ganu > > > > --- > > > > doc/mkeficapsule.1 | 29 ++--- > > > > tools/eficapsule.h | 8 +++ > > > > tools/mkeficapsule.c | 139 +-- > > > > 3 files changed, 151 insertions(+), 25 deletions(-) > > > > > > > > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 > > > > index 09bdc24295..77ca061efd 100644 > > > > --- a/doc/mkeficapsule.1 > > > > +++ b/doc/mkeficapsule.1 > > > > @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot > > > > > > > > .SH SYNOPSIS > > > > .B mkeficapsule > > > > -.RI [ options "] " image-blob " " capsule-file > > > > +.RI [ options ] " " [ image-blob ] " " capsule-file > > > > > > > > .SH "DESCRIPTION" > > > > .B mkeficapsule > > > > @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a > > > > given private key. > > > > In this case, the update will be authenticated by verifying the > > > > signature > > > > before applying. > > > > > > > > +Additionally, an empty capsule file can be generated for acceptance or > > > > +rejection of firmware images by a governing component like an Operating > > > > +System. The empty capsules do not require an image-blob input file. > > > > + > > > > + > > > > .B mkeficapsule > > > > -takes any type of image files, including: > > > > +takes any type of image files when generating non empty capsules, > > > > including: > > > > .TP > > > > .I raw image > > > > format is a single binary blob of any type of firmware. > > > > @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file. > > > > This type of image file can be generated by > > > > .BR mkimage . > > > > > > > > -.PP > > > > -If you want to use other types than above two, you should explicitly > > > > -specify a guid for the FMP driver. > > > > - > > > > .SH "OPTIONS" > > > > + > > > > .TP > > > > .BI "-g\fR,\fB --guid " guid-string > > > > Specify guid for image blob type. The format is: > > > > ---- > > > > > > > > The first three elements are in little endian, while the rest > > > > -is in big endian. > > > > +is in big endian. The option must be specified for all non empty and > > > > +image acceptance capsules > > > > > > "image acceptance" -> "firmware acceptance" > > > > Okay > > > > > > > > I don't still understand why we need a guid for acceptance > > > while revert doesn't require it. > > > I believe that firmware update is "all or nothing", isn't it? > > > > I believe this gives more flexibility in that different components > > might be required to accept the various firmware images. So, one > > component might accept the optee_os, while another might be > > responsible for accepting u-boot. In any case, we do check that all > > the components have their accepted bit set, and only if so, does the > > bank boot in the regular state. > > Probably I don't understand the behavior. > Let's assume that we have firmware A and firmware B and then > update both. > When the firmware A is accepted and B is not (not yet issuing > acceptance capsule) and I try to reboot the system, what happens? > From which bank does the system boot, old one or new one? Onc
Re: [PATCH v5 23/23] sandbox: fwu: Add support for testing FWU feature on sandbox
On Wed, 15 Jun 2022 at 12:00, Takahiro Akashi wrote: > > On Thu, Jun 09, 2022 at 06:00:10PM +0530, Sughosh Ganu wrote: > > Add a python test script for testing the FWU Multi Bank Update > > functionality on the sandbox platform. The script has test cases for > > updation of the u-boot binary and the u-boot environment image to the > > non active bank. > > IIUC, your test doesn't not exercise neither accept-capsule nor > revert capsule. > I think those tests are crucial for verifying the code. Yes, this is on my todo list. By default, all the images get accepted by the firmware itself, which is being done in u-boot. In case the oemflag bit 15 is set to 1 in the capsule header, the image acceptance is done through the accept capsule. I will need to add support for passing the oemflag parameter to the mkeficapsule, and then I can test this. Will keep this on my todo list, and try to put it in the upcoming versions. -sughosh > > -Takahiro Akashi > > > The FWU metadata is being stored on the SPI NOR flash, along with the > > updatable images, and the FWU metadata driver for MTD devices is being > > used for accessing the metadata. Certain FWU boottime checks are > > bypassed due to the unavailability of the EFI variable access very > > early in the boot on the sandbox platform -- the variable access is > > only available once the block disk image has been bound through the > > host interface. > > > > The FWU Multi Bank feature being enabled on the sandbox64 platform is > > enabling the RAW Firmware Management Protocol(FMP) instance, therefore > > the FIT FMP instance is being removed -- the FIT FMP is already being > > tested on the sandbox flattree variant. > > > > Signed-off-by: Sughosh Ganu > > --- > > arch/sandbox/Kconfig | 6 + > > arch/sandbox/dts/test.dts | 45 ++- > > board/sandbox/sandbox.c | 49 +++ > > configs/sandbox64_defconfig | 12 +- > > include/fwu.h | 2 + > > lib/fwu_updates/Kconfig | 2 +- > > lib/fwu_updates/fwu.c | 18 +- > > lib/fwu_updates/fwu_mtd.c | 10 +- > > .../test_capsule_firmware_fit.py | 1 - > > .../py/tests/test_fwu_updates/capsule_defs.py | 10 + > > test/py/tests/test_fwu_updates/conftest.py| 78 > > .../test_fwu_updates/test_fwu_updates.py | 367 ++ > > 12 files changed, 587 insertions(+), 13 deletions(-) > > create mode 100644 test/py/tests/test_fwu_updates/capsule_defs.py > > create mode 100644 test/py/tests/test_fwu_updates/conftest.py > > create mode 100644 test/py/tests/test_fwu_updates/test_fwu_updates.py > > > > diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig > > index 5f55c7f28e..2985572083 100644 > > --- a/arch/sandbox/Kconfig > > +++ b/arch/sandbox/Kconfig > > @@ -84,3 +84,9 @@ config SYS_FDT_LOAD_ADDR > > See `doc/arch/sandbox.rst` for more information. > > > > endmenu > > + > > +config FWU_NUM_BANKS > > + default 2 > > + > > +config FWU_NUM_IMAGES_PER_BANK > > + default 2 > > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts > > index 8f93775ff4..f11fa8733f 100644 > > --- a/arch/sandbox/dts/test.dts > > +++ b/arch/sandbox/dts/test.dts > > @@ -1145,11 +1145,48 @@ > > pinctrl-names = "default"; > > pinctrl-0 = <_spi0_pins>; > > > > - spi.bin@0 { > > + spi0: spi.bin@0 { > > reg = <0>; > > compatible = "spansion,m25p16", "jedec,spi-nor"; > > spi-max-frequency = <4000>; > > sandbox,filename = "spi.bin"; > > + > > + partitions { > > + compatible = "fixed-partitions"; > > + #address-cells = <1>; > > + #size-cells = <1>; > > + uuid = "af9e8c96-bec5-48be-9dab-3491c04b1366"; > > + > > + partition@0 { > > + label = "Metadata"; > > + reg = <0x0 0x2>; > > + }; > > + > > + /* FWU Multi bank update partitions */ > > +
Re: [PATCH v5 23/23] sandbox: fwu: Add support for testing FWU feature on sandbox
On Wed, 15 Jun 2022 at 11:07, Takahiro Akashi wrote: > > On Thu, Jun 09, 2022 at 06:00:10PM +0530, Sughosh Ganu wrote: > > Add a python test script for testing the FWU Multi Bank Update > > functionality on the sandbox platform. The script has test cases for > > updation of the u-boot binary and the u-boot environment image to the > > non active bank. > > > > The FWU metadata is being stored on the SPI NOR flash, along with the > > updatable images, and the FWU metadata driver for MTD devices is being > > used for accessing the metadata. Certain FWU boottime checks are > > bypassed due to the unavailability of the EFI variable access very > > early in the boot on the sandbox platform -- the variable access is > > only available once the block disk image has been bound through the > > host interface. > > > > The FWU Multi Bank feature being enabled on the sandbox64 platform is > > enabling the RAW Firmware Management Protocol(FMP) instance, therefore > > the FIT FMP instance is being removed -- the FIT FMP is already being > > tested on the sandbox flattree variant. > > IMO, > Thinking of the importance of this feature, FIT FMP should also be > tested *with FWU*. How will the FWU update feature work for FIT images? As I understand FIT, it is a way of packaging different firmware images into a single package. At the time of writing the images, the FIT image parser would check the image configuration, and write the images to their respective locations. As you are aware, for the FWU feature, the information about the images, and the update bank is obtained from the structure called metadata. How does the FIT update mechanism map with the FWU metadata which is used to identify which bank needs to be updated. The bank to which the image is to be written translates into the DFU alt_num value for that image, and this gets computed at runtime. In the case of the FIT image, as per my understanding, the alt_num value is irrelevant. So my question is, how do we map the information obtained from the FWU metadata to tell the FIT image writing function(fit_update) which locations do the images need to be written to. I think this needs some more thought. > > > Signed-off-by: Sughosh Ganu > > --- > > arch/sandbox/Kconfig | 6 + > > arch/sandbox/dts/test.dts | 45 ++- > > board/sandbox/sandbox.c | 49 +++ > > configs/sandbox64_defconfig | 12 +- > > include/fwu.h | 2 + > > lib/fwu_updates/Kconfig | 2 +- > > lib/fwu_updates/fwu.c | 18 +- > > lib/fwu_updates/fwu_mtd.c | 10 +- > > .../test_capsule_firmware_fit.py | 1 - > > .../py/tests/test_fwu_updates/capsule_defs.py | 10 + > > test/py/tests/test_fwu_updates/conftest.py| 78 > > .../test_fwu_updates/test_fwu_updates.py | 367 ++ > > 12 files changed, 587 insertions(+), 13 deletions(-) > > create mode 100644 test/py/tests/test_fwu_updates/capsule_defs.py > > create mode 100644 test/py/tests/test_fwu_updates/conftest.py > > create mode 100644 test/py/tests/test_fwu_updates/test_fwu_updates.py > > > > diff --git a/test/py/tests/test_fwu_updates/conftest.py > > b/test/py/tests/test_fwu_updates/conftest.py > > new file mode 100644 > > index 00..cdf824c3be > > --- /dev/null > > +++ b/test/py/tests/test_fwu_updates/conftest.py > > @@ -0,0 +1,78 @@ > > +# SPDX-License-Identifier: GPL-2.0+ > > +# Copyright (c) 2020, Linaro Limited > > +# Author: AKASHI Takahiro > > If this file is exactly same as test_efi_capsule/conftest.py, > why not move all the tests (test_fwu_updates.py) to test_efi_capsule? The files are not exactly the same. There is use of the mkfwumdata utility used for FWU tests, along with the capsule files that are being generated. I had tried putting the code under the test_efi_capsule directory, but the result was getting cluttered. Which is why I decided to put the changes separately under the test_fwu_updates directory. > > The basic scenario of updating firmware, u-boot.bin and u-boot.env, > is also the same, isn't it? The only difference is whether > FWU_MULTI_BANK_UPDATE > is enabled or not. There are two capsule files per image, one per bank. Also, the FWU metadata is being written to the SPI NOR device, which is being formatted as a MTD partitioned device. The underlying update mechanism is the same, yes. -sughosh > > -Takahiro Akashi > > > + > > +import os > > +import os.path > > +import re > > +from subprocess import call, chec
Re: [PATCH v5 11/23] mkeficapsule: Add support for generating empty capsules
On Wed, 15 Jun 2022 at 10:41, Takahiro Akashi wrote: > > On Thu, Jun 09, 2022 at 05:59:58PM +0530, Sughosh Ganu wrote: > > The Dependable Boot specification[1] describes the structure of the > > firmware accept and revert capsules. These are empty capsules which > > are used for signalling the acceptance or rejection of the updated > > firmware by the OS. Add support for generating these empty capsules. > > > > [1] - > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf > > > > Signed-off-by: Sughosh Ganu > > --- > > doc/mkeficapsule.1 | 29 ++--- > > tools/eficapsule.h | 8 +++ > > tools/mkeficapsule.c | 139 +-- > > 3 files changed, 151 insertions(+), 25 deletions(-) > > > > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 > > index 09bdc24295..77ca061efd 100644 > > --- a/doc/mkeficapsule.1 > > +++ b/doc/mkeficapsule.1 > > @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot > > > > .SH SYNOPSIS > > .B mkeficapsule > > -.RI [ options "] " image-blob " " capsule-file > > +.RI [ options ] " " [ image-blob ] " " capsule-file > > > > .SH "DESCRIPTION" > > .B mkeficapsule > > @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given > > private key. > > In this case, the update will be authenticated by verifying the signature > > before applying. > > > > +Additionally, an empty capsule file can be generated for acceptance or > > +rejection of firmware images by a governing component like an Operating > > +System. The empty capsules do not require an image-blob input file. > > + > > + > > .B mkeficapsule > > -takes any type of image files, including: > > +takes any type of image files when generating non empty capsules, > > including: > > .TP > > .I raw image > > format is a single binary blob of any type of firmware. > > @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file. > > This type of image file can be generated by > > .BR mkimage . > > > > -.PP > > -If you want to use other types than above two, you should explicitly > > -specify a guid for the FMP driver. > > - > > .SH "OPTIONS" > > + > > .TP > > .BI "-g\fR,\fB --guid " guid-string > > Specify guid for image blob type. The format is: > > ---- > > > > The first three elements are in little endian, while the rest > > -is in big endian. > > +is in big endian. The option must be specified for all non empty and > > +image acceptance capsules > > "image acceptance" -> "firmware acceptance" Okay > > I don't still understand why we need a guid for acceptance > while revert doesn't require it. > I believe that firmware update is "all or nothing", isn't it? I believe this gives more flexibility in that different components might be required to accept the various firmware images. So, one component might accept the optee_os, while another might be responsible for accepting u-boot. In any case, we do check that all the components have their accepted bit set, and only if so, does the bank boot in the regular state. In case of a firmware revert, it would not matter which firmware component is being reverted -- the platform would simply need to boot from the other bank. Do you see any issue with the current method that we have? > > If there is a good reason, please describe a possible/expected > scenario. Where do you want me to explain this, in the feature documentation? Or do you think this can be elaborated in greater detail in the spec. > > > .TP > > .BI "-i\fR,\fB --index " index > > @@ -57,6 +60,18 @@ Specify an image index > > .BI "-I\fR,\fB --instance " instance > > Specify a hardware instance > > > > +.PP > > +For generation of firmware accept empty capsule > > +.BR --guid > > +is mandatory > > +.TP > > +.BI "-A\fR,\fB --fw-accept " > > +Generate a firmware acceptance empty capsule > > + > > +.TP > > +.BI "-R\fR,\fB --fw-revert " > > +Generate a firmware revert empty capsule > > + > > .TP > > .BR -h ", " --help > > Print a help message > > diff --git a/tools/eficapsule.h b/tools/eficapsule.h > > index d63b831443..072a4b5598 100644 > > --- a/tools/eficapsule.h > > +++ b/tools/eficapsule.h > > @@ -41,6 +41,14 @@ typede
Re: [PATCH v5 10/23] FWU: cmd: Add a command to read FWU metadata
hi Ilias, On Fri, 10 Jun 2022 at 17:37, Ilias Apalodimas wrote: > > On Thu, Jun 09, 2022 at 05:59:57PM +0530, Sughosh Ganu wrote: > > Add a command to read the metadata as specified in the FWU > > specification and print the fields of the metadata. > > > > Signed-off-by: Sughosh Ganu > > --- > > cmd/Kconfig | 7 + > > cmd/Makefile| 1 + > > cmd/fwu_mdata.c | 74 + > > 3 files changed, 82 insertions(+) > > create mode 100644 cmd/fwu_mdata.c > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 09193b61b9..275becd837 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -144,6 +144,13 @@ config CMD_CPU > > internal name) and clock frequency. Other information may be > > available depending on the CPU driver. > > > > +config CMD_FWU_METADATA > > + bool "fwu metadata read" > > + depends on FWU_MULTI_BANK_UPDATE > > + default y if FWU_MULTI_BANK_UPDATE > > + help > > + Command to read the metadata and dump it's contents > > + > > config CMD_LICENSE > > bool "license" > > select BUILD_BIN2C > > diff --git a/cmd/Makefile b/cmd/Makefile > > index 5e43a1e022..259a93bc65 100644 > > --- a/cmd/Makefile > > +++ b/cmd/Makefile > > @@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_FPGA) += fpga.o > > obj-$(CONFIG_CMD_FPGAD) += fpgad.o > > obj-$(CONFIG_CMD_FS_GENERIC) += fs.o > > obj-$(CONFIG_CMD_FUSE) += fuse.o > > +obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o > > obj-$(CONFIG_CMD_GETTIME) += gettime.o > > obj-$(CONFIG_CMD_GPIO) += gpio.o > > obj-$(CONFIG_CMD_HVC) += smccc.o > > diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c > > new file mode 100644 > > index 00..bc20ca26a3 > > --- /dev/null > > +++ b/cmd/fwu_mdata.c > > @@ -0,0 +1,74 @@ > > +/* SPDX-License-Identifier: GPL-2.0+ */ > > +/* > > + * Copyright (c) 2022, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +static void print_mdata(struct fwu_mdata *mdata) > > +{ > > + int i, j; > > + struct fwu_image_entry *img_entry; > > + struct fwu_image_bank_info *img_info; > > + u32 nimages, nbanks; > > nit but we don't really need those two. Just use the define. Okay. Will change. > > > + > > + 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); > > + > > + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; > > + nbanks = CONFIG_FWU_NUM_BANKS; > > + printf("\tImage Info\n"); > > + for (i = 0; i < nimages; i++) { > > + img_entry = >img_entry[i]; > > + printf("\nImage Type Guid: %pUL\n", > > _entry->image_type_uuid); > > + printf("Location Guid: %pUL\n", _entry->location_uuid); > > + for (j = 0; j < nbanks; j++) { > > + img_info = _entry->img_bank_info[j]; > > + printf("Image Guid: %pUL\n", _info->image_uuid); > > + printf("Image Acceptance: %#x\n", img_info->accepted); > > Can we do 'yes/no' on the image acceptance please? Okay. Will change. -sughosh > > > + } > > + } > > +} > > + > > +int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, > > + int argc, char * const argv[]) > > +{ > > + struct udevice *dev; > > + int ret = CMD_RET_SUCCESS; > > + struct fwu_mdata *mdata = NULL; > > + > > + if (uclass_get_device(UCLASS_FWU_MDATA, 0, ) || !dev) { > > + log_err("Unable to get FWU metadata device\n"); > > + return CMD_RET_FAILURE; > > + } > > + > > + ret = fwu_get_mdata(); > > + if (ret < 0) { > > + log_err("Unable to get valid FWU metadata\n"); > > + ret = CMD_RET_FAILURE; > > + goto out; > > + } > > + > > + print_mdata(mdata); > > + > > +out: > > + free(mdata); > > + return ret; > > +} > > + > > +U_BOOT_CMD( > > + fwu_mdata_read, 1, 1, do_fwu_mdata_read, > > + "Read and print FWU metadata", > > + "" > > +); > > -- > > 2.25.1 > > > > Regards > /Ilias
Re: [PATCH v5 06/23] FWU: stm32mp1: Add helper functions for accessing FWU metadata
hi Ilias, On Fri, 10 Jun 2022 at 17:23, Ilias Apalodimas wrote: > > Hi Sughosh, > > On Thu, Jun 09, 2022 at 05:59:53PM +0530, Sughosh Ganu wrote: > > Add helper functions needed for accessing the FWU metadata which > > contains information on the updatable images. These functions have > > been added for the STM32MP157C-DK2 board which has the updatable > > images on the uSD card, formatted as GPT partitions. > > > > Signed-off-by: Sughosh Ganu > > --- > > board/st/stm32mp1/stm32mp1.c | 115 +++ > > include/fwu.h| 2 + > > 2 files changed, 117 insertions(+) > > > > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > > index 62d98ad776..e68bf09955 100644 > > --- a/board/st/stm32mp1/stm32mp1.c > > +++ b/board/st/stm32mp1/stm32mp1.c > > @@ -7,9 +7,11 @@ > > > > #include > > #include > > +#include > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -25,9 +27,11 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -967,3 +971,114 @@ static void board_copro_image_process(ulong fw_image, > > size_t fw_size) > > } > > > > U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); > > + > > +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) > > +#include > > +#include > > + > > +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t > > *image_guid) > > +{ > > + int i; > > + struct disk_partition info; > > + efi_guid_t unique_part_guid; > > + > > + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { > > + if (part_get_info(desc, i, )) > > + continue; > > + uuid_str_to_bin(info.uuid, unique_part_guid.b, > > + UUID_STR_FORMAT_GUID); > > + > > + if (!guidcmp(_part_guid, image_guid)) > > + return i; > > + } > > + > > + log_err("No partition found with image_guid %pUs\n", image_guid); > > + return -ENOENT; > > +} > > + > > +static int gpt_plat_get_alt_num(struct blk_desc *desc, efi_guid_t > > *image_guid, > > + int *alt_num) > > Does this really need to be defined per platform? > > Most of the stuff in here are generic apart from the info of were the > metadata is stored. So wouldn't it better to move this in the generic API > and add an argument for the dfu device type? > > The platform portion would then just call this function with an extra arg > e.g DFU_DEV_MMC Yes, it makes sense. I will make the change that you suggest. Thanks. -sughosh > > > +{ > > + int ret = -1; > > + int i, part, dev_num; > > + int nalt; > > + struct dfu_entity *dfu; > > + > > + dev_num = desc->devnum; > > + part = get_gpt_dfu_identifier(desc, image_guid); > > + if (part < 0) > > + return -ENOENT; > > + > > + dfu_init_env_entities(NULL, NULL); > > [...] > > > Regards > /Ilias
Re: [PATCH v5 11/23] mkeficapsule: Add support for generating empty capsules
On Thu, 9 Jun 2022 at 21:58, Heinrich Schuchardt wrote: > > On 6/9/22 14:29, Sughosh Ganu wrote: > > The Dependable Boot specification[1] describes the structure of the > > firmware accept and revert capsules. These are empty capsules which > > are used for signalling the acceptance or rejection of the updated > > firmware by the OS. Add support for generating these empty capsules. > > > > [1] - > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf > > > > Signed-off-by: Sughosh Ganu > > --- > > doc/mkeficapsule.1 | 29 ++--- > > tools/eficapsule.h | 8 +++ > > tools/mkeficapsule.c | 139 +-- > > 3 files changed, 151 insertions(+), 25 deletions(-) > > diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c > > index 5f74d23b9e..e8eb6b070d 100644 > > --- a/tools/mkeficapsule.c > > +++ b/tools/mkeficapsule.c > > @@ -29,7 +29,16 @@ static const char *tool_name = "mkeficapsule"; > > efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; > > efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; > > > > -static const char *opts_short = "g:i:I:v:p:c:m:dh"; > > +static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; > > + > > +static bool empty_capsule; > > +static unsigned char capsule; > > + > > +enum { > > + CAPSULE_NORMAL_BLOB = 0, > > + CAPSULE_ACCEPT, > > + CAPSULE_REVERT, > > +} capsule_type; > > > > static struct option options[] = { > > {"guid", required_argument, NULL, 'g'}, > > @@ -39,24 +48,47 @@ static struct option options[] = { > > {"certificate", required_argument, NULL, 'c'}, > > {"monotonic-count", required_argument, NULL, 'm'}, > > {"dump-sig", no_argument, NULL, 'd'}, > > + {"fw-accept", no_argument, NULL, 'A'}, > > + {"fw-revert", no_argument, NULL, 'R'}, > > {"help", no_argument, NULL, 'h'}, > > {NULL, 0, NULL, 0}, > > }; > > > > static void print_usage(void) > > { > > - fprintf(stderr, "Usage: %s [options] \n" > > - "Options:\n" > > - > > - "\t-g, --guid guid for image blob type\n" > > - "\t-i, --index update image index\n" > > - "\t-I, --instanceupdate hardware instance\n" > > - "\t-p, --private-key private key file\n" > > - "\t-c, --certificate signer's certificate > > file\n" > > - "\t-m, --monotonic-count monotonic count\n" > > - "\t-d, --dump_sig dump signature (*.p7)\n" > > - "\t-h, --help print a help message\n", > > - tool_name); > > + if (empty_capsule) { > > + if (capsule == CAPSULE_ACCEPT) { > > + fprintf(stderr, "Usage: %s [options] \n", > > My expectation is that this function always provides the same output. > > If different scenarios allow only specific combinations of arguments you > may describe it here. Okay > > > > + tool_name); > > + fprintf(stderr, "Options:\n" > > + "\t-A, --fw-accept firmware > > accept capsule\n" > > + "\t-g, --guid guid for image > > blob type\n" > > + "\t-h, --help print a help > > message\n" > > + ); > > + } else { > > + fprintf(stderr, "Usage: %s [options] \n", > > + tool_name); > > + fprintf(stderr, "Options:\n" > > + "\t-R, --fw-revert firmware > > revert capsule\n" > > + "\t-h, --help print a help > > message\n" > > + ); > > + } > > + } else { > > + fprintf(stderr, "Usage: %s [options] > file>\n" > > + "Options:\n" > > + > > + "\t-g, --guid guid for image blob > > type\n" > > +
[PATCH v5 23/23] sandbox: fwu: Add support for testing FWU feature on sandbox
Add a python test script for testing the FWU Multi Bank Update functionality on the sandbox platform. The script has test cases for updation of the u-boot binary and the u-boot environment image to the non active bank. The FWU metadata is being stored on the SPI NOR flash, along with the updatable images, and the FWU metadata driver for MTD devices is being used for accessing the metadata. Certain FWU boottime checks are bypassed due to the unavailability of the EFI variable access very early in the boot on the sandbox platform -- the variable access is only available once the block disk image has been bound through the host interface. The FWU Multi Bank feature being enabled on the sandbox64 platform is enabling the RAW Firmware Management Protocol(FMP) instance, therefore the FIT FMP instance is being removed -- the FIT FMP is already being tested on the sandbox flattree variant. Signed-off-by: Sughosh Ganu --- arch/sandbox/Kconfig | 6 + arch/sandbox/dts/test.dts | 45 ++- board/sandbox/sandbox.c | 49 +++ configs/sandbox64_defconfig | 12 +- include/fwu.h | 2 + lib/fwu_updates/Kconfig | 2 +- lib/fwu_updates/fwu.c | 18 +- lib/fwu_updates/fwu_mtd.c | 10 +- .../test_capsule_firmware_fit.py | 1 - .../py/tests/test_fwu_updates/capsule_defs.py | 10 + test/py/tests/test_fwu_updates/conftest.py| 78 .../test_fwu_updates/test_fwu_updates.py | 367 ++ 12 files changed, 587 insertions(+), 13 deletions(-) create mode 100644 test/py/tests/test_fwu_updates/capsule_defs.py create mode 100644 test/py/tests/test_fwu_updates/conftest.py create mode 100644 test/py/tests/test_fwu_updates/test_fwu_updates.py diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 5f55c7f28e..2985572083 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -84,3 +84,9 @@ config SYS_FDT_LOAD_ADDR See `doc/arch/sandbox.rst` for more information. endmenu + +config FWU_NUM_BANKS + default 2 + +config FWU_NUM_IMAGES_PER_BANK + default 2 diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 8f93775ff4..f11fa8733f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1145,11 +1145,48 @@ pinctrl-names = "default"; pinctrl-0 = <_spi0_pins>; - spi.bin@0 { + spi0: spi.bin@0 { reg = <0>; compatible = "spansion,m25p16", "jedec,spi-nor"; spi-max-frequency = <4000>; sandbox,filename = "spi.bin"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + uuid = "af9e8c96-bec5-48be-9dab-3491c04b1366"; + + partition@0 { + label = "Metadata"; + reg = <0x0 0x2>; + }; + + /* FWU Multi bank update partitions */ + partition@10 { + label = "U-Boot-Bank0"; + reg = <0x10 0x1>; + uuid = "a8f61787-5d68-4c9d-9e4a-37bb0df99da7"; + }; + + partition@12 { + label = "U-Boot-ENV-Bank0"; + reg = <0x12 0x1>; + uuid = "ea9d59af-e0e8-4ef5-9b16-4c80ff67524c"; + }; + + partition@14 { + label = "U-Boot-Bank1"; + reg = <0x14 0x1>; + uuid = "52377abf-c4e4-4d0b-aafd-ba081a500847"; + }; + + partition@16 { + label = "U-Boot-ENV-Bank1"; + reg = <0x16 0x1>; + uuid = "4e01d1fa-eebb-437e-9cfe-e7dfbcd04bb3"; + }; + }; }; spi.bin@1 { reg = <1>; @@ -1633,6 +1670,12 @@ compatible = "sandbox,regmap_te
[PATCH v5 22/23] [TEMP]configs: synquacer: Add FWU support for DeveloperBox
From: Masami Hiramatsu Enable FWU Multi-Bank support for DeveloperBox SynQuacer platform. This also enables fwu_metadata_read command and "reboot soon after update" option. Signed-off-by: Masami Hiramatsu --- Changes in v3: - Use CONFIG_FWU_MDATA_MTD. - Remove unused CONFIG_FWU_INIT_BROKEN_METADATA and add CONFIG_TOOLS_MKFWUMDATA. Signed-off-by: Sughosh Ganu --- configs/synquacer_developerbox_defconfig | 5 + 1 file changed, 5 insertions(+) diff --git a/configs/synquacer_developerbox_defconfig b/configs/synquacer_developerbox_defconfig index 29b1e11401..f2c8c3cc4e 100644 --- a/configs/synquacer_developerbox_defconfig +++ b/configs/synquacer_developerbox_defconfig @@ -94,3 +94,8 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_IGNORE_OSINDICATIONS=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +CONFIG_EFI_SECURE_BOOT=y +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_FWU_MDATA_MTD=y +CONFIG_CMD_FWU_METADATA=y +CONFIG_TOOLS_MKFWUMDATA=y -- 2.25.1
[PATCH v5 21/23] doc: synquacer: Add how to enable FWU Multi Bank Update
From: Masami Hiramatsu Add a section for the instruction of building the FWU Multi Bank Update supported U-Boot and installation. Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- doc/board/socionext/developerbox.rst | 110 +++ 1 file changed, 110 insertions(+) diff --git a/doc/board/socionext/developerbox.rst b/doc/board/socionext/developerbox.rst index 2d943c23be..d9f38a3897 100644 --- a/doc/board/socionext/developerbox.rst +++ b/doc/board/socionext/developerbox.rst @@ -85,3 +85,113 @@ Once the flasher tool is running we are ready flash the UEFI image:: After transferring the SPI_NOR_UBOOT.fd, turn off the DSW2-7 and reset the board. + +Enable FWU Multi Bank Update + + +DeveloperBox supports the FWU Multi Bank Update. You *MUST* update both *SCP firmware* and *TF-A* for this feature. This will change the layout and the boot process but you can switch back to the normal one by changing the DSW 1-4 off. + +Configure U-Boot + + +To enable the FWU Multi Bank Update on the DeveloperBox, you need to add following configurations to configs/synquacer_developerbox_defconfig :: + + CONFIG_FWU_MULTI_BANK_UPDATE=y + CONFIG_FWU_MDATA_MTD=y + CONFIG_CMD_FWU_METADATA=y + CONFIG_TOOLS_MKFWUMDATA=y + +And build it:: + + cd u-boot/ + export ARCH=arm64 + export CROSS_COMPILE=aarch64-linux-gnu- + make synqucer_developerbox_defconfig + make -j `noproc` + cd ../ + +By default, the CONFIG_FWU_NUM_BANKS and COFNIG_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. + +Rebuild SCP firmware + + +Rebuild SCP firmware which supports FWU Multi Bank Update as below:: + + cd SCP-firmware/ + OUT=./build/product/synquacer + ROMFW_FILE=$OUT/scp_romfw/$SCP_BUILD_MODE/bin/scp_romfw.bin + RAMFW_FILE=$OUT/scp_ramfw/$SCP_BUILD_MODE/bin/scp_ramfw.bin + ROMRAMFW_FILE=scp_romramfw_release.bin + + make CC=$ARM_EMB_GCC PRODUCT=synquacer MODE=release + tr "\000" "\377" < /dev/zero | dd of=${ROMRAMFW_FILE} bs=1 count=196608 + dd if=${ROMFW_FILE} of=${ROMRAMFW_FILE} bs=1 conv=notrunc seek=0 + dd if=${RAMFW_FILE} of=${ROMRAMFW_FILE} bs=1 seek=65536 + cd ../ + +And you can get the `scp_romramfw_release.bin` file + +Rebuild TF-A and FIP + + +Rebuild TF-A which supports FWU Multi Bank Update as below:: + + cd arm-trusted-firmware/ + make CROSS_COMPILE=aarch64-linux-gnu- -j`nproc` PLAT=synquacer \ + SPD=opteed SQ_RESET_TO_BL2=1 GENERATE_COT=1 MBEDTLS_DIR=../mbedtls \ + BL33=../u-boot/u-boot.bin all fip fiptool + +And make a FIP image.:: + + cp build/synquacer/release/fip.bin SPI_NOR_NEWFIP.fd + tools/fiptool/fiptool update --tb-fw build/synquacer/release/bl2.bin SPI_NOR_NEWFIP.fd + + +UUIDs for the FWU Multi Bank Update +--- + +FWU multi-bank update requires some UUIDs. The DeveloperBox platform uses following UUIDs. + + - Location UUID for the FIP image: 17e86d77-41f9-4fd7-87ec-a55df9842de5 + - Image type UUID for the FIP image: 10c36d7d-ca52-b843-b7b9-f9d6c501d108 + - Image UUID for Bank0 : 5a66a702-99fd-4fef-a392-c26e261a2828 + - Image UUID for Bank1 : a8f868a1-6e5c-4757-878d-ce63375ef2c0 + +These UUIDs are used for making a FWU metadata image. + +Generate FWU metadata image +--- + +Before installation, you need to generate a FWU metadata image file by mkfwumdata command as below:: + + tools/mkfwumdata -i 1 -b 2 "17e86d77-41f9-4fd7-87ec-a55df9842de5,10c36d7d-ca52-b843-b7b9-f9d6c501d108,5a66a702-99fd-4fef-a392-c26e261a2828,a8f868a1-6e5c-4757-878d-ce63375ef2c0" fwu-mdata.img + +Then, you can get the `fwu-mdata.img` image file. + +Install via flash writer + + +As explained in above section, the new FIP image and the FWU metadata image can be installed via NOR flash writer. Note that the installation offsets for the FWU multi bank update supported firmware. + +Once the flasher tool is running we are ready flash the images. At first, please install FWU metadata at 0x50 (primary) and 0x53 (secondary).:: + + flash rawwrite 50 60 + >> Send fwu-mdata.img via XMODEM (Control-A S in minicom) << + + flash rawwrite 53 60 + >> Send fwu-mdata.img via XMODEM (Control-A S in minicom) << + +And write the FIP image to the 0x60 offset.:: + + flash rawwrite 60 18 + >> Send SPI_NOR_NEWFIP.fd via XMODEM (Control-A S in minicom) << + +And write the new SCP firmware.:: + + flash write cm3 + >> Send scp_romramfw_release.bin via XMODEM (Control-A S in minicom) << + +At last, turn on the DSW 3-4 on the board, and reboot. +Note that if DSW 3-4 is turned off, the DeveloperBox will boot from +the original EDK2 firmware (or non-FWU U-Boot if you already installed.) -- 2.25.1
[PATCH v5 20/23] FWU: synquacer: Generate dfu_alt_info from devicetree partition
From: Masami Hiramatsu Generate dfu_alt_info from the partition uuid information in the devicetree, and record the mapping of partition uuid and the index of dfu_alt_num. This could be a reference implementation of the automatic DFU generation for FWU multi-bank update for non GPT firmware platforms. Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- .../synquacer-sc2a11-developerbox-u-boot.dtsi | 3 + board/socionext/developerbox/Kconfig | 1 + board/socionext/developerbox/fwu_plat.c | 79 include/configs/synquacer.h | 6 +- include/fwu.h | 6 + lib/fwu_updates/Makefile | 1 + lib/fwu_updates/fwu_mtd.c | 173 ++ 7 files changed, 221 insertions(+), 48 deletions(-) create mode 100644 lib/fwu_updates/fwu_mtd.c diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi index ab4e3d1c2b..c7ec8a0321 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi @@ -36,6 +36,7 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; + uuid = "17e86d77-41f9-4fd7-87ec-a55df9842de5"; partition@0 { label = "BootStrap-BL1"; @@ -88,10 +89,12 @@ partition@60 { label = "FIP-Bank0"; reg = <0x60 0x40>; + uuid = "5a66a702-99fd-4fef-a392-c26e261a2828"; }; partition@a0 { label = "FIP-Bank1"; reg = <0xa0 0x40>; + uuid = "a8f868a1-6e5c-4757-878d-ce63375ef2c0"; }; }; }; diff --git a/board/socionext/developerbox/Kconfig b/board/socionext/developerbox/Kconfig index 7df6750baf..ad2a284f13 100644 --- a/board/socionext/developerbox/Kconfig +++ b/board/socionext/developerbox/Kconfig @@ -38,6 +38,7 @@ config FWU_MULTI_BANK_UPDATE select DM_SPI_FLASH select DM_FWU_MDATA select BOARD_LATE_INIT + select SET_DFU_ALT_INFO config FWU_NUM_BANKS default 2 diff --git a/board/socionext/developerbox/fwu_plat.c b/board/socionext/developerbox/fwu_plat.c index fd6d0e3659..ff06eade7d 100644 --- a/board/socionext/developerbox/fwu_plat.c +++ b/board/socionext/developerbox/fwu_plat.c @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -94,6 +96,36 @@ static int sf_save_data(u32 offs, u32 size, void *data) return ret; } +#define DFU_ALT_BUF_LEN 256 +#define DFU_ALT_NUM_MAX (CONFIG_FWU_NUM_IMAGES_PER_BANK * CONFIG_FWU_NUM_BANKS) + +/* Generate dfu_alt_info from partitions */ +void set_dfu_alt_info(char *interface, char *devstr) +{ + int ret; + struct mtd_info *mtd; + static char *buf = NULL; + + if (!buf) { + buf = malloc_cache_aligned(DFU_ALT_BUF_LEN); + memset(buf, 0, DFU_ALT_BUF_LEN); + + mtd_probe_devices(); + + mtd = get_mtd_device_nm("nor1"); + if (IS_ERR_OR_NULL(mtd)) + return; + + ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd); + if (ret < 0) { + log_err("Error: Failed to generate dfu_alt_info. (%d)\n", ret); + return; + } + log_debug("Make dfu_alt_info: '%s'\n", buf); + } + env_set("dfu_alt_info", buf); +} + #define PLAT_METADATA_OFFSET 0x51 #define PLAT_METADATA_SIZE (sizeof(struct devbox_metadata)) @@ -105,49 +137,7 @@ struct __packed devbox_metadata { int fwu_plat_get_alt_num(struct udevice __always_unused *dev, efi_guid_t *image_id, int *alt_num) { - struct fwu_image_bank_info *bank; - struct fwu_mdata *mdata; - int i, ret; - - ret = fwu_get_mdata(); - if (ret < 0) - return ret; - - /* -* DeveloperBox FWU expects Bank:Image = 1:1, and the dfu_alt_info -* only has the entries for banks. Thus the alt_no should be equal -* to the bank index number. -*/ - ret = -ENOENT; - for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) { - bank = >img_entry[0].
[PATCH v5 19/23] FWU: synquacer: Add FWU Multi bank update support for DeveloperBox
From: Masami Hiramatsu The DeveloperBox platform can support the FWU Multi bank update. SCP firmware will switch the boot mode by DSW3-4 and load the Multi bank update supported TF-A BL2 from 0x60 offset on the SPI flash. Thus it can co-exist with the legacy boot mode (legacy U-Boot or EDK2). Signed-off-by: Masami Hiramatsu --- Changes in v3: - Change devicetree to add partitions. - Update fwu_plat_get_alt_num() to find the alt number from the bank index. - Use only 2 partitions for AB update. - Clear platform-mdata's boot_count to finish platform trial boot. Signed-off-by: Sughosh Ganu --- .../synquacer-sc2a11-developerbox-u-boot.dtsi | 15 +- board/socionext/developerbox/Kconfig | 13 ++ board/socionext/developerbox/Makefile | 1 + board/socionext/developerbox/fwu_plat.c | 207 ++ include/configs/synquacer.h | 8 + 5 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 board/socionext/developerbox/fwu_plat.c diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi index 095727e03c..ab4e3d1c2b 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi @@ -23,7 +23,7 @@ active_clk_edges; chipselect_num = <1>; - spi-flash@0 { + spi_flash: spi-flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; @@ -84,11 +84,15 @@ label = "UBoot-Env"; reg = <0x58 0x8>; }; - + /* FWU Multi bank update partitions */ partition@60 { - label = "FIP"; + label = "FIP-Bank0"; reg = <0x60 0x40>; }; + partition@a0 { + label = "FIP-Bank1"; + reg = <0xa0 0x40>; + }; }; }; }; @@ -114,6 +118,11 @@ optee { status = "okay"; }; + fwu-mdata { + compatible = "u-boot,fwu-mdata-mtd"; + fwu-mdata-store = <_flash>; + mdata-offsets = <0x50 0x53>; + }; }; }; diff --git a/board/socionext/developerbox/Kconfig b/board/socionext/developerbox/Kconfig index c181d26a44..7df6750baf 100644 --- a/board/socionext/developerbox/Kconfig +++ b/board/socionext/developerbox/Kconfig @@ -32,4 +32,17 @@ config SYS_CONFIG_NAME default "synquacer" endif + +config FWU_MULTI_BANK_UPDATE + select FWU_MDATA_MTD + select DM_SPI_FLASH + select DM_FWU_MDATA + select BOARD_LATE_INIT + +config FWU_NUM_BANKS + default 2 + +config FWU_NUM_IMAGES_PER_BANK + default 1 + endif diff --git a/board/socionext/developerbox/Makefile b/board/socionext/developerbox/Makefile index 4a46de995a..9b80ee38e7 100644 --- a/board/socionext/developerbox/Makefile +++ b/board/socionext/developerbox/Makefile @@ -7,3 +7,4 @@ # obj-y := developerbox.o +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_plat.o diff --git a/board/socionext/developerbox/fwu_plat.c b/board/socionext/developerbox/fwu_plat.c new file mode 100644 index 00..fd6d0e3659 --- /dev/null +++ b/board/socionext/developerbox/fwu_plat.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* SPI Flash accessors */ +static struct spi_flash *plat_spi_flash; + +static int __plat_sf_get_flash(void) +{ + /* TODO: define platform spi-flash somewhere. */ + plat_spi_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, +CONFIG_SF_DEFAULT_CS, +CONFIG_SF_DEFAULT_SPEED, +CONFIG_SF_DEFAULT_MODE); + + return 0; +} + +static int plat_sf_get_flash(struct spi_flash **flash) +{ + int ret = 0; + + if (!plat_spi_flash) + ret = __plat_sf_get_flash(); + + *flash = plat_spi_flash; + + return ret; +} + +static int sf_load_data(u32 offs, u32 size, void **data) +{ + struct spi_flash *flash; + int ret; + + ret = plat_sf_get_f
[PATCH v5 18/23] developerbox: synquacer: Use FIP as the updatable image
From: Jassi Brar The Synquacer board is migrating to using the FIP as the only updatable image on the platform with the u-boot and op-tee images packaged as part of the FIP image. Make changes to the structures used for capsule updates to reflect this change. Signed-off-by: Jassi Brar Signed-off-by: Sughosh Ganu --- board/socionext/developerbox/developerbox.c | 17 +++-- include/configs/synquacer.h | 13 ++--- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/board/socionext/developerbox/developerbox.c b/board/socionext/developerbox/developerbox.c index f5a5fe0121..b946428ddb 100644 --- a/board/socionext/developerbox/developerbox.c +++ b/board/socionext/developerbox/developerbox.c @@ -20,27 +20,16 @@ #if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) struct efi_fw_image fw_images[] = { - { - .image_type_id = DEVELOPERBOX_UBOOT_IMAGE_GUID, - .fw_name = u"DEVELOPERBOX-UBOOT", - .image_index = 1, - }, { .image_type_id = DEVELOPERBOX_FIP_IMAGE_GUID, .fw_name = u"DEVELOPERBOX-FIP", - .image_index = 2, - }, - { - .image_type_id = DEVELOPERBOX_OPTEE_IMAGE_GUID, - .fw_name = u"DEVELOPERBOX-OPTEE", - .image_index = 3, + .image_index = 1, }, }; struct efi_capsule_update_info update_info = { - .dfu_string = "mtd nor1=u-boot.bin raw 20 10;" - "fip.bin raw 18 78000;" - "optee.bin raw 50 10", + .dfu_string = "mtd nor1=bank0 raw 60 40;" + "bank1 raw a0 40;", .images = fw_images, }; diff --git a/include/configs/synquacer.h b/include/configs/synquacer.h index 572f0a42ac..eafcc69e12 100644 --- a/include/configs/synquacer.h +++ b/include/configs/synquacer.h @@ -50,18 +50,9 @@ "mtd nor1=fip.bin raw 60 40\0" /* GUIDs for capsule updatable firmware images */ -#define DEVELOPERBOX_UBOOT_IMAGE_GUID \ - EFI_GUID(0x53a92e83, 0x4ef4, 0x473a, 0x8b, 0x0d, \ -0xb5, 0xd8, 0xc7, 0xb2, 0xd6, 0x00) - #define DEVELOPERBOX_FIP_IMAGE_GUID \ - EFI_GUID(0x880866e9, 0x84ba, 0x4793, 0xa9, 0x08, \ -0x33, 0xe0, 0xb9, 0x16, 0xf3, 0x98) - -#define DEVELOPERBOX_OPTEE_IMAGE_GUID \ - EFI_GUID(0xc1b629f1, 0xce0e, 0x4894, 0x82, 0xbf, \ -0xf0, 0xa3, 0x83, 0x87, 0xe6, 0x30) - + EFI_GUID(0x7d6dc310, 0x52ca, 0x43b8, 0xb7, 0xb9, \ +0xf9, 0xd6, 0xc5, 0x01, 0xd1, 0x08) /* Distro boot settings */ #ifndef CONFIG_SPL_BUILD #ifdef CONFIG_CMD_USB -- 2.25.1
[PATCH v5 16/23] FWU: doc: Update documentation for the FWU non-GPT MTD
From: Masami Hiramatsu Update documentation for the FWU non-GPT MTD device and mkfwumdata command. Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- doc/develop/uefi/fwu_updates.rst | 82 +++- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst index 1c34beb7d5..1ea54328d1 100644 --- a/doc/develop/uefi/fwu_updates.rst +++ b/doc/develop/uefi/fwu_updates.rst @@ -15,10 +15,11 @@ boot. The UEFI capsule-on-disk update feature is used for performing the actual updates of the updatable firmware images. The bookkeeping of the updatable images is done through a structure -called metadata. Currently, the FWU metadata supports identification +called FWU metadata. Currently, the FWU metadata supports identification of images based on image GUIDs stored on a GPT partitioned storage -media. There are plans to extend the metadata structure for non GPT -partitioned devices as well. +media. If the firmware images are stored on the flash device which +has no GPT, the platform driver can provide the image identification +feature. Accessing the FWU metadata is done through generic API's which are defined in a driver which complies with the u-boot's driver model. A @@ -43,21 +44,31 @@ The feature can be enabled by specifying the following configs:: CONFIG_FWU_MULTI_BANK_UPDATE=y CONFIG_CMD_FWU_METADATA=y CONFIG_DM_FWU_MDATA=y -CONFIG_FWU_MDATA_GPT_BLK=y CONFIG_FWU_NUM_BANKS= CONFIG_FWU_NUM_IMAGES_PER_BANK= +CONFIG_TOOLS_MKFWUMDATA=y + +CONFIG_FWU_MDATA_GPT_BLK=y +CONFIG_FWU_MDATA_SF=y -in the .config file +in the .config file. The first group of configs enable the UEFI capsule-on-disk update functionality. The second group of configs 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. +Update functionality. And the third group of configs are FWU Metadata +drivers. You can enable either one of ``CONFIG_FWU_MDATA_GPT_BLK`` and +``CONFIG_FWU_MDATA_SF`` or both of them, according to the platform +support. Anyway, a correct driver will be probed by devicetree node. + +Please refer to the section :ref:`uefi_capsule_update_ref` for +more details on generation of the UEFI capsule. Setting up the device for GPT partitioned storage - +If your platform stores the firmware on GPT partitioned storage +device (e.g. eMMC/SD), please follow this section. + Before enabling the functionality in U-Boot, certain changes are required to be done on the storage device. Assuming a GPT partitioned storage device, the storage media needs to be partitioned with the @@ -74,7 +85,14 @@ media can have additional partitions of non-updatable images, like the EFI System Partition(ESP), a partition for the root file system etc. When generating the partitions, a few aspects need to be taken care -of. Each GPT partition entry in the GPT header has two GUIDs:: +of. The GPT itself has one GUID:: + +*DiskGUID* + +This DiskGUID value should correspond to the *location_uuid* field +of the FWU metadata. + +And each GPT partition entry in the GPT header has two GUIDs:: *PartitionTypeGUID* *UniquePartitionGUID* @@ -93,9 +111,49 @@ Similarly, the FWU specifications defines the GUID value to be used for the metadata partitions. This would be the PartitionTypeGUID for the metadata partitions. -When generating the metadata, the *image_type_uuid* and the -*image_uuid* values should match the *PartitionTypeGUID* and the -*UniquePartitionGUID* values respectively. +Setting up the device for non-GPT partitioned MTD device + + +If your platform stores the firmware on non-GPT partitioned MTD +device, please follow this section. + +Before enabling the functionality in U-Boot, please confirm that +your platform correctly define (or generate) `dfu_alt_info`, which +has to have all *banks* as the dfu entries. Also, the devicetree's +`fwu_mdata` node must be "u-boot,fwu-mdata-mtd" compatible node +and has FWU metadata offsets on `mdata-offsets` property. +Please refer to U-Boot +`doc `__ for +the device tree bindings. + +Similar to the GPT, you can also define the DiskGUID, and the +UniquePartitionGUID in the devicetree as additional properties of +the "fixed-partitions" compatible partition nodes, and the platform +code can generate the `dfu_alt_info` from that. In this case, +*image_type_uuid* field of the FWU mdata is used instead of the +PartitionTypeGUID. + +Generate the FWU metadata image +--- + +To generate the FWU metadata raw image, you can use `tools/mkfwumdata` +command. + + tools/mkfwumdata -i <#images> -b <#banks> \ +\ + [location_uuid1,image_type_uuid1,image_uuid1_0,image_uuid1_
[PATCH v5 17/23] synquacer: Update for TBBR (BL2) based new FIP layout
From: Masami Hiramatsu This changes SPI NOR flash partition layout for TBBR and also make the U-Boot as position independent executable again because BL33 is loaded on the memory. With enabling TBBR, TF-A BL2 loads all BL3x images from FIP image, and the U-Boot image is added to the FIP image as BL33, and loaded to memory when boot instead of XIP on SPI NOR flash. To avoid mixing up with the legacy images, this new FIP image is stored on unused area (0x60-) and the U-Boot env vars are also stored at 0x58 so that it will not break existing EDK2 area. NOTE: This introduces an incombatible change to the synquacer_developerbox_defconfig. If you want to build U-Boot for booting from legacy FIP image, you need to specify previous configuration. Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- .../synquacer-sc2a11-developerbox-u-boot.dtsi | 26 +-- configs/synquacer_developerbox_defconfig | 5 ++-- include/configs/synquacer.h | 4 +-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi index 7a56116d6f..095727e03c 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi @@ -56,7 +56,7 @@ }; partition@18 { - label = "FIP-TFA"; + label = "LegacyFIP"; reg = <0x18 0x78000>; }; @@ -66,18 +66,28 @@ }; partition@20 { - label = "U-Boot"; - reg = <0x20 0x10>; + label = "EDK2"; + reg = <0x20 0x20>; }; - partition@30 { - label = "UBoot-Env"; - reg = <0x30 0x10>; + partition@40 { + label = "EDK2-Env"; + reg = <0x40 0x10>; }; partition@50 { - label = "Ex-OPTEE"; - reg = <0x50 0x20>; + label = "Metadata"; + reg = <0x50 0x8>; + }; + + partition@58 { + label = "UBoot-Env"; + reg = <0x58 0x8>; + }; + + partition@60 { + label = "FIP"; + reg = <0x60 0x40>; }; }; }; diff --git a/configs/synquacer_developerbox_defconfig b/configs/synquacer_developerbox_defconfig index add6041e27..29b1e11401 100644 --- a/configs/synquacer_developerbox_defconfig +++ b/configs/synquacer_developerbox_defconfig @@ -1,10 +1,11 @@ CONFIG_ARM=y CONFIG_ARCH_SYNQUACER=y -CONFIG_SYS_TEXT_BASE=0x0820 +CONFIG_POSITION_INDEPENDENT=y +CONFIG_SYS_TEXT_BASE=0 CONFIG_SYS_MALLOC_LEN=0x100 CONFIG_SYS_MALLOC_F_LEN=0x400 CONFIG_ENV_SIZE=0x3 -CONFIG_ENV_OFFSET=0x30 +CONFIG_ENV_OFFSET=0x58 CONFIG_ENV_SECT_SIZE=0x1 CONFIG_DM_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="synquacer-sc2a11-developerbox" diff --git a/include/configs/synquacer.h b/include/configs/synquacer.h index 5686a5b910..572f0a42ac 100644 --- a/include/configs/synquacer.h +++ b/include/configs/synquacer.h @@ -47,9 +47,7 @@ /* Since U-Boot 64bit PCIe support is limited, disable 64bit MMIO support */ #define DEFAULT_DFU_ALT_INFO "dfu_alt_info=" \ - "mtd nor1=u-boot.bin raw 20 10;"\ - "fip.bin raw 18 78000;" \ - "optee.bin raw 50 10\0" + "mtd nor1=fip.bin raw 60 40\0" /* GUIDs for capsule updatable firmware images */ #define DEVELOPERBOX_UBOOT_IMAGE_GUID \ -- 2.25.1
[PATCH v5 15/23] tools: Add mkfwumdata tool for FWU metadata image
From: Masami Hiramatsu Add 'mkfwumdata' tool which can generate an image of the FWU metadata which is required for initializing the platform. Usage: mkfwumdata -i NR_IMAGES -b NR_BANKS [--guid] \ LOCATION_UUID0,IMAGE_TYPE_UUID0,BANK0_IMAGE_UUID[,BANK1_IMAGE_UUID[,...]] \ LOCATION_UUID1,... \ IMAGE_FILE '-i' takes the number of images and '-b' takes the number of banks. This takes lists of uuids for the images on arguments, and the last argument must be the output image file name. '--guid' (or '-g' in short) allows user to specify the location UUID and image IDs in GUID instead of UUID. This option is useful if the platform uses GPT partiotion. In this case, the UUID list (for an image) becomes; DiskGUID,ParitionTypeGUID,UniquePartitionGUID,... Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- tools/Kconfig | 9 ++ tools/Makefile | 4 + tools/mkfwumdata.c | 298 + 3 files changed, 311 insertions(+) create mode 100644 tools/mkfwumdata.c diff --git a/tools/Kconfig b/tools/Kconfig index 117c921da3..3484be99d0 100644 --- a/tools/Kconfig +++ b/tools/Kconfig @@ -98,4 +98,13 @@ config TOOLS_MKEFICAPSULE optionally sign that file. If you want to enable UEFI capsule update feature on your target, you certainly need this. +config TOOLS_MKFWUMDATA + bool "Build mkfwumdata command" + default y if FWU_MULTI_BANK_UPDATE + help + This command allows users to create a raw image of the FWU + metadata for initial installation of the FWU multi bank + update on the board. The installation method depends on + the platform. + endmenu diff --git a/tools/Makefile b/tools/Makefile index 9f2339666a..cd39e5ff6f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -245,6 +245,10 @@ HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include HOSTLDLIBS_mkeficapsule += -lgnutls -luuid hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule +mkfwumdata-objs := mkfwumdata.o lib/crc32.o +HOSTLDLIBS_mkfwumdata += -luuid +hostprogs-$(CONFIG_TOOLS_MKFWUMDATA) += mkfwumdata + # We build some files with extra pedantic flags to try to minimize things # that won't build on some weird host compiler -- though there are lots of # exceptions for files that aren't complaint. diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c new file mode 100644 index 00..4eb304cae3 --- /dev/null +++ b/tools/mkfwumdata.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#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; + +#include + +/* TODO: Endianess conversion may be required for some arch. */ + +static const char *opts_short = "b:i:a:gh"; + +static struct option options[] = { + {"banks", required_argument, NULL, 'b'}, + {"images", required_argument, NULL, 'i'}, + {"guid", required_argument, NULL, 'g'}, + {"active-bank", required_argument, NULL, 'a'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}, +}; + +static void print_usage(void) +{ + fprintf(stderr, "Usage: mkfwumdata [options] [...] \n"); + fprintf(stderr, "Options:\n" + "\t-i, --images Number of images\n" + "\t-b, --banksNumber of banks\n" + "\t-a, --active-bank Active bank\n" + "\t-g, --guid Use GUID instead of UUID\n" + "\t-h, --help print a help message\n" + ); + fprintf(stderr, "UUIDs list syntax:\n" + "\t,,[,]\n" + "\n\tYou must specify # of banks of image-uuid and # of images of the lists.\n" + "\tIf the location uuid and image uuid are '0', those are filled with null uuid.\n" + ); +} + +static bool __use_guid; +static u32 active_bank; + +struct fwu_mdata_object { + size_t images; + size_t banks; + size_t size; + struct fwu_mdata *mdata; +}; + +struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) +{ + struct fwu_mdata_object *mobj; + + mobj = malloc(sizeof(*mobj)); + if (!mobj) + return NULL; + mobj->size = sizeof(struct fwu_mdata) + + (sizeof(struct fwu_image_entry) + +sizeof(struct fwu_image_bank_info) * banks) * images; + mobj->images = images;
[PATCH v5 13/23] FWU: Add FWU metadata access driver for non-GPT MTD devices
From: Masami Hiramatsu For the platform which doesn't have GPT partitions for the firmware but on MTD devices, the FWU metadata is stored on MTD device as raw image at specific offset. This driver gives the access methods for the FWU metadata information on such MTD devices. Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- drivers/fwu-mdata/Kconfig | 8 + drivers/fwu-mdata/Makefile| 1 + drivers/fwu-mdata/fwu_mdata_mtd.c | 308 ++ 3 files changed, 317 insertions(+) create mode 100644 drivers/fwu-mdata/fwu_mdata_mtd.c diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig index d5edef19d6..a8fa9ad783 100644 --- a/drivers/fwu-mdata/Kconfig +++ b/drivers/fwu-mdata/Kconfig @@ -14,3 +14,11 @@ config FWU_MDATA_GPT_BLK help Enable support for accessing FWU Metadata on GPT partitioned block devices. + +config FWU_MDATA_MTD + bool "FWU Metadata access for non-GPT MTD devices" + depends on DM_FWU_MDATA && MTD + help + Enable support for accessing FWU Metadata on non-partitioned + (or non-GPT partitioned, e.g. partition nodes in devicetree) + MTD devices. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile index 12a5b4fe04..c574c59be2 100644 --- a/drivers/fwu-mdata/Makefile +++ b/drivers/fwu-mdata/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o +obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mdata_mtd.o diff --git a/drivers/fwu-mdata/fwu_mdata_mtd.c b/drivers/fwu-mdata/fwu_mdata_mtd.c new file mode 100644 index 00..9eb471e73e --- /dev/null +++ b/drivers/fwu-mdata/fwu_mdata_mtd.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct fwu_mdata_mtd_priv { + struct mtd_info *mtd; + u32 pri_offset; + u32 sec_offset; +}; + +enum fwu_mtd_op { + FWU_MTD_READ, + FWU_MTD_WRITE, +}; + +static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) +{ + return !do_div(size, mtd->erasesize); +} + +static int mtd_io_data(struct mtd_info *mtd, u32 offs, u32 size, void *data, + enum fwu_mtd_op op) +{ + struct mtd_oob_ops io_op ={}; + u64 lock_offs, lock_len; + size_t len; + void *buf; + int ret; + + if (!mtd_is_aligned_with_block_size(mtd, offs)) + return -EINVAL; + lock_offs = offs; + lock_len = round_up(size, mtd->erasesize); + + ret = mtd_unlock(mtd, lock_offs, lock_len); + if (ret && ret != -EOPNOTSUPP) + return ret; + + if (op == FWU_MTD_WRITE) { + struct erase_info erase_op = {}; + + /* This will expand erase size to align with the block size */ + erase_op.mtd = mtd; + erase_op.addr = lock_offs; + erase_op.len = lock_len; + erase_op.scrub = 0; + + ret = mtd_erase(mtd, _op); + if (ret) + goto lock_out; + } + + /* Also, expand the write size to align with the write size */ + len = round_up(size, mtd->writesize); + + buf = memalign(ARCH_DMA_MINALIGN, len); + if (!buf) { + ret = -ENOMEM; + goto lock_out; + } + io_op.mode = MTD_OPS_AUTO_OOB; + io_op.len = len; + io_op.ooblen = 0; + io_op.datbuf = buf; + io_op.oobbuf = NULL; + + if (op == FWU_MTD_WRITE) { + memcpy(buf, data, size); + ret = mtd_write_oob(mtd, offs, _op); + } else { + ret = mtd_read_oob(mtd, offs, _op); + if (!ret) + memcpy(data, buf, size); + } + free(buf); + +lock_out: + mtd_lock(mtd, lock_offs, lock_len); + + return ret; +} + +static int fwu_mtd_load_mdata(struct mtd_info *mtd, struct fwu_mdata **mdata, + u32 offs, bool primary) +{ + size_t size = sizeof(struct fwu_mdata); + int ret; + + *mdata = malloc(size); + if (!*mdata) + return -ENOMEM; + + ret = mtd_io_data(mtd, offs, size, (void *)*mdata, FWU_MTD_READ); + if (ret >= 0) { + ret = fwu_verify_mdata(*mdata, primary); + if (ret < 0) { + free(*mdata); + *mdata = NULL; + } + } + + return ret; +} + +static int fwu_mtd_load_primary_mdata(struct fwu_mdata_mtd_priv *mtd_priv, +struct fwu_mdata **mdata) +{ + return fwu_mtd_load_mdata(mtd_priv->mtd, mdata, mtd_priv->pri_offset, true); +} + +static int fwu_mtd_load_seco
[PATCH v5 14/23] dt/bindings: firmware: Add FWU metadata on MTD devices binding
From: Masami Hiramatsu Add a devicetree-binding YAML file for the FWU metadata on MTD devices without GPT. Signed-off-by: Masami Hiramatsu Signed-off-by: Sughosh Ganu --- .../firmware/uboot,fwu-mdata-mtd.yaml | 38 +++ 1 file changed, 38 insertions(+) create mode 100644 doc/device-tree-bindings/firmware/uboot,fwu-mdata-mtd.yaml diff --git a/doc/device-tree-bindings/firmware/uboot,fwu-mdata-mtd.yaml b/doc/device-tree-bindings/firmware/uboot,fwu-mdata-mtd.yaml new file mode 100644 index 00..4f5404f999 --- /dev/null +++ b/doc/device-tree-bindings/firmware/uboot,fwu-mdata-mtd.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/firmware/u-boot,fwu-mdata-sf.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: FWU metadata on MTD device without GPT + +maintainers: + - Masami Hiramatsu + +properties: + compatible: +items: + - const: u-boot,fwu-mdata-mtd + + fwu-mdata-store: +maxItems: 1 +description: Phandle of the MTD device which contains the FWU medatata. + + mdata-offsets: +minItems: 2 +description: Offsets of the primary and secondary FWU metadata in the NOR flash. + +required: + - compatible + - fwu-mdata-store + - mdata-offsets + +additionalProperties: false + +examples: + - | +fwu-mdata { +compatible = "u-boot,fwu-mdata-mtd"; +fwu-mdata-store = <>; +mdata-offsets = <0x50 0x53>; +}; -- 2.25.1
[PATCH v5 11/23] mkeficapsule: Add support for generating empty capsules
The Dependable Boot specification[1] describes the structure of the firmware accept and revert capsules. These are empty capsules which are used for signalling the acceptance or rejection of the updated firmware by the OS. Add support for generating these empty capsules. [1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Signed-off-by: Sughosh Ganu --- doc/mkeficapsule.1 | 29 ++--- tools/eficapsule.h | 8 +++ tools/mkeficapsule.c | 139 +-- 3 files changed, 151 insertions(+), 25 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 09bdc24295..77ca061efd 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot .SH SYNOPSIS .B mkeficapsule -.RI [ options "] " image-blob " " capsule-file +.RI [ options ] " " [ image-blob ] " " capsule-file .SH "DESCRIPTION" .B mkeficapsule @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given private key. In this case, the update will be authenticated by verifying the signature before applying. +Additionally, an empty capsule file can be generated for acceptance or +rejection of firmware images by a governing component like an Operating +System. The empty capsules do not require an image-blob input file. + + .B mkeficapsule -takes any type of image files, including: +takes any type of image files when generating non empty capsules, including: .TP .I raw image format is a single binary blob of any type of firmware. @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file. This type of image file can be generated by .BR mkimage . -.PP -If you want to use other types than above two, you should explicitly -specify a guid for the FMP driver. - .SH "OPTIONS" + .TP .BI "-g\fR,\fB --guid " guid-string Specify guid for image blob type. The format is: ---- The first three elements are in little endian, while the rest -is in big endian. +is in big endian. The option must be specified for all non empty and +image acceptance capsules .TP .BI "-i\fR,\fB --index " index @@ -57,6 +60,18 @@ Specify an image index .BI "-I\fR,\fB --instance " instance Specify a hardware instance +.PP +For generation of firmware accept empty capsule +.BR --guid +is mandatory +.TP +.BI "-A\fR,\fB --fw-accept " +Generate a firmware acceptance empty capsule + +.TP +.BI "-R\fR,\fB --fw-revert " +Generate a firmware revert empty capsule + .TP .BR -h ", " --help Print a help message diff --git a/tools/eficapsule.h b/tools/eficapsule.h index d63b831443..072a4b5598 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -41,6 +41,14 @@ typedef struct { EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \ 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) +#define FW_ACCEPT_OS_GUID \ + EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) + +#define FW_REVERT_OS_GUID \ + EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \ +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0) + /* flags */ #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x0001 diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 5f74d23b9e..e8eb6b070d 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,16 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; -static const char *opts_short = "g:i:I:v:p:c:m:dh"; +static const char *opts_short = "g:i:I:v:p:c:m:dhAR"; + +static bool empty_capsule; +static unsigned char capsule; + +enum { + CAPSULE_NORMAL_BLOB = 0, + CAPSULE_ACCEPT, + CAPSULE_REVERT, +} capsule_type; static struct option options[] = { {"guid", required_argument, NULL, 'g'}, @@ -39,24 +48,47 @@ static struct option options[] = { {"certificate", required_argument, NULL, 'c'}, {"monotonic-count", required_argument, NULL, 'm'}, {"dump-sig", no_argument, NULL, 'd'}, + {"fw-accept", no_argument, NULL, 'A'}, + {"fw-revert", no_argument, NULL, 'R'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; static void print_usage(void) { - fprintf(stderr, "Usage: %s [options] \n" - "Options:\n" - - "\t-g, --guid guid for image blob type\n" - "\t-i, --index update image index\n" - "\t-I, --instanceupdate hardware instance\n" - "\t-p,
[PATCH v5 12/23] FWU: doc: Add documentation for the FWU feature
Add documentattion for the FWU Multi Bank Update feature. The document describes the steps needed for setting up the platform for the feature, as well as steps for enabling the feature on the platform. Signed-off-by: Sughosh Ganu --- doc/develop/uefi/fwu_updates.rst | 142 +++ doc/develop/uefi/index.rst | 1 + doc/develop/uefi/uefi.rst| 2 + 3 files changed, 145 insertions(+) create mode 100644 doc/develop/uefi/fwu_updates.rst diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst new file mode 100644 index 00..1c34beb7d5 --- /dev/null +++ b/doc/develop/uefi/fwu_updates.rst @@ -0,0 +1,142 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (c) 2022 Linaro Limited + +FWU Multi Bank Updates in U-Boot + + +The FWU Multi Bank Update feature implements the firmware update +mechanism described in the PSA Firmware Update for A-profile Arm +Architecture specification[1]. Certain aspects of the Dependable +Boot specification[2] are also implemented. The feature provides a +mechanism to have multiple banks of updatable firmware images and for +updating the firmware images on the non-booted bank. On a successful +update, the platform boots from the updated bank on subsequent +boot. The UEFI capsule-on-disk update feature is used for performing +the actual updates of the updatable firmware images. + +The bookkeeping of the updatable images is done through a structure +called metadata. Currently, the FWU metadata supports identification +of images based on image GUIDs stored on a GPT partitioned storage +media. There are plans to extend the metadata structure for non GPT +partitioned devices as well. + +Accessing the FWU metadata is done through generic API's which are +defined in a driver which complies with the u-boot's driver model. A +new uclass UCLASS_FWU_MDATA has been added for accessing the FWU +metadata. Individual drivers can be added based on the type of storage +media, and it's partitioning method. Details of the storage device +containing the FWU metadata partitions are specified through a U-Boot +specific device tree property `fwu-mdata-store`. Please refer to +U-Boot `doc `__ for +the device tree bindings. + +Enabling the FWU Multi Bank Update feature +-- + +The feature can be enabled by specifying the following configs:: + +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y +CONFIG_EFI_CAPSULE_FIRMWARE=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y + +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_CMD_FWU_METADATA=y +CONFIG_DM_FWU_MDATA=y +CONFIG_FWU_MDATA_GPT_BLK=y +CONFIG_FWU_NUM_BANKS= +CONFIG_FWU_NUM_IMAGES_PER_BANK= + +in the .config file + +The first group of configs enable the UEFI capsule-on-disk update +functionality. The second group of configs 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. + +Setting up the device for GPT partitioned storage +- + +Before enabling the functionality in U-Boot, certain changes are +required to be done on the storage device. Assuming a GPT partitioned +storage device, the storage media needs to be partitioned with the +correct number of partitions, given the number of banks and number of +images per bank that the platform is going to support. Each updatable +firmware image will be stored on an separate partition. In addition, +the two copies of the FWU metadata will be stored on two separate +partitions. + +As an example, a platform supporting two banks with each bank +containing three images would need to have 2 * 3 = 6 parititions plus +the two metadata partitions, or 8 partitions. In addition the storage +media can have additional partitions of non-updatable images, like the +EFI System Partition(ESP), a partition for the root file system etc. + +When generating the partitions, a few aspects need to be taken care +of. Each GPT partition entry in the GPT header has two GUIDs:: + +*PartitionTypeGUID* +*UniquePartitionGUID* + +The PartitionTypeGUID value should correspond to the *image_type_uuid* +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* +field in the FWU metadata. This GUID is used to identify images of a +given image type in different banks. + +Similarly, the FWU specifications defines the GUID value to be used +for the metadata partitions. This would be the PartitionTypeGUID for +the metadata partitions. + +When generating the metadata, the *image_type_uuid* and the +*image_uuid* values should match the *PartitionTypeGUID
[PATCH v5 09/23] FWU: Add support for the FWU Multi Bank Update feature
The FWU Multi Bank Update feature supports updation of firmware images to one of multiple sets(also called banks) of images. The firmware images are clubbed together in banks, with the system booting images from the active bank. Information on the images such as which bank they belong to is stored as part of the metadata structure, which is stored on the same storage media as the firmware images on a dedicated partition. At the time of update, the metadata is read to identify the bank to which the images need to be flashed(update bank). On a successful update, the metadata is modified to set the updated bank as active bank to subsequently boot from. Signed-off-by: Sughosh Ganu --- include/fwu.h| 12 +- lib/Kconfig | 6 + lib/Makefile | 1 + lib/efi_loader/efi_capsule.c | 231 ++- lib/efi_loader/efi_setup.c | 3 +- lib/fwu_updates/Kconfig | 31 + lib/fwu_updates/Makefile | 6 + lib/fwu_updates/fwu.c| 26 8 files changed, 309 insertions(+), 7 deletions(-) create mode 100644 lib/fwu_updates/Kconfig create mode 100644 lib/fwu_updates/Makefile diff --git a/include/fwu.h b/include/fwu.h index 8fbd91b463..9c8012407b 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -28,13 +28,23 @@ struct fwu_mdata_ops { }; #define FWU_MDATA_VERSION 0x1 +#define FWU_IMAGE_ACCEPTED 0x1 #define FWU_MDATA_GUID \ EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) -int fwu_boottime_checks(void); +#define FWU_OS_REQUEST_FW_REVERT_GUID \ + EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \ +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0) + +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \ + EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) + u8 fwu_update_checks_pass(void); +int fwu_boottime_checks(void); +int fwu_trial_state_ctr_start(void); int fwu_get_mdata(struct fwu_mdata **mdata); int fwu_update_mdata(struct fwu_mdata *mdata); diff --git a/lib/Kconfig b/lib/Kconfig index acc0ac081a..4ca6ea226b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -966,3 +966,9 @@ config PHANDLE_CHECK_SEQ phandles in fdtdec_get_alias_seq() function. endmenu + +menu "FWU Multi Bank Updates" + +source lib/fwu_updates/Kconfig + +endmenu diff --git a/lib/Makefile b/lib/Makefile index d9b1811f75..0cf8527c2d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/ obj-$(CONFIG_EFI_LOADER) += efi_driver/ obj-$(CONFIG_EFI_LOADER) += efi_loader/ obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/ +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/ obj-$(CONFIG_LZMA) += lzma/ obj-$(CONFIG_BZIP2) += bzip2/ obj-$(CONFIG_TIZEN) += tizen/ diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index c76a5f3570..8ca041e6a2 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,17 @@ static const efi_guid_t efi_guid_firmware_management_capsule_id = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; const efi_guid_t efi_guid_firmware_management_protocol = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; +const efi_guid_t fwu_guid_os_request_fw_revert = + FWU_OS_REQUEST_FW_REVERT_GUID; +const efi_guid_t fwu_guid_os_request_fw_accept = + FWU_OS_REQUEST_FW_ACCEPT_GUID; + +#define FW_ACCEPT_OS (u32)0x8000 + +__maybe_unused static u32 update_index; +__maybe_unused static bool capsule_update; +__maybe_unused static bool fw_accept_os; +static bool image_index_check = true; #ifdef CONFIG_EFI_CAPSULE_ON_DISK /* for file system access */ @@ -205,7 +217,8 @@ efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance, log_debug("+++ desc[%d] index: %d, name: %ls\n", j, desc->image_index, desc->image_id_name); if (!guidcmp(>image_type_id, image_type) && - (desc->image_index == image_index) && + (!image_index_check || +desc->image_index == image_index) && (!instance || !desc->hardware_instance || desc->hardware_instance == instance)) @@ -388,6 +401,87 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s } #endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */ +static bool fwu_empty_capsule(struct efi_capsule_header *capsule) +{ + return !guidcmp(>capsule_guid, + _guid_os_request_fw_revert) || + !guidcmp(>capsule_guid, +_guid_os_request_fw_accept); +} + +static ef
[PATCH v5 10/23] FWU: cmd: Add a command to read FWU metadata
Add a command to read the metadata as specified in the FWU specification and print the fields of the metadata. Signed-off-by: Sughosh Ganu --- cmd/Kconfig | 7 + cmd/Makefile| 1 + cmd/fwu_mdata.c | 74 + 3 files changed, 82 insertions(+) create mode 100644 cmd/fwu_mdata.c diff --git a/cmd/Kconfig b/cmd/Kconfig index 09193b61b9..275becd837 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -144,6 +144,13 @@ config CMD_CPU internal name) and clock frequency. Other information may be available depending on the CPU driver. +config CMD_FWU_METADATA + bool "fwu metadata read" + depends on FWU_MULTI_BANK_UPDATE + default y if FWU_MULTI_BANK_UPDATE + help + Command to read the metadata and dump it's contents + config CMD_LICENSE bool "license" select BUILD_BIN2C diff --git a/cmd/Makefile b/cmd/Makefile index 5e43a1e022..259a93bc65 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_FPGA) += fpga.o obj-$(CONFIG_CMD_FPGAD) += fpgad.o obj-$(CONFIG_CMD_FS_GENERIC) += fs.o obj-$(CONFIG_CMD_FUSE) += fuse.o +obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o obj-$(CONFIG_CMD_GETTIME) += gettime.o obj-$(CONFIG_CMD_GPIO) += gpio.o obj-$(CONFIG_CMD_HVC) += smccc.o diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c new file mode 100644 index 00..bc20ca26a3 --- /dev/null +++ b/cmd/fwu_mdata.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static void print_mdata(struct fwu_mdata *mdata) +{ + int i, j; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_info; + u32 nimages, nbanks; + + 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); + + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; + nbanks = CONFIG_FWU_NUM_BANKS; + printf("\tImage Info\n"); + for (i = 0; i < nimages; i++) { + img_entry = >img_entry[i]; + printf("\nImage Type Guid: %pUL\n", _entry->image_type_uuid); + printf("Location Guid: %pUL\n", _entry->location_uuid); + for (j = 0; j < nbanks; j++) { + img_info = _entry->img_bank_info[j]; + printf("Image Guid: %pUL\n", _info->image_uuid); + printf("Image Acceptance: %#x\n", img_info->accepted); + } + } +} + +int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, +int argc, char * const argv[]) +{ + struct udevice *dev; + int ret = CMD_RET_SUCCESS; + struct fwu_mdata *mdata = NULL; + + if (uclass_get_device(UCLASS_FWU_MDATA, 0, ) || !dev) { + log_err("Unable to get FWU metadata device\n"); + return CMD_RET_FAILURE; + } + + ret = fwu_get_mdata(); + if (ret < 0) { + log_err("Unable to get valid FWU metadata\n"); + ret = CMD_RET_FAILURE; + goto out; + } + + print_mdata(mdata); + +out: + free(mdata); + return ret; +} + +U_BOOT_CMD( + fwu_mdata_read, 1, 1, do_fwu_mdata_read, + "Read and print FWU metadata", + "" +); -- 2.25.1
[PATCH v5 08/23] FWU: Add boot time checks as highlighted by the FWU specification
The FWU Multi Bank Update specification requires the Update Agent to carry out certain checks at the time of platform boot. The Update Agent is the component which is responsible for updating the firmware components and maintaining and keeping the metadata in sync. The spec requires that the Update Agent perform the following checks at the time of boot * Sanity check of both the metadata copies maintained by the platform. * Get the boot index passed to U-Boot by the prior stage bootloader and use this value for metadata bookkeeping. * Check if the system is booting in Trial State. If the system boots in the Trial State for more than a specified number of boot counts, change the Active Bank to be booting the platform from. Add these checks in the board initialisation sequence, invoked after relocation. Signed-off-by: Sughosh Ganu --- common/board_r.c | 5 ++ include/fwu.h | 3 + lib/fwu_updates/fwu.c | 170 ++ 3 files changed, 178 insertions(+) create mode 100644 lib/fwu_updates/fwu.c diff --git a/common/board_r.c b/common/board_r.c index 6f4aca2077..33a600715d 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -797,6 +798,10 @@ static init_fnc_t init_sequence_r[] = { #if defined(CONFIG_PRAM) initr_mem, #endif + +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE + fwu_boottime_checks, +#endif run_main_loop, }; diff --git a/include/fwu.h b/include/fwu.h index 41774ff9e2..8fbd91b463 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -33,6 +33,9 @@ struct fwu_mdata_ops { EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \ 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23) +int fwu_boottime_checks(void); +u8 fwu_update_checks_pass(void); + int fwu_get_mdata(struct fwu_mdata **mdata); int fwu_update_mdata(struct fwu_mdata *mdata); int fwu_get_active_index(u32 *active_idx); diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c new file mode 100644 index 00..af884439fb --- /dev/null +++ b/lib/fwu_updates/fwu.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static u8 trial_state; +static u8 boottime_check; + +static int fwu_trial_state_check(void) +{ + int ret, i; + efi_status_t status; + efi_uintn_t var_size; + u16 trial_state_ctr; + u32 nimages, active_bank, var_attributes, active_idx; + struct fwu_mdata *mdata = NULL; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_bank_info; + + ret = fwu_get_mdata(); + if (ret) + return ret; + + ret = 0; + nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK; + active_bank = mdata->active_index; + img_entry = >img_entry[0]; + for (i = 0; i < nimages; i++) { + img_bank_info = _entry[i].img_bank_info[active_bank]; + if (!img_bank_info->accepted) { + trial_state = 1; + break; + } + } + + if (trial_state) { + var_size = (efi_uintn_t)sizeof(trial_state_ctr); + log_info("System booting in Trial State\n"); + var_attributes = EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS; + status = efi_get_variable_int(L"TrialStateCtr", + _global_variable_guid, + _attributes, + _size, _state_ctr, + NULL); + if (status != EFI_SUCCESS) { + log_err("Unable to read TrialStateCtr variable\n"); + ret = -1; + goto out; + } + + ++trial_state_ctr; + if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) { + log_info("Trial State count exceeded. Revert back to previous_active_index\n"); + active_idx = mdata->active_index; + ret = fwu_revert_boot_index(); + if (ret) { + log_err("Unable to revert active_index\n"); + goto out; + } + + trial_state_ctr = 0; + status = efi_set_variable_int(L"TrialStateCtr", + _global_variable_guid, + var_attributes, + 0, +
[PATCH v5 07/23] FWU: STM32MP1: Add support to read boot index from backup register
The FWU Multi Bank Update feature allows the platform to boot the firmware images from one of the partitions(banks). The first stage bootloader(fsbl) passes the value of the boot index, i.e. the bank from which the firmware images were booted from to U-Boot. On the STM32MP157C-DK2 board, this value is passed through one of the SoC's backup register. Add a function to read the boot index value from the backup register. Signed-off-by: Sughosh Ganu --- arch/arm/mach-stm32mp/include/mach/stm32.h | 4 board/st/stm32mp1/stm32mp1.c | 7 +++ include/fwu.h | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 47e88fc3dc..40995ee142 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -100,6 +100,7 @@ enum boot_device { #define TAMP_BACKUP_REGISTER(x)(STM32_TAMP_BASE + 0x100 + 4 * x) #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) +#define TAMP_FWU_BOOT_INFO_REG TAMP_BACKUP_REGISTER(10) #define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) #define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) @@ -118,6 +119,9 @@ enum boot_device { #define TAMP_BOOT_INSTANCE_MASKGENMASK(3, 0) #define TAMP_BOOT_FORCED_MASK GENMASK(7, 0) #define TAMP_BOOT_DEBUG_ON BIT(16) +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) + +#define TAMP_FWU_BOOT_IDX_OFFSET 0 enum forced_boot_mode { BOOT_NORMAL = 0x00, diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index e68bf09955..dff41ed6f6 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -1081,4 +1081,11 @@ int fwu_plat_get_update_index(u32 *update_idx) return ret; } +void fwu_plat_get_bootidx(void *boot_idx) +{ + u32 *bootidx = boot_idx; + + *bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >> + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; +} #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/include/fwu.h b/include/fwu.h index 36e58afa29..41774ff9e2 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -46,7 +46,7 @@ int fwu_revert_boot_index(void); int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); - +void fwu_plat_get_bootidx(void *boot_idx); int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, int *alt_num); int fwu_plat_get_update_index(u32 *update_idx); -- 2.25.1
[PATCH v5 06/23] FWU: stm32mp1: Add helper functions for accessing FWU metadata
Add helper functions needed for accessing the FWU metadata which contains information on the updatable images. These functions have been added for the STM32MP157C-DK2 board which has the updatable images on the uSD card, formatted as GPT partitions. Signed-off-by: Sughosh Ganu --- board/st/stm32mp1/stm32mp1.c | 115 +++ include/fwu.h| 2 + 2 files changed, 117 insertions(+) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 62d98ad776..e68bf09955 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -25,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -967,3 +971,114 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size) } U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); + +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) +#include +#include + +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t *image_guid) +{ + int i; + struct disk_partition info; + efi_guid_t unique_part_guid; + + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { + if (part_get_info(desc, i, )) + continue; + uuid_str_to_bin(info.uuid, unique_part_guid.b, + UUID_STR_FORMAT_GUID); + + if (!guidcmp(_part_guid, image_guid)) + return i; + } + + log_err("No partition found with image_guid %pUs\n", image_guid); + return -ENOENT; +} + +static int gpt_plat_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid, + int *alt_num) +{ + int ret = -1; + int i, part, dev_num; + int nalt; + struct dfu_entity *dfu; + + dev_num = desc->devnum; + part = get_gpt_dfu_identifier(desc, image_guid); + if (part < 0) + return -ENOENT; + + dfu_init_env_entities(NULL, NULL); + + nalt = 0; + list_for_each_entry(dfu, _list, list) { + nalt++; + } + + if (!nalt) { + log_warning("No entities in dfu_alt_info\n"); + dfu_free_entities(); + return -ENOENT; + } + + + for (i = 0; i < nalt; i++) { + dfu = dfu_get_entity(i); + + if (!dfu) + continue; + + /* +* Currently, Multi Bank update +* feature is being supported +* only on GPT partitioned +* MMC/SD devices. +*/ + if (dfu->dev_type != DFU_DEV_MMC) + continue; + + if (dfu->layout == DFU_RAW_ADDR && + dfu->data.mmc.dev_num == dev_num && + dfu->data.mmc.part == part) { + *alt_num = dfu->alt; + ret = 0; + break; + } + } + + dfu_free_entities(); + + return ret; +} + +int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, +int *alt_num) +{ + struct blk_desc *desc; + + desc = dev_get_uclass_plat(dev); + if (!desc) { + log_err("Block device not found\n"); + return -ENODEV; + } + + return gpt_plat_get_alt_num(desc, image_guid, alt_num); +} + +int fwu_plat_get_update_index(u32 *update_idx) +{ + int ret; + u32 active_idx; + + ret = fwu_get_active_index(_idx); + + if (ret < 0) + return -1; + + *update_idx = active_idx ^= 0x1; + + return ret; +} + +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/include/fwu.h b/include/fwu.h index 3b1ee4e83e..36e58afa29 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -46,6 +46,8 @@ int fwu_revert_boot_index(void); int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); + int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, int *alt_num); +int fwu_plat_get_update_index(u32 *update_idx); #endif /* _FWU_H_ */ -- 2.25.1
[PATCH v5 03/23] FWU: Add FWU metadata access driver for GPT partitioned block devices
In the FWU Multi Bank Update feature, the information about the updatable images is stored as part of the metadata, on a separate partition. Add a driver for reading from and writing to the metadata when the updatable images and the metadata are stored on a block device which is formated with GPT based partition scheme. Signed-off-by: Sughosh Ganu --- drivers/fwu-mdata/Kconfig | 9 + drivers/fwu-mdata/Makefile| 1 + drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 404 ++ include/fwu.h | 2 + 4 files changed, 416 insertions(+) create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig index d6a21c8e19..d5edef19d6 100644 --- a/drivers/fwu-mdata/Kconfig +++ b/drivers/fwu-mdata/Kconfig @@ -5,3 +5,12 @@ config DM_FWU_MDATA Enable support for accessing FWU Metadata partitions. The FWU Metadata partitions reside on the same storage device which contains the other FWU updatable firmware images. + +config FWU_MDATA_GPT_BLK + bool "FWU Metadata access for GPT partitioned Block devices" + select PARTITION_TYPE_GUID + select PARTITION_UUIDS + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION + help + Enable support for accessing FWU Metadata on GPT partitioned + block devices. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile index 7fec7171f4..12a5b4fe04 100644 --- a/drivers/fwu-mdata/Makefile +++ b/drivers/fwu-mdata/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c new file mode 100644 index 00..329bd3779b --- /dev/null +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PRIMARY_PART BIT(0) +#define SECONDARY_PART BIT(1) +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) + +#define MDATA_READ BIT(0) +#define MDATA_WRITEBIT(1) + +static int gpt_get_mdata_partitions(struct blk_desc *desc, + u16 *primary_mpart, + u16 *secondary_mpart) +{ + int i, ret; + u32 mdata_parts; + efi_guid_t part_type_guid; + struct disk_partition info; + const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID; + + mdata_parts = 0; + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { + if (part_get_info(desc, i, )) + continue; + uuid_str_to_bin(info.type_guid, part_type_guid.b, + UUID_STR_FORMAT_GUID); + + if (!guidcmp(_mdata_guid, _type_guid)) { + ++mdata_parts; + if (!*primary_mpart) + *primary_mpart = i; + else + *secondary_mpart = i; + } + } + + if (mdata_parts != 2) { + log_err("Expect two copies of the FWU metadata instead of %d\n", + mdata_parts); + ret = -EINVAL; + } else { + ret = 0; + } + + return ret; +} + +static int gpt_get_mdata_disk_part(struct blk_desc *desc, + struct disk_partition *info, + u32 part_num) +{ + int ret; + char *mdata_guid_str = "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23"; + + ret = part_get_info(desc, part_num, info); + if (ret < 0) { + log_err("Unable to get the partition info for the FWU metadata part %d", + part_num); + return -1; + } + + /* Check that it is indeed the FWU metadata partition */ + if (!strncmp(info->type_guid, mdata_guid_str, UUID_STR_LEN)) { + /* Found the FWU metadata partition */ + return 0; + } + + return -1; +} + +static int gpt_read_write_mdata(struct blk_desc *desc, + struct fwu_mdata *mdata, + u8 access, u32 part_num) +{ + int ret; + u32 len, blk_start, blkcnt; + struct disk_partition info; + + ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1, +desc->blksz); + + ret = gpt_get_mdata_disk_part(desc, , part_num); + if (ret < 0) { + printf("Unable to get the FWU metadata partition\n"); + return -ENODE
[PATCH v5 05/23] stm32mp1: dk2: Add image information for capsule updates
Enabling capsule update functionality on the platform requires populating information on the images that are to be updated using the functionality. Do so for the DK2 board. Signed-off-by: Sughosh Ganu --- board/st/stm32mp1/stm32mp1.c | 19 +++ include/configs/stm32mp15_common.h | 4 2 files changed, 23 insertions(+) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 07b1a63db7..62d98ad776 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,16 @@ DECLARE_GLOBAL_DATA_PTR; #define USB_START_LOW_THRESHOLD_UV 123 #define USB_START_HIGH_THRESHOLD_UV215 +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) +struct efi_fw_image fw_images[1]; + +struct efi_capsule_update_info update_info = { + .images = fw_images, +}; + +u8 num_image_type_guids = ARRAY_SIZE(fw_images); +#endif /* EFI_HAVE_CAPSULE_SUPPORT */ + int board_early_init_f(void) { /* nothing to do, only used in SPL */ @@ -675,6 +686,14 @@ int board_init(void) setup_led(LEDST_ON); +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) + if (board_is_dk2()) { + efi_guid_t image_type_guid = STM32MP1_DK2_FIP_IMAGE_GUID; + guidcpy(_images[0].image_type_id, _type_guid); + fw_images[0].fw_name = u"STM32MP1-DK2-FIP"; + fw_images[0].image_index = 5; + } +#endif return 0; } diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h index 6b40cdb017..6a1ae9788d 100644 --- a/include/configs/stm32mp15_common.h +++ b/include/configs/stm32mp15_common.h @@ -54,6 +54,10 @@ #define CONFIG_SYS_AUTOLOAD"no" #endif +#define STM32MP1_DK2_FIP_IMAGE_GUID \ + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \ +0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) + /*/ #ifdef CONFIG_DISTRO_DEFAULTS /*/ -- 2.25.1
[PATCH v5 02/23] FWU: Add FWU metadata structure and driver for accessing metadata
In the FWU Multi Bank Update feature, the information about the updatable images is stored as part of the metadata, which is stored on a dedicated partition. Add the metadata structure, and a driver model uclass which provides functions to access the metadata. These are generic API's, and implementations can be added based on parameters like how the metadata partition is accessed and what type of storage device houses the metadata. Signed-off-by: Sughosh Ganu --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/fwu-mdata/Kconfig| 7 + drivers/fwu-mdata/Makefile | 6 + drivers/fwu-mdata/fwu-mdata-uclass.c | 459 +++ include/dm/uclass-id.h | 1 + include/fwu.h| 49 +++ include/fwu_mdata.h | 67 8 files changed, 592 insertions(+) create mode 100644 drivers/fwu-mdata/Kconfig create mode 100644 drivers/fwu-mdata/Makefile create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c create mode 100644 include/fwu.h create mode 100644 include/fwu_mdata.h diff --git a/drivers/Kconfig b/drivers/Kconfig index b26ca8cf70..adc6079ecf 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -42,6 +42,8 @@ source "drivers/firmware/Kconfig" source "drivers/fpga/Kconfig" +source "drivers/fwu-mdata/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/hwspinlock/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 67c8af7442..901150bb35 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -83,6 +83,7 @@ obj-y += cache/ obj-$(CONFIG_CPU) += cpu/ obj-y += crypto/ obj-$(CONFIG_FASTBOOT) += fastboot/ +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/ obj-y += misc/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_NVME) += nvme/ diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig new file mode 100644 index 00..d6a21c8e19 --- /dev/null +++ b/drivers/fwu-mdata/Kconfig @@ -0,0 +1,7 @@ +config DM_FWU_MDATA + bool "Driver support for accessing FWU Metadata" + depends on DM + help + Enable support for accessing FWU Metadata partitions. The + FWU Metadata partitions reside on the same storage device + which contains the other FWU updatable firmware images. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile new file mode 100644 index 00..7fec7171f4 --- /dev/null +++ b/drivers/fwu-mdata/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2022, Linaro Limited +# + +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c new file mode 100644 index 00..1530ceb01d --- /dev/null +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define IMAGE_ACCEPT_SET BIT(0) +#define IMAGE_ACCEPT_CLEAR BIT(1) + +static int fwu_get_dev_ops(struct udevice **dev, + const struct fwu_mdata_ops **ops) +{ + int ret; + + ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev); + if (ret) { + log_debug("Cannot find fwu device\n"); + return ret; + } + + if ((*ops = device_get_ops(*dev)) == NULL) { + log_debug("Cannot get fwu device ops\n"); + return -ENOSYS; + } + + return 0; +} + +/** + * fwu_verify_mdata() - Verify the FWU metadata + * @mdata: FWU metadata structure + * @pri_part: FWU metadata partition is primary or secondary + * + * Verify the FWU metadata by computing the CRC32 for the metadata + * structure and comparing it against the CRC32 value stored as part + * of the structure. + * + * Return: 0 if OK, -ve on error + * + */ +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part) +{ + u32 calc_crc32; + void *buf; + + buf = >version; + calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); + + if (calc_crc32 != mdata->crc32) { + log_err("crc32 check failed for %s FWU metadata partition\n", + pri_part ? "primary" : "secondary"); + return -1; + } + + return 0; +} + +/** + * fwu_get_active_index() - Get active_index from the FWU metadata + * @active_idx: active_index value to be read + * + * Read the active_index field from the FWU metadata and place it in + * the variable pointed to be the function argument. + * + * Return: 0 if OK, -ve on error + * + */ +int fwu_get_active_index(u32 *active_idx) +{ + int ret; + struct fwu_mdata *mdata = NULL; + + ret = fwu_get_mdata(); + if (ret < 0) { +
[PATCH v5 04/23] stm32mp1: dk2: Add a node for the FWU metadata device
The FWU metadata structure is accessed through the driver model interface. On the stm32mp157c-dk2 board, the FWU metadata is stored on the uSD card. Add the fwu-mdata node on the u-boot specifc dtsi file for accessing the metadata structure. Signed-off-by: Sughosh Ganu --- arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi index 06ef3a4095..24f86209db 100644 --- a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi @@ -4,3 +4,10 @@ */ #include "stm32mp157a-dk1-u-boot.dtsi" + +/ { + fwu-mdata { + compatible = "u-boot,fwu-mdata-gpt"; + fwu-mdata-store = <>; + }; +}; -- 2.25.1
[PATCH v5 01/23] dt/bindings: Add bindings for FWU Metadata storage device
Add bindings needed for accessing the FWU metadata partitions. These include the compatible string which point to the access method and the actual device which stores the FWU metadata. The current patch adds basic bindings needed for accessing the metadata structure on GPT partitioned block devices. Signed-off-by: Sughosh Ganu --- .../firmware/fwu-mdata.txt | 18 ++ 1 file changed, 18 insertions(+) create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt new file mode 100644 index 00..2d8ed056a5 --- /dev/null +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt @@ -0,0 +1,18 @@ +FWU Metadata Access Devicetree Binding + +The FWU Multi Bank Update feature uses a metadata structure, stored on +a separate partition for keeping information on the set of updatable +images. The device tree node provides information on the storage +device that contains the FWU metadata. + +Required properties : + +- compatible : "u-boot,fwu-mdata-gpt"; +- fwu-mdata-store : should point to the storage device which contains + the FWU metadata partition. + +Example : + fwu-mdata { + compatible = "u-boot,fwu-mdata-gpt"; + fwu-mdata-store = <>; + }; -- 2.25.1
[PATCH v5 00/23] FWU: Add FWU Multi Bank Update feature support
The patchset adds support for the FWU Multi Bank Update[1] feature. Certain aspects of the Dependable Boot[2] specification have also been implemented. The FWU multi bank update feature is used for supporting multiple sets(also called banks) of firmware image(s), allowing the platform to boot from a different bank, in case it fails to boot from the active bank. This functionality is supported by keeping the relevant information in a structure called metadata, which provides information on the images. Among other parameters, the metadata structure contains information on the currect active bank that is being used to boot image(s). Functionality is being added to work with the UEFI capsule driver in u-boot. The metadata is read to gather information on the update bank, which is the bank to which the firmware images would be flashed to. On a successful completion of the update of all components, the active bank field in the metadata is updated, to reflect the bank from which the platform will boot on the subsequent boots. Currently, the feature is being enabled on the STM32MP157C-DK2 and Synquacer boards. The DK2 board boots a FIP image from a uSD card partitioned with the GPT partioning scheme, while the Synquacer board boots a FIP image from a MTD partitioned SPI NOR flash device. This feature also requires changes in a previous stage of bootloader, which parses the metadata and selects the bank to boot the image(s) from. Support has being added in tf-a(BL2 stage) for the STM32MP157C-DK2 board to boot the active bank images. These changes have been merged to the upstream tf-a repository. Earlier, two separate patchsets were being sent. The patchset sent by me was adding support for the feature, and enabling the feature on the ST board. The other set of patches were being sent by Masami Hiramatsu, which were enabling the feature on the Synquacer platform. This patchset contains both set of patches, along with the associated documentation and the python test script for testing the feature. The upstreaming effort for this feature had been put on a temporary hold to address the fixing of some issues in the capsule update code, primarily using a per platform image GUID for the updatable images. Now that the series has been merged, upstreaming effort for the FWU update feature is being resumed. Hence, this version does not have any review comments being addressed. [1] - https://developer.arm.com/documentation/den0118/a [2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Jassi Brar (1): developerbox: synquacer: Use FIP as the updatable image Masami Hiramatsu (9): FWU: Add FWU metadata access driver for non-GPT MTD devices dt/bindings: firmware: Add FWU metadata on MTD devices binding tools: Add mkfwumdata tool for FWU metadata image FWU: doc: Update documentation for the FWU non-GPT MTD synquacer: Update for TBBR (BL2) based new FIP layout FWU: synquacer: Add FWU Multi bank update support for DeveloperBox FWU: synquacer: Generate dfu_alt_info from devicetree partition doc: synquacer: Add how to enable FWU Multi Bank Update [TEMP]configs: synquacer: Add FWU support for DeveloperBox Sughosh Ganu (13): dt/bindings: Add bindings for FWU Metadata storage device FWU: Add FWU metadata structure and driver for accessing metadata FWU: Add FWU metadata access driver for GPT partitioned block devices stm32mp1: dk2: Add a node for the FWU metadata device stm32mp1: dk2: Add image information for capsule updates FWU: stm32mp1: Add helper functions for accessing FWU metadata FWU: STM32MP1: Add support to read boot index from backup register FWU: Add boot time checks as highlighted by the FWU specification FWU: Add support for the FWU Multi Bank Update feature FWU: cmd: Add a command to read FWU metadata mkeficapsule: Add support for generating empty capsules FWU: doc: Add documentation for the FWU feature sandbox: fwu: Add support for testing FWU feature on sandbox arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 + .../synquacer-sc2a11-developerbox-u-boot.dtsi | 40 +- arch/arm/mach-stm32mp/include/mach/stm32.h| 4 + arch/sandbox/Kconfig | 6 + arch/sandbox/dts/test.dts | 45 +- board/sandbox/sandbox.c | 49 ++ board/socionext/developerbox/Kconfig | 14 + board/socionext/developerbox/Makefile | 1 + board/socionext/developerbox/developerbox.c | 17 +- board/socionext/developerbox/fwu_plat.c | 200 board/st/stm32mp1/stm32mp1.c | 141 ++ cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/fwu_mdata.c | 74 +++ common/board_r.c | 5 + configs/sandbox64_defconfig | 12 +- configs/synquacer_developerbox_defconfig | 10 +- doc
[PATCH v2 4/4] EFI: FMP: Use a common GetImageInfo function for FIT and raw images
The GetImageInfo function definitions for the FIT images and raw images are the same. Use a common function for the both the Firmware Management Protocol(FMP) instances for raw and FIT images. Signed-off-by: Sughosh Ganu --- Changes since V1: None lib/efi_loader/efi_firmware.c | 80 ++- 1 file changed, 14 insertions(+), 66 deletions(-) diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 9cdefab41f..0ffee3fb1f 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -177,18 +177,8 @@ static efi_status_t efi_fill_image_desc_array( return EFI_SUCCESS; } -#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT -/* - * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update - * method with existing FIT image format, and handles - * - multiple regions of firmware via DFU - * but doesn't support - * - versioning of firmware image - * - package information - */ - /** - * efi_firmware_fit_get_image_info - return information about the current + * efi_firmware_get_image_info - return information about the current * firmware image * @this: Protocol instance * @image_info_size: Size of @image_info @@ -206,7 +196,7 @@ static efi_status_t efi_fill_image_desc_array( * Return status code */ static -efi_status_t EFIAPI efi_firmware_fit_get_image_info( +efi_status_t EFIAPI efi_firmware_get_image_info( struct efi_firmware_management_protocol *this, efi_uintn_t *image_info_size, struct efi_firmware_image_descriptor *image_info, @@ -239,6 +229,16 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info( return EFI_EXIT(ret); } +#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT +/* + * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update + * method with existing FIT image format, and handles + * - multiple regions of firmware via DFU + * but doesn't support + * - versioning of firmware image + * - package information + */ + /** * efi_firmware_fit_set_image - update the firmware image * @this: Protocol instance @@ -278,7 +278,7 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( } const struct efi_firmware_management_protocol efi_fmp_fit = { - .get_image_info = efi_firmware_fit_get_image_info, + .get_image_info = efi_firmware_get_image_info, .get_image = efi_firmware_get_image_unsupported, .set_image = efi_firmware_fit_set_image, .check_image = efi_firmware_check_image_unsupported, @@ -293,58 +293,6 @@ const struct efi_firmware_management_protocol efi_fmp_fit = { * method with raw data. */ -/** - * efi_firmware_raw_get_image_info - return information about the current - * firmware image - * @this: Protocol instance - * @image_info_size: Size of @image_info - * @image_info:Image information - * @descriptor_version:Pointer to version number - * @descriptor_count: Pointer to number of descriptors - * @descriptor_size: Pointer to descriptor size - * @package_version: Package version - * @package_version_name: Package version's name - * - * Return information bout the current firmware image in @image_info. - * @image_info will consist of a number of descriptors. - * Each descriptor will be created based on "dfu_alt_info" variable. - * - * Return status code - */ -static -efi_status_t EFIAPI efi_firmware_raw_get_image_info( - struct efi_firmware_management_protocol *this, - efi_uintn_t *image_info_size, - struct efi_firmware_image_descriptor *image_info, - u32 *descriptor_version, - u8 *descriptor_count, - efi_uintn_t *descriptor_size, - u32 *package_version, - u16 **package_version_name) -{ - efi_status_t ret = EFI_SUCCESS; - - EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, - image_info_size, image_info, - descriptor_version, descriptor_count, descriptor_size, - package_version, package_version_name); - - if (!image_info_size) - return EFI_EXIT(EFI_INVALID_PARAMETER); - - if (*image_info_size && - (!image_info || !descriptor_version || !descriptor_count || -!descriptor_size || !package_version || !package_version_name)) - return EFI_EXIT(EFI_INVALID_PARAMETER); - - ret = efi_fill_image_desc_array(image_info_size, image_info, - descriptor_version, descriptor_count, - descriptor_size, package_version, - package_version_name); - - return EFI_EXIT(ret); -} - /** * efi_firmware_raw_set_image - update the firmware image * @this: Protocol instance @@ -430,7 +
[PATCH v2 3/4] EFI: Update the documentation to reflect the correct value of OsIndications
The OsIndications is a 64 bit variable, and the current code expects the value of the variable to be 64 bit. Update the documentation to reflect this fact. Signed-off-by: Sughosh Ganu Reviewed-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- Changes since V1: None doc/develop/uefi/uefi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index 753a4e5e29..941e427093 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -326,7 +326,7 @@ bit in OsIndications variable with .. code-block:: console -=> setenv -e -nv -bs -rt -v OsIndications =0x04 +=> setenv -e -nv -bs -rt -v OsIndications =0x0004 Since U-boot doesn't currently support SetVariable at runtime, its value won't be taken over across the reboot. If this is the case, you can skip -- 2.25.1
[PATCH v2 2/4] EFI: Do not consider OsIndications variable if CONFIG_EFI_IGNORE_OSINDICATIONS is enabled
The EFI_IGNORE_OSINDICATIONS config symbol was introduced as a mechanism to have capsule updates work even on platforms where the SetVariable runtime service was not supported. The current logic requires the OsIndications variable to have been set to a 64 bit value even when the EFI_IGNORE_OSINDICATIONS config is enabled. Return an error code on not being able to read the variable only when EFI_IGNORE_OSINDICATIONS is not enabled. Signed-off-by: Sughosh Ganu --- Changes since V1: * Read the OsIndications variable, if present and clear the EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED flag even if the CONFIG_EFI_IGNORE_OSINDICATIONS config is enabled. lib/efi_loader/efi_capsule.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index c76a5f3570..a6b98f066a 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -1058,14 +1058,15 @@ static void efi_capsule_scan_done(void) */ static efi_status_t check_run_capsules(void) { - u64 os_indications; + u64 os_indications = 0x0; efi_uintn_t size; efi_status_t r; size = sizeof(os_indications); r = efi_get_variable_int(u"OsIndications", _global_variable_guid, NULL, , _indications, NULL); - if (r != EFI_SUCCESS || size != sizeof(os_indications)) + if (!IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS) && + (r != EFI_SUCCESS || size != sizeof(os_indications))) return EFI_NOT_FOUND; if (os_indications & @@ -1084,7 +1085,7 @@ static efi_status_t check_run_capsules(void) return EFI_SUCCESS; } else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) { return EFI_SUCCESS; - } else { + } else { return EFI_NOT_FOUND; } } -- 2.25.1
[PATCH v2 1/4] EFI: Populate descriptor_count value only when image_info_size is not zero
The GetImageInfo function of the Firmware Mangement Protocol(FMP) gets called initially to query the size of the image descriptor array that would have to be allocated. During this call, the rest of the function arguments, specifically pointers might be passed as NULL. Do not populate the descriptor_count value before it is known that the call to GetImageInfo has been made with the allocated buffer for the image descriptors. Signed-off-by: Sughosh Ganu Reviewed-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- Changes since V1: None lib/efi_loader/efi_firmware.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index fe4e084106..9cdefab41f 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -130,9 +130,6 @@ static efi_status_t efi_fill_image_desc_array( struct efi_fw_image *fw_array; int i; - fw_array = update_info.images; - *descriptor_count = num_image_type_guids; - total_size = sizeof(*image_info) * num_image_type_guids; if (*image_info_size < total_size) { @@ -142,6 +139,8 @@ static efi_status_t efi_fill_image_desc_array( } *image_info_size = total_size; + fw_array = update_info.images; + *descriptor_count = num_image_type_guids; *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; *descriptor_size = sizeof(*image_info); *package_version = 0x; /* not supported */ -- 2.25.1
[PATCH v2 0/4] EFI: Miscellaneous capsule update fixes
The following set of patches fix separate issues relating to the capsule update code. The first patch moves the setting of the descriptor_count parameter to the GetImageInfo function after assertion of a non zero image descriptor buffer. The second patch enables capsule update to proceed even when the OsIndications variable is not set with EFI_IGNORE_OSINDICATIONS config enabled. The third patch updates the capsule update documentation to highlight the 64 bit value of OsIndications that needs to be set. The fourth patch defines a common function for the GetImageInfo functionality for both FIT and raw image FMP instances. Sughosh Ganu (4): EFI: Populate descriptor_count value only when image_info_size is not zero EFI: Do not consider OsIndications variable if CONFIG_EFI_IGNORE_OSINDICATIONS is enabled EFI: Update the documentation to reflect the correct value of OsIndications EFI: FMP: Use a common GetImageInfo function for FIT and raw images doc/develop/uefi/uefi.rst | 2 +- lib/efi_loader/efi_capsule.c | 7 +-- lib/efi_loader/efi_firmware.c | 85 +++ 3 files changed, 21 insertions(+), 73 deletions(-) -- 2.25.1
Re: [PATCH 2/3] EFI: Do not read OsIndications variable if EFI_IGNORE_OSINDICATIONS is enabled
hi Heinrich, On Wed, 1 Jun 2022 at 11:33, Heinrich Schuchardt wrote: > > On 5/31/22 09:15, Sughosh Ganu wrote: > > The EFI_IGNORE_OSINDICATIONS config symbol was introduced as a > > mechanism to have capsule updates work even on platforms where the > > SetVariable runtime service was not supported. The current logic > > requires the OsIndications variable to have been set to a 64 bit value > > even when the EFI_IGNORE_OSINDICATIONS config is enabled. Move the > > check to see if the config symbol is enabled at the beginning of the > > function. If the config is enabled, return a success code without > > checking for the existence of the variable. > > > > Signed-off-by: Sughosh Ganu > > --- > > lib/efi_loader/efi_capsule.c | 5 +++-- > > 1 file changed, 3 insertions(+), 2 deletions(-) > > > > diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c > > index c76a5f3570..0ea21dc168 100644 > > --- a/lib/efi_loader/efi_capsule.c > > +++ b/lib/efi_loader/efi_capsule.c > > @@ -1062,6 +1062,9 @@ static efi_status_t check_run_capsules(void) > > efi_uintn_t size; > > efi_status_t r; > > > > + if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) > > + return EFI_SUCCESS; > > + > > If CONFIG_EFI_IGNORE_OSINDICATIONS=y it is correct to ignore a missing > OsIndications variable. > > But I think we should stay as close as possible to the UEFI specification: > > If the variable exists and the flag > EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED is set, we should > remove the flag even if CONFIG_EFI_IGNORE_OSINDICATIONS=y. Okay. I get your point. Will make the change to not return EFI_NOT_FOUND when the OsIndications variable is not set with CONFIG_EFI_IGNORE_OSINDICATIONS=y. The subsequent code will clear the EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit if the variable is found irrespective of the value of the above config. > > Please, have a look at the configuration symbols > EFI_CAPSULE_ON_DISK_EARLY and EFI_SETUP_EARLY. > > As block devices now can be added to the UEFI sub-system after > initialization of the same shouldn't we always initialize the sub-system > early. And shouldn't we always consider capsules before distro-boot, > U-Boot menu, or entering the U-Boot shell? I believe that can be done by enabling CONFIG_EFI_CAPSULE_ON_DISK_EARLY. -sughosh > > Best regards > > Heinrich > > > size = sizeof(os_indications); > > r = efi_get_variable_int(u"OsIndications", _global_variable_guid, > >NULL, , _indications, NULL); > > @@ -1082,8 +1085,6 @@ static efi_status_t check_run_capsules(void) > > if (r != EFI_SUCCESS) > > log_err("Setting %ls failed\n", L"OsIndications"); > > return EFI_SUCCESS; > > - } else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) { > > - return EFI_SUCCESS; > > } else { > > return EFI_NOT_FOUND; > > }
Re: efi_firmware_raw_get_image_info and efi_firmware_fit_get_image_info
hello Heinrich, On Wed, 1 Jun 2022 at 11:11, Heinrich Schuchardt wrote: > > Hello Sughosh, > > I can't see any difference between efi_firmware_raw_get_image_info() and > efi_firmware_fit_get_image_info(). Shouldn't we replace them by a single > function to avoid maintaining duplicate code? The two functions can indeed be refactored into a single function. I will add this patch to the miscellaneous capsule fixes series that I posted yesterday. Thanks. -sughosh > > Best regards > > Heinrich
[PATCH 3/3] EFI: Update the documentation to reflect the correct value of OsIndications
The OsIndications is a 64 bit variable, and the current code expects the value of the variable to be 64 bit. Update the documentation to reflect this fact. Signed-off-by: Sughosh Ganu --- doc/develop/uefi/uefi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index 753a4e5e29..941e427093 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -326,7 +326,7 @@ bit in OsIndications variable with .. code-block:: console -=> setenv -e -nv -bs -rt -v OsIndications =0x04 +=> setenv -e -nv -bs -rt -v OsIndications =0x0004 Since U-boot doesn't currently support SetVariable at runtime, its value won't be taken over across the reboot. If this is the case, you can skip -- 2.25.1
[PATCH 2/3] EFI: Do not read OsIndications variable if EFI_IGNORE_OSINDICATIONS is enabled
The EFI_IGNORE_OSINDICATIONS config symbol was introduced as a mechanism to have capsule updates work even on platforms where the SetVariable runtime service was not supported. The current logic requires the OsIndications variable to have been set to a 64 bit value even when the EFI_IGNORE_OSINDICATIONS config is enabled. Move the check to see if the config symbol is enabled at the beginning of the function. If the config is enabled, return a success code without checking for the existence of the variable. Signed-off-by: Sughosh Ganu --- lib/efi_loader/efi_capsule.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index c76a5f3570..0ea21dc168 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -1062,6 +1062,9 @@ static efi_status_t check_run_capsules(void) efi_uintn_t size; efi_status_t r; + if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) + return EFI_SUCCESS; + size = sizeof(os_indications); r = efi_get_variable_int(u"OsIndications", _global_variable_guid, NULL, , _indications, NULL); @@ -1082,8 +1085,6 @@ static efi_status_t check_run_capsules(void) if (r != EFI_SUCCESS) log_err("Setting %ls failed\n", L"OsIndications"); return EFI_SUCCESS; - } else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) { - return EFI_SUCCESS; } else { return EFI_NOT_FOUND; } -- 2.25.1
[PATCH 1/3] EFI: Populate descriptor_count value only when image_info_size is not zero
The GetImageInfo function of the Firmware Mangement Protocol(FMP) gets called initially to query the size of the image descriptor array that would have to be allocated. During this call, the rest of the function arguments, specifically pointers might be passed as NULL. Do not populate the descriptor_count value before it is known that the call to GetImageInfo has been made with the allocated buffer for the image descriptors. Signed-off-by: Sughosh Ganu --- lib/efi_loader/efi_firmware.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 27953fe769..6290ca0190 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -130,9 +130,6 @@ static efi_status_t efi_fill_image_desc_array( struct efi_fw_image *fw_array; int i; - fw_array = update_info.images; - *descriptor_count = num_image_type_guids; - total_size = sizeof(*image_info) * num_image_type_guids; if (*image_info_size < total_size) { @@ -142,6 +139,8 @@ static efi_status_t efi_fill_image_desc_array( } *image_info_size = total_size; + fw_array = update_info.images; + *descriptor_count = num_image_type_guids; *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; *descriptor_size = sizeof(*image_info); *package_version = 0x; /* not supported */ -- 2.25.1
[PATCH 0/3] EFI: Miscellaneous capsule update fixes
The following set of patches fix separate issues relating to the capsule update code. The first patch moves the setting of the descriptor_count parameter to the GetImageInfo function after assertion of a non zero image descriptor buffer. The second patch enables capsule update to proceed even when the OsIndications variable is not set with EFI_IGNORE_OSINDICATIONS config enabled. The third patch updates the capsule update documentation to highlight the 64 bit value of OsIndications that needs to be set. Sughosh Ganu (3): EFI: Populate descriptor_count value only when image_info_size is not zero EFI: Do not read OsIndications variable if EFI_IGNORE_OSINDICATIONS is enabled EFI: Update the documentation to reflect the correct value of OsIndications doc/develop/uefi/uefi.rst | 2 +- lib/efi_loader/efi_capsule.c | 5 +++-- lib/efi_loader/efi_firmware.c | 5 ++--- 3 files changed, 6 insertions(+), 6 deletions(-) -- 2.25.1