Message ID | 20240809-b4-dynamic-uuid-v7-3-8c44ab1f06a5@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | efi: CapsuleUpdate: support for dynamic UUIDs | expand |
On Fri, 9 Aug 2024 at 03:56, Caleb Connolly <caleb.connolly@linaro.org> wrote: > > Introduce a new helper efi_capsule_update_info_gen_ids() which populates > the capsule update fw images image_type_id field. This allows for > determinstic UUIDs to be used that can scale to a large number of > different boards and board variants without the need to maintain a big > list. > > We call this from efi_fill_image_desc_array() to populate the UUIDs > lazily on-demand. > > Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org> > --- > lib/efi_loader/Kconfig | 12 ++++++++++ > lib/efi_loader/efi_capsule.c | 1 + > lib/efi_loader/efi_firmware.c | 55 ++++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 67 insertions(+), 1 deletion(-) > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > index 1179c31bb136..85a31113fcf0 100644 > --- a/lib/efi_loader/Kconfig > +++ b/lib/efi_loader/Kconfig > @@ -236,8 +236,20 @@ config EFI_CAPSULE_ON_DISK_EARLY > If this option is enabled, capsules will be enforced to be > executed as part of U-Boot initialisation so that they will > surely take place whatever is set to distro_bootcmd. > > +config EFI_CAPSULE_NAMESPACE_GUID > + string "Namespace for dynamic capsule GUIDs" > + # v4 UUID as a default for upstream U-Boot boards > + default "8c9f137e-91dc-427b-b2d6-b420faebaf2a" > + depends on EFI_HAVE_CAPSULE_SUPPORT > + help > + Define the namespace or "salt" GUID used to generate the per-image > + GUIDs. This should be a GUID in the standard 8-4-4-4-12 format. > + > + Device vendors are expected to generate their own namespace GUID > + to avoid conflicts with upstream/community images. > + > config EFI_CAPSULE_FIRMWARE > bool > > config EFI_CAPSULE_FIRMWARE_MANAGEMENT > diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c > index 635088f25a13..f3a2388506cc 100644 > --- a/lib/efi_loader/efi_capsule.c > +++ b/lib/efi_loader/efi_capsule.c > @@ -19,8 +19,9 @@ > #include <mapmem.h> > #include <sort.h> > #include <sysreset.h> > #include <asm/global_data.h> > +#include <uuid.h> > > #include <crypto/pkcs7.h> > #include <crypto/pkcs7_parser.h> > #include <linux/err.h> > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c > index ba5aba098c0f..c0240e95cf13 100644 > --- a/lib/efi_loader/efi_firmware.c > +++ b/lib/efi_loader/efi_firmware.c > @@ -244,8 +244,57 @@ void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_ > > free(var_state); > } > > +/** > + * efi_gen_capsule_guids - generate GUIDs for the images > + * > + * Generate the image_type_id for each image in the update_info.images array > + * using the first compatible from the device tree and a salt > + * UUID defined at build time. > + * > + * Returns: status code > + */ > +static efi_status_t efi_gen_capsule_guids(void) > +{ > + int ret, i; > + struct uuid namespace; > + const char *compatible; /* Full array including null bytes */ > + struct efi_fw_image *fw_array; > + > + fw_array = update_info.images; > + /* Check if we need to run (there are images and we didn't already generate their IDs) */ > + if (!update_info.num_images || > + memchr_inv(&fw_array[0].image_type_id, 0, sizeof(fw_array[0].image_type_id))) > + return EFI_SUCCESS; > + > + ret = uuid_str_to_bin(CONFIG_EFI_CAPSULE_NAMESPACE_GUID, > + (unsigned char *)&namespace, UUID_STR_FORMAT_GUID); > + if (ret) { > + log_debug("%s: EFI_CAPSULE_NAMESPACE_GUID is invalid: %d\n", __func__, ret); > + return EFI_INVALID_PARAMETER; > + } > + > + compatible = ofnode_read_string(ofnode_root(), "compatible"); > + if (!compatible) { > + log_debug("%s: model or compatible not defined\n", __func__); > + return EFI_INVALID_PARAMETER; > + } > + > + for (i = 0; i < update_info.num_images; i++) { > + gen_v5_guid(&namespace, > + &fw_array[i].image_type_id, > + compatible, strlen(compatible), > + fw_array[i].fw_name, u16_strlen(fw_array[i].fw_name) * sizeof(uint16_t), > + NULL); > + > + log_debug("Image %ls UUID %pUl\n", fw_array[i].fw_name, > + &fw_array[i].image_type_id); > + } > + > + return EFI_SUCCESS; > +} > + > /** > * efi_fill_image_desc_array - populate image descriptor array > * @image_info_size: Size of @image_info > * @image_info: Image information > @@ -271,9 +320,9 @@ static efi_status_t efi_fill_image_desc_array( > u16 **package_version_name) > { > size_t total_size; > struct efi_fw_image *fw_array; > - int i; > + int i, ret; > > total_size = sizeof(*image_info) * update_info.num_images; > > if (*image_info_size < total_size) { > @@ -282,8 +331,12 @@ static efi_status_t efi_fill_image_desc_array( > return EFI_BUFFER_TOO_SMALL; > } > *image_info_size = total_size; > > + ret = efi_gen_capsule_guids(); ret should be efi_status_t > + if (ret != EFI_SUCCESS) > + return ret; > + > fw_array = update_info.images; > *descriptor_count = update_info.num_images; > *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; > *descriptor_size = sizeof(*image_info); > > -- > 2.46.0 > with the fix above Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 1179c31bb136..85a31113fcf0 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -236,8 +236,20 @@ config EFI_CAPSULE_ON_DISK_EARLY If this option is enabled, capsules will be enforced to be executed as part of U-Boot initialisation so that they will surely take place whatever is set to distro_bootcmd. +config EFI_CAPSULE_NAMESPACE_GUID + string "Namespace for dynamic capsule GUIDs" + # v4 UUID as a default for upstream U-Boot boards + default "8c9f137e-91dc-427b-b2d6-b420faebaf2a" + depends on EFI_HAVE_CAPSULE_SUPPORT + help + Define the namespace or "salt" GUID used to generate the per-image + GUIDs. This should be a GUID in the standard 8-4-4-4-12 format. + + Device vendors are expected to generate their own namespace GUID + to avoid conflicts with upstream/community images. + config EFI_CAPSULE_FIRMWARE bool config EFI_CAPSULE_FIRMWARE_MANAGEMENT diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 635088f25a13..f3a2388506cc 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -19,8 +19,9 @@ #include <mapmem.h> #include <sort.h> #include <sysreset.h> #include <asm/global_data.h> +#include <uuid.h> #include <crypto/pkcs7.h> #include <crypto/pkcs7_parser.h> #include <linux/err.h> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index ba5aba098c0f..c0240e95cf13 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -244,8 +244,57 @@ void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_ free(var_state); } +/** + * efi_gen_capsule_guids - generate GUIDs for the images + * + * Generate the image_type_id for each image in the update_info.images array + * using the first compatible from the device tree and a salt + * UUID defined at build time. + * + * Returns: status code + */ +static efi_status_t efi_gen_capsule_guids(void) +{ + int ret, i; + struct uuid namespace; + const char *compatible; /* Full array including null bytes */ + struct efi_fw_image *fw_array; + + fw_array = update_info.images; + /* Check if we need to run (there are images and we didn't already generate their IDs) */ + if (!update_info.num_images || + memchr_inv(&fw_array[0].image_type_id, 0, sizeof(fw_array[0].image_type_id))) + return EFI_SUCCESS; + + ret = uuid_str_to_bin(CONFIG_EFI_CAPSULE_NAMESPACE_GUID, + (unsigned char *)&namespace, UUID_STR_FORMAT_GUID); + if (ret) { + log_debug("%s: EFI_CAPSULE_NAMESPACE_GUID is invalid: %d\n", __func__, ret); + return EFI_INVALID_PARAMETER; + } + + compatible = ofnode_read_string(ofnode_root(), "compatible"); + if (!compatible) { + log_debug("%s: model or compatible not defined\n", __func__); + return EFI_INVALID_PARAMETER; + } + + for (i = 0; i < update_info.num_images; i++) { + gen_v5_guid(&namespace, + &fw_array[i].image_type_id, + compatible, strlen(compatible), + fw_array[i].fw_name, u16_strlen(fw_array[i].fw_name) * sizeof(uint16_t), + NULL); + + log_debug("Image %ls UUID %pUl\n", fw_array[i].fw_name, + &fw_array[i].image_type_id); + } + + return EFI_SUCCESS; +} + /** * efi_fill_image_desc_array - populate image descriptor array * @image_info_size: Size of @image_info * @image_info: Image information @@ -271,9 +320,9 @@ static efi_status_t efi_fill_image_desc_array( u16 **package_version_name) { size_t total_size; struct efi_fw_image *fw_array; - int i; + int i, ret; total_size = sizeof(*image_info) * update_info.num_images; if (*image_info_size < total_size) { @@ -282,8 +331,12 @@ static efi_status_t efi_fill_image_desc_array( return EFI_BUFFER_TOO_SMALL; } *image_info_size = total_size; + ret = efi_gen_capsule_guids(); + if (ret != EFI_SUCCESS) + return ret; + fw_array = update_info.images; *descriptor_count = update_info.num_images; *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; *descriptor_size = sizeof(*image_info);
Introduce a new helper efi_capsule_update_info_gen_ids() which populates the capsule update fw images image_type_id field. This allows for determinstic UUIDs to be used that can scale to a large number of different boards and board variants without the need to maintain a big list. We call this from efi_fill_image_desc_array() to populate the UUIDs lazily on-demand. Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org> --- lib/efi_loader/Kconfig | 12 ++++++++++ lib/efi_loader/efi_capsule.c | 1 + lib/efi_loader/efi_firmware.c | 55 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-)