|
@@ -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
|
|