summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2022-01-04 14:31:15 +0100
committerMichael Brown2022-01-04 15:03:12 +0100
commitf43c2fd69749bb9a44f2a3ab61b6735938432b52 (patch)
treeb5afddef6c6f701312dda21aa4732e9c0253d587
parent[efi] Disable EFI watchdog timer when shutting down to boot an OS (diff)
downloadipxe-f43c2fd69749bb9a44f2a3ab61b6735938432b52.tar.gz
ipxe-f43c2fd69749bb9a44f2a3ab61b6735938432b52.tar.xz
ipxe-f43c2fd69749bb9a44f2a3ab61b6735938432b52.zip
[settings] Support formatting UUIDs as little-endian GUIDs
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>
-rw-r--r--src/core/settings.c23
-rw-r--r--src/include/ipxe/settings.h1
-rw-r--r--src/interface/smbios/smbios_settings.c3
-rw-r--r--src/tests/settings_test.c10
4 files changed, 31 insertions, 6 deletions
diff --git a/src/core/settings.c b/src/core/settings.c
index 430cdc84..fcdf98d2 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -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
*
diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h
index f463e667..e042b975 100644
--- a/src/include/ipxe/settings.h
+++ b/src/include/ipxe/settings.h
@@ -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;
diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c
index 2d571f2e..ec31b43f 100644
--- a/src/interface/smbios/smbios_settings.c
+++ b/src/interface/smbios/smbios_settings.c
@@ -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" );
diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c
index 828901b0..5da7eb00 100644
--- a/src/tests/settings_test.c
+++ b/src/tests/settings_test.c
@@ -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,