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]> >