[PATCH RFC 2/4] efi: add a helper to generate dynamic UUIDs

Caleb Connolly caleb.connolly at linaro.org
Fri Apr 26 16:19:36 CEST 2024


Introduce a new helper efi_capsule_update_info_gen_ids() which takes
several strings to identify the currently running board as well as a
platform specific salt UUID and uses this data to populate 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.

Generating capsule updates can be done using the same namespace, soc,
model, compatible, and fw_image name strings.

This is behind an additional config option as it depends on V5 UUIDs and
the SHA1 implementation.

Signed-off-by: Caleb Connolly <caleb.connolly at linaro.org>
---
 include/efi_loader.h         | 28 ++++++++++++++++++++++++++++
 lib/efi_loader/Kconfig       | 14 ++++++++++++++
 lib/efi_loader/efi_capsule.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 69442f4e58de..7d6b6ff83229 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -1125,8 +1125,36 @@ struct efi_capsule_update_info {
 };
 
 extern struct efi_capsule_update_info update_info;
 
+#if CONFIG_IS_ENABLED(EFI_CAPSULE_DYNAMIC_UUIDS)
+/**
+ * efi_capsule_update_info_gen_ids - Generate image_type_id UUIDs
+ * for all firmware images based on a platform namespace UUID.
+ *
+ * @namespace: The arch/platform specific namespace salt. This should be
+ * hardcoded per platform and replaced by vendors.
+ * @soc: A string identifying the SoC used on this board.
+ * @model: The model string for the board.
+ * @compatible: The most specific (first) root compatible string.
+ *
+ * This can be called by board code to populate the image_type_id
+ * UUID fields deterministically based on the board's model. Allowing
+ * many boards to be supported without the need for a large hardcoded
+ * array of fw images. This works using v5 UUIDs.
+ */
+int efi_capsule_update_info_gen_ids(efi_guid_t *namespace, const char *soc,
+				    const char *model,
+				    const char *compatible);
+#else
+static inline int efi_capsule_update_info_gen_ids(efi_guid_t *namespace, const char *soc,
+						  const char *model,
+						  const char *compatible)
+{
+	return -ENOSYS;
+}
+#endif
+
 /**
  * Install the ESRT system table.
  *
  * Return:	status code
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 430bb7f0f7dc..dd8fc1b08812 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -235,8 +235,22 @@ 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_DYNAMIC_UUIDS
+	bool "Dynamic UUIDs for capsules"
+	depends on EFI_HAVE_CAPSULE_SUPPORT
+	select UUID_GEN_V5
+	help
+	  Select this option if you want to use dynamically generated v5
+	  UUIDs for your board. To make use of this feature, your board
+	  code should call efi_capsule_update_info_gen_ids() with a seed
+	  UUID to generate the image_type_id field for each fw_image.
+
+	  The CapsuleUpdate payloads are expected to generate matching UUIDs
+	  using the same scheme.
+
+
 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 de0d49ebebda..9ef67d1b4405 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>
@@ -403,8 +404,40 @@ out:
 	return status;
 }
 #endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */
 
+#if CONFIG_IS_ENABLED(EFI_CAPSULE_DYNAMIC_UUIDS)
+int efi_capsule_update_info_gen_ids(efi_guid_t *namespace, const char *soc, const char *model, const char *compatible)
+{
+	int i;
+
+	if (!soc || !model || !compatible) {
+		log_err("%s: soc, model, or compatible not defined\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!update_info.num_images) {
+		log_err("%s: no fw_images, make sure update_info.num_images is set\n", __func__);
+		return -ENODATA;
+	}
+
+	for (i = 0; i < update_info.num_images; i++) {
+		gen_uuid_v5((struct uuid*)namespace,
+			    (struct uuid *)&update_info.images[i].image_type_id,
+			    soc, strlen(soc),
+			    model, strlen(model),
+			    compatible, strlen(compatible),
+			    update_info.images[i].fw_name, u16_strlen(update_info.images[i].fw_name),
+			    NULL);
+
+		log_debug("Image %ls generated UUID %pUs\n", update_info.images[i].fw_name,
+			  &update_info.images[i].image_type_id);
+	}
+
+	return 0;
+}
+#endif
+
 static __maybe_unused bool fwu_empty_capsule(struct efi_capsule_header *capsule)
 {
 	return !guidcmp(&capsule->capsule_guid,
 			&fwu_guid_os_request_fw_revert) ||

-- 
2.44.0



More information about the U-Boot mailing list