efi: add a helper to generate dynamic UUIDs
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.
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index ab961a8..e58b882 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -272,6 +272,18 @@
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
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 635088f..f3a2388 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -20,6 +20,7 @@
#include <sort.h>
#include <sysreset.h>
#include <asm/global_data.h>
+#include <uuid.h>
#include <crypto/pkcs7.h>
#include <crypto/pkcs7_parser.h>
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index ba5aba0..6650c2b 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -246,6 +246,55 @@
}
/**
+ * 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
@@ -272,7 +321,7 @@
{
size_t total_size;
struct efi_fw_image *fw_array;
- int i;
+ int i, ret;
total_size = sizeof(*image_info) * update_info.num_images;
@@ -283,6 +332,10 @@
}
*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;