Re: [PATCH] test: lib/uuid: Fix endianness for dynamic GUIDs

Heinrich Schuchardt <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
On 8/27/26 15:00, Alexey Charkov wrote:
> If LIB_UUID is enabled on a big-endian board, such as when it is pulled
> in by EFI_PARTITION, its tests will fail due to the dynamic capsule GUIDs
> computed by lib_test_dynamic_uuid() using native endianness for the UTF-16
> image name, instead of little-endian:
> 
>    malta # ut lib lib_test_dynamic_uuid
>    Test: dynamic_uuid: uuid.c
>    test/lib/uuid.c:114, lib_test_dynamic_uuid_case(): expected_uuid = uuid_str: Expected "985f2937-7c2e-5e9a-8a5e-8e063312964b", got "829f5cb0-1a07-5718-8774-4514bda82c39"
>    Test 'dynamic_uuid' failed 1 times
>    Tests run: 1, 2 ms, average: 2 ms, failures: 1
>    exit not allowed from main input shell.
>    malta #
> 
> Add explicit endianness conversion to the test and to other similar
> callers of gen_v5_guid() to make sure they work uniformly regardless of
> the host or target endianness.
> 
> Signed-off-by: Alexey Charkov <[email protected]>

Thank you for reporting that the test fails on big endian systems.

In lib_test_dynamic_uuid() we define define dynamic_uuid_test_data 
test_data[].images as u16 string. On a big endian system the characters 
of the string will not be stored in the same sequence as on a low endian 
system so the UUID generated in gen_v5_guid() is expected to be different.

test_data[].images should contain unique sequences of bytes.

The relevant code was introduced with
26e16a850e64 ("test: lib/uuid: add unit tests for dynamic UUIDs")

With that I don't think that the EFI changes are needed. Anyway UEFI is 
little endian only.

Best regards

Heinrich

> ---
> This was uncovered [1] while adding tests for GPT partition labels on big
> endian boards, which pulls in PARTITION_UUIDS, which in turn pulls in
> LIB_UUID and its tests. Turns out no BE board in CI ever enabled LIB_UUID,
> so this went unnoticed to date.
> 
> The immediate users of this code other than the test suite are EFI capsule
> updates, which is unlikely to be relevant for anything big endian (given
> that UEFI is little endian), but the test suite itself seems to be a good
> reason to get this fixed.
> 
> No functional change on little endian either way.
> 
> [1] https://git.u-boot-project.org/u-boot/contributors/alchark/u-boot/-/pipelines/1101
> ---
>   include/u-boot/uuid.h         |  5 +++++
>   lib/efi_loader/efi_firmware.c | 19 ++++++++++++++++++-
>   test/lib/uuid.c               | 15 ++++++++++++++-
>   tools/mkeficapsule.c          |  3 ++-
>   4 files changed, 39 insertions(+), 3 deletions(-)
> 
> diff --git a/include/u-boot/uuid.h b/include/u-boot/uuid.h
> index 7f8414dc906c..acdf3a85a6cb 100644
> --- a/include/u-boot/uuid.h
> +++ b/include/u-boot/uuid.h
> @@ -149,6 +149,11 @@ struct efi_guid;
>   /**
>    * gen_v5_guid() - generate little endian v5 GUID from namespace and other seed data.
>    *
> + * The seed data is hashed as raw bytes, so any of it that is not a byte string
> + * has to be supplied in a fixed byte order for the result to be reproducible.
> + * UTF-16 seed data, such as a firmware image name, must therefore be passed
> + * little-endian, which is the byte order the UEFI specification uses for it.
> + *
>    * @namespace:   pointer to UUID namespace salt
>    * @guid:        pointer to allocated GUID output
>    * @...:         NULL terminated list of seed data as pairs of pointers
> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> index b41969c70fde..7f3b2da3ef89 100644
> --- a/lib/efi_loader/efi_firmware.c
> +++ b/lib/efi_loader/efi_firmware.c
> @@ -279,15 +279,32 @@ static efi_status_t efi_gen_capsule_guids(void)
>   	}
>   
>   	for (i = 0; i < update_info.num_images; i++) {
> +		size_t len, j;
> +		u16 *name_le;
> +
>   		if (!fw_array[i].fw_name) {
>   			log_err("fw_name is not defined. Not generating capsule GUIDs\n");
>   			return EFI_INVALID_PARAMETER;
>   		}
> +
> +		/*
> +		 * The name is hashed as UTF-16LE, so that a big-endian board
> +		 * arrives at the same GUID as mkeficapsule running on a
> +		 * little-endian build host.
> +		 */
> +		len = u16_strlen(fw_array[i].fw_name);
> +		name_le = calloc(len, sizeof(*name_le));
> +		if (!name_le)
> +			return EFI_OUT_OF_RESOURCES;
> +		for (j = 0; j < len; j++)
> +			name_le[j] = cpu_to_le16(fw_array[i].fw_name[j]);
> +
>   		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),
> +			    name_le, len * sizeof(*name_le),
>   			    NULL);
> +		free(name_le);
>   
>   		log_debug("Image %ls UUID %pUl\n", fw_array[i].fw_name,
>   			  &fw_array[i].image_type_id);
> diff --git a/test/lib/uuid.c b/test/lib/uuid.c
> index d00e9563a472..1c66021af3ed 100644
> --- a/test/lib/uuid.c
> +++ b/test/lib/uuid.c
> @@ -10,6 +10,7 @@
>   
>   #include <charset.h>
>   #include <u-boot/uuid.h>
> +#include <asm/byteorder.h>
>   #include <test/lib.h>
>   #include <test/test.h>
>   #include <test/ut.h>
> @@ -102,12 +103,24 @@ static int lib_test_dynamic_uuid_case(struct unit_test_state *uts,
>   	for (j = 0; data->images[j]; j++) {
>   		const char *expected_uuid = data->expected_uuids[j];
>   		const u16 *image = data->images[j];
> +		u16 image_le[64];
>   		efi_guid_t uuid;
>   		char uuid_str[37];
> +		size_t len, k;
> +
> +		/*
> +		 * u"..." is native-endian, but the name is hashed as UTF-16LE
> +		 * so that the GUID does not depend on the endianness of the
> +		 * board or of the host running mkeficapsule.
> +		 */
> +		len = u16_strlen(image);
> +		ut_assert(len <= ARRAY_SIZE(image_le));
> +		for (k = 0; k < len; k++)
> +			image_le[k] = cpu_to_le16(image[k]);
>   
>   		gen_v5_guid(&namespace, &uuid,
>   			    data->compatible, strlen(data->compatible),
> -			    image, u16_strlen(image) * sizeof(uint16_t),
> +			    image_le, len * sizeof(*image_le),
>   			    NULL);
>   		uuid_bin_to_str((unsigned char *)&uuid, uuid_str, UUID_STR_FORMAT_GUID);
>   
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index ec640c57e8a5..55a58f07d56e 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -1004,8 +1004,9 @@ static int genguid(int argc, char **argv)
>   			return -1;
>   		}
>   
> +		/* The name is hashed as UTF-16LE, whatever this host is */
>   		for (int i = 0; i < namelen; i++)
> -			fw_image[i] = (uint16_t)argv[idx][i];
> +			fw_image[i] = cpu_to_le16((uint16_t)argv[idx][i]);
>   
>   		gen_v5_guid((struct uuid *)&namespace, &image_type_id,
>   			    compatible, strlen(compatible),
> 
> ---
> base-commit: 964ad5b5c91b7be56e443e899d7f873e6aa8c9fc
> change-id: 20260827-uuid-be-56657e7aa80e
> 
> Best regards,
> --
> Alexey Charkov <[email protected]>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.