Skip to content

Commit 9e896d0

Browse files
committed
[smbios] Mangle UUIDs for SMBIOS version 2.6 and newer
iPXE treats UUIDs as being in network byte order (big-endian). The SMBIOS specification version 2.6 states that UUIDs are stored with little-endian values in the first three fields; earlier versions did not specify an endianness. This results in some inconsistency between the BIOS, vendor PXE, iPXE, and operating system interpretations of the SMBIOS UUID. dmidecode assumes that the byte order is little-endian if and only if the SMBIOS version is 2.6 or higher. Choose to match this behaviour. Reported-by: Matthew Helton <mwhelton@gmail.com> Reported-by: Alexandru Bordei <alexandru.bordei@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent 4f742bc commit 9e896d0

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

src/interface/smbios/smbios_settings.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
2222
#include <stdint.h>
2323
#include <string.h>
2424
#include <errno.h>
25+
#include <byteswap.h>
2526
#include <ipxe/settings.h>
2627
#include <ipxe/init.h>
2728
#include <ipxe/uuid.h>
@@ -112,14 +113,16 @@ static int smbios_fetch ( struct settings *settings __unused,
112113

113114
{
114115
uint8_t buf[structure.header.len];
116+
const void *raw;
117+
union uuid uuid;
115118

116119
/* Read SMBIOS structure */
117120
if ( ( rc = read_smbios_structure ( &structure, buf,
118121
sizeof ( buf ) ) ) != 0 )
119122
return rc;
120123

124+
/* A tag length of zero indicates a string */
121125
if ( tag_len == 0 ) {
122-
/* String */
123126
if ( ( rc = read_smbios_string ( &structure,
124127
buf[tag_offset],
125128
data, len ) ) < 0 ) {
@@ -128,15 +131,36 @@ static int smbios_fetch ( struct settings *settings __unused,
128131
if ( ! setting->type )
129132
setting->type = &setting_type_string;
130133
return rc;
131-
} else {
132-
/* Raw data */
133-
if ( len > tag_len )
134-
len = tag_len;
135-
memcpy ( data, &buf[tag_offset], len );
136-
if ( ! setting->type )
137-
setting->type = &setting_type_hex;
138-
return tag_len;
139134
}
135+
136+
/* Mangle UUIDs if necessary. iPXE treats UUIDs as
137+
* being in network byte order (big-endian). SMBIOS
138+
* specification version 2.6 states that UUIDs are
139+
* stored with little-endian values in the first three
140+
* fields; earlier versions did not specify an
141+
* endianness. dmidecode assumes that the byte order
142+
* is little-endian if and only if the SMBIOS version
143+
* is 2.6 or higher; we match this behaviour.
144+
*/
145+
raw = &buf[tag_offset];
146+
if ( ( setting->type == &setting_type_uuid ) &&
147+
( tag_len == sizeof ( uuid ) ) &&
148+
( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) {
149+
DBG ( "SMBIOS detected mangled UUID\n" );
150+
memcpy ( &uuid, &buf[tag_offset], sizeof ( uuid ) );
151+
__bswap_32s ( &uuid.canonical.a );
152+
__bswap_16s ( &uuid.canonical.b );
153+
__bswap_16s ( &uuid.canonical.c );
154+
raw = &uuid;
155+
}
156+
157+
/* Return data */
158+
if ( len > tag_len )
159+
len = tag_len;
160+
memcpy ( data, raw, len );
161+
if ( ! setting->type )
162+
setting->type = &setting_type_hex;
163+
return tag_len;
140164
}
141165
}
142166

0 commit comments

Comments
 (0)