Procházet zdrojové kódy

[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 před 11 roky
rodič
revize
9e896d0eea
1 změnil soubory, kde provedl 33 přidání a 9 odebrání
  1. 33
    9
      src/interface/smbios/smbios_settings.c

+ 33
- 9
src/interface/smbios/smbios_settings.c Zobrazit soubor

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

Načítá se…
Zrušit
Uložit