]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[settings] Support formatting UUIDs as little-endian GUIDs 545/head
authorMichael Brown <mcb30@ipxe.org>
Tue, 4 Jan 2022 13:31:15 +0000 (13:31 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 4 Jan 2022 14:03:12 +0000 (14:03 +0000)
The RFC4122 specification defines UUIDs as being in network byte
order, but an unfortunately significant amount of (mostly Microsoft)
software treats them as having the first three fields in little-endian
byte order.

In an ideal world, any server-side software that compares UUIDs for
equality would perform an endian-insensitive comparison (analogous to
comparing strings for equality using a case-insensitive comparison),
and would therefore not care about byte order differences.

Define a setting type name ":guid" to allow a UUID setting to be
formatted in little-endian order, to simplify interoperability with
server-side software that expects such a formatting.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/settings.c
src/include/ipxe/settings.h
src/interface/smbios/smbios_settings.c
src/tests/settings_test.c

index 430cdc84bc5508be87059a672d041ab6ce5930cb..fcdf98d2b71618e7fa456d236252287731a5bf85 100644 (file)
@@ -2199,7 +2199,7 @@ const struct setting_type setting_type_base64 __setting_type = {
 };
 
 /**
- * Format UUID setting value
+ * Format UUID/GUID setting value
  *
  * @v type             Setting type
  * @v raw              Raw setting value
@@ -2208,17 +2208,24 @@ const struct setting_type setting_type_base64 __setting_type = {
  * @v len              Length of buffer
  * @ret len            Length of formatted value, or negative error
  */
-static int format_uuid_setting ( const struct setting_type *type __unused,
+static int format_uuid_setting ( const struct setting_type *type,
                                 const void *raw, size_t raw_len, char *buf,
                                 size_t len ) {
-       const union uuid *uuid = raw;
+       union uuid uuid;
 
        /* Range check */
-       if ( raw_len != sizeof ( *uuid ) )
+       if ( raw_len != sizeof ( uuid ) )
                return -ERANGE;
 
+       /* Copy value */
+       memcpy ( &uuid, raw, sizeof ( uuid ) );
+
+       /* Mangle GUID byte ordering */
+       if ( type == &setting_type_guid )
+               uuid_mangle ( &uuid );
+
        /* Format value */
-       return snprintf ( buf, len, "%s", uuid_ntoa ( uuid ) );
+       return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
 }
 
 /** UUID setting type */
@@ -2227,6 +2234,12 @@ const struct setting_type setting_type_uuid __setting_type = {
        .format = format_uuid_setting,
 };
 
+/** GUID setting type */
+const struct setting_type setting_type_guid __setting_type = {
+       .name = "guid",
+       .format = format_uuid_setting,
+};
+
 /**
  * Format PCI bus:dev.fn setting value
  *
index f463e6674dc34f0961eabf45081f0829638382dc..e042b97580db6f8bfbec96811653390085e81b35 100644 (file)
@@ -426,6 +426,7 @@ extern const struct setting_type setting_type_hexhyp __setting_type;
 extern const struct setting_type setting_type_hexraw __setting_type;
 extern const struct setting_type setting_type_base64 __setting_type;
 extern const struct setting_type setting_type_uuid __setting_type;
+extern const struct setting_type setting_type_guid __setting_type;
 extern const struct setting_type setting_type_busdevfn __setting_type;
 extern const struct setting_type setting_type_dnssl __setting_type;
 
index 2d571f2e44e6109919099154385645b4df90eb3f..ec31b43f2c32dc51280fc28d31c7d9dc2e791a0c 100644 (file)
@@ -140,7 +140,8 @@ static int smbios_fetch ( struct settings *settings __unused,
                 * is 2.6 or higher; we match this behaviour.
                 */
                raw = &buf[tag_offset];
-               if ( ( setting->type == &setting_type_uuid ) &&
+               if ( ( ( setting->type == &setting_type_uuid ) ||
+                      ( setting->type == &setting_type_guid ) ) &&
                     ( tag_len == sizeof ( uuid ) ) &&
                     ( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) {
                        DBG ( "SMBIOS detected mangled UUID\n" );
index 828901b0665d9854236ef2de7e9277a08d6b0509..5da7eb00871800e9636e0ef4721ea3477276a078 100644 (file)
@@ -250,6 +250,12 @@ static struct setting test_uuid_setting = {
        .type = &setting_type_uuid,
 };
 
+/** Test GUID setting type */
+static struct setting test_guid_setting = {
+       .name = "test_guid",
+       .type = &setting_type_guid,
+};
+
 /** Test PCI bus:dev.fn setting type */
 static struct setting test_busdevfn_setting = {
        .name = "test_busdevfn",
@@ -419,6 +425,10 @@ static void settings_test_exec ( void ) {
                    RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8,
                          0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ),
                    "1a6a749d-0eda-461a-a87a-7cfe4fca4a57" );
+       fetchf_ok ( &test_settings, &test_guid_setting,
+                   RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8,
+                         0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ),
+                   "9d746a1a-da0e-1a46-a87a-7cfe4fca4a57" );
 
        /* "busdevfn" setting type (no store capability) */
        fetchf_ok ( &test_settings, &test_busdevfn_setting,