Sfoglia il codice sorgente

[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>
tags/v1.20.1
Michael Brown 11 anni fa
parent
commit
9e896d0eea
1 ha cambiato i file con 33 aggiunte e 9 eliminazioni
  1. 33
    9
      src/interface/smbios/smbios_settings.c

+ 33
- 9
src/interface/smbios/smbios_settings.c Vedi File

@@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
22 22
 #include <stdint.h>
23 23
 #include <string.h>
24 24
 #include <errno.h>
25
+#include <byteswap.h>
25 26
 #include <ipxe/settings.h>
26 27
 #include <ipxe/init.h>
27 28
 #include <ipxe/uuid.h>
@@ -112,14 +113,16 @@ static int smbios_fetch ( struct settings *settings __unused,
112 113
 
113 114
 	{
114 115
 		uint8_t buf[structure.header.len];
116
+		const void *raw;
117
+		union uuid uuid;
115 118
 
116 119
 		/* Read SMBIOS structure */
117 120
 		if ( ( rc = read_smbios_structure ( &structure, buf,
118 121
 						    sizeof ( buf ) ) ) != 0 )
119 122
 			return rc;
120 123
 
124
+		/* A tag length of zero indicates a string */
121 125
 		if ( tag_len == 0 ) {
122
-			/* String */
123 126
 			if ( ( rc = read_smbios_string ( &structure,
124 127
 							 buf[tag_offset],
125 128
 							 data, len ) ) < 0 ) {
@@ -128,15 +131,36 @@ static int smbios_fetch ( struct settings *settings __unused,
128 131
 			if ( ! setting->type )
129 132
 				setting->type = &setting_type_string;
130 133
 			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;
139 134
 		}
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;
140 164
 	}
141 165
 }
142 166
 

Loading…
Annulla
Salva