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

Alexey Charkov <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
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 #

The image names come from u"" literals, which the compiler lays out in
the endianness of the target, while the GUIDs they are checked against
were computed little-endian, as the UEFI specification requires.

Spell the names out as UTF-16LE byte strings instead, so that the test
data no longer depends on how the target stores a u16 and nothing has to
be converted at run time. Measure them by scanning for a pair of null
bytes: that comes out the same either way round, and unlike walking the
string as u16 it assumes nothing about the alignment of a string literal,
which m68k for one does not guarantee.

Other callers of gen_v5_guid() are EFI update capsule code, which only
ever runs on little endian systems (as UEFI is little endian), so keep
them as they are.

Signed-off-by: Alexey Charkov <[email protected]>
---
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.

No functional change on little endian.

[1] https://git.u-boot-project.org/u-boot/contributors/alchark/u-boot/-/pipelines/1101
---
Changes in v2:
- Dropped the EFI changes, keeping only the test expectations update for
  big endian systems (thanks Heinrich). Keep the hunk updating the
  kerneldoc to help others avoid tripping over this in the future.
- Dropped the runtime endianness conversion loop and instead store the
  seed strings as explicitly spelled out UTF-16LE bytes in a plain char *
  string (thanks Heinrich). The length function also had to be replaced,
  because string literals are not guaranteed to be halfword aligned
- Link to v1: https://patch.msgid.link/[email protected]

To: Casey Connolly <[email protected]>
To: Ilias Apalodimas <[email protected]>
To: [email protected]
Cc: Tom Rini <[email protected]>
Cc: Abdellatif El Khlifi <[email protected]>
Cc: Alexey Charkov <[email protected]>
---
 include/u-boot/uuid.h |  5 +++++
 test/lib/uuid.c       | 37 +++++++++++++++++++++++++++++--------
 2 files changed, 34 insertions(+), 8 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/test/lib/uuid.c b/test/lib/uuid.c
index d00e9563a472..f958897dd7b5 100644
--- a/test/lib/uuid.c
+++ b/test/lib/uuid.c
@@ -8,7 +8,6 @@
  *   Abdellatif El Khlifi <[email protected]>
  */
 
-#include <charset.h>
 #include <u-boot/uuid.h>
 #include <test/lib.h>
 #include <test/test.h>
@@ -86,10 +85,31 @@ LIB_TEST(lib_test_uuid_bits, 0);
 
 struct dynamic_uuid_test_data {
 	const char *compatible;
-	const u16 *images[4];
+	const char *images[4];
 	const char *expected_uuids[4];
 };
 
+/**
+ * bytes_to_null_pair() - offset of a pair of null bytes within a string
+ *
+ * Steps through the string two bytes at a time, looking for a null character,
+ * which in UTF-16 is a pair of null bytes. The string is walked byte-wise
+ * rather than as u16, since a string literal carries no alignment guarantee
+ * and some architectures cannot load a halfword from an odd address.
+ *
+ * @str:	UTF-16LE string, terminated by a null character
+ * Return:	number of bytes preceding the terminator
+ */
+static size_t bytes_to_null_pair(const char *str)
+{
+	size_t len = 0;
+
+	while (str[len] || str[len + 1])
+		len += 2;
+
+	return len;
+}
+
 static int lib_test_dynamic_uuid_case(struct unit_test_state *uts,
 				      const struct dynamic_uuid_test_data *data)
 {
@@ -101,13 +121,13 @@ 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];
+		const char *image = data->images[j];
 		efi_guid_t uuid;
 		char uuid_str[37];
 
 		gen_v5_guid(&namespace, &uuid,
 			    data->compatible, strlen(data->compatible),
-			    image, u16_strlen(image) * sizeof(uint16_t),
+			    image, bytes_to_null_pair(image),
 			    NULL);
 		uuid_bin_to_str((unsigned char *)&uuid, uuid_str, UUID_STR_FORMAT_GUID);
 
@@ -124,9 +144,10 @@ static int lib_test_dynamic_uuid(struct unit_test_state *uts)
 		{
 			.compatible = "sandbox",
 			.images = {
-				u"SANDBOX-UBOOT",
-				u"SANDBOX-UBOOT-ENV",
-				u"SANDBOX-FIT",
+				/* Forced UTF-16LE to keep these endianness agnostic */
+				"S\0A\0N\0D\0B\0O\0X\0-\0U\0B\0O\0O\0T\0\0",
+				"S\0A\0N\0D\0B\0O\0X\0-\0U\0B\0O\0O\0T\0-\0E\0N\0V\0\0",
+				"S\0A\0N\0D\0B\0O\0X\0-\0F\0I\0T\0\0",
 				NULL,
 			},
 			.expected_uuids = {
@@ -139,7 +160,7 @@ static int lib_test_dynamic_uuid(struct unit_test_state *uts)
 		{
 			.compatible = "qcom,qrb4210-rb2",
 			.images = {
-				u"QUALCOMM-UBOOT",
+				"Q\0U\0A\0L\0C\0O\0M\0M\0-\0U\0B\0O\0O\0T\0\0",
 				NULL,
 			},
 			.expected_uuids = {

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