1 | /*␊ |
2 | * A very simple SMBIOS Table decoder, part of the Chameleon Boot Loader Project␊ |
3 | *␊ |
4 | * Copyright 2010 by Islam M. Ahmed Zaid. All rights reserved.␊ |
5 | *␊ |
6 | */␊ |
7 | ␊ |
8 | #include "libsaio.h"␊ |
9 | #include "mysmbios.h"␊ |
10 | ␊ |
11 | #ifndef DEBUG_SMBIOS␊ |
12 | #define DEBUG_SMBIOS 0␊ |
13 | #endif␊ |
14 | ␊ |
15 | #if DEBUG_SMBIOS␊ |
16 | #define DBG(x...)␉printf(x)␊ |
17 | #define DBGSMBIOS(x,y)␉if(y) printf(x,y)␊ |
18 | ␊ |
19 | #else␊ |
20 | #define DBG(x...)␉msglog(x)␊ |
21 | #define DBGSMBIOS(x,y)␉if(y) msglog(x,y)␊ |
22 | ␊ |
23 | #endif␊ |
24 | ␊ |
25 | ␊ |
26 | static SMBWord minorVersion;␊ |
27 | ␊ |
28 | static void decodeBIOSInformation(SMBBIOSInformation *structHeader);␊ |
29 | static void decodeSystemInformation(SMBSystemInformation *structHeader);␊ |
30 | static void decodeBaseBoard(SMBBaseBoard *structHeader);␊ |
31 | static void decodeSystemEnclosure(SMBSystemEnclosure *structHeader);␊ |
32 | static void decodeProcessorInformation(SMBProcessorInformation *structHeader);␊ |
33 | static void decodeMemoryDevice(SMBMemoryDevice *structHeader);␊ |
34 | static void decodeOemProcessorType(SMBOemProcessorType *structHeader);␊ |
35 | static void decodeOemProcessorBusSpeed(SMBOemProcessorBusSpeed *structHeader);␊ |
36 | ␊ |
37 | static const char *␊ |
38 | SMBMemoryDeviceTypes[] =␊ |
39 | {␊ |
40 | "RAM", /* 00h Undefined */␊ |
41 | "RAM", /* 01h Other */␊ |
42 | "RAM", /* 02h Unknown */␊ |
43 | "DRAM", /* 03h DRAM */␊ |
44 | "EDRAM", /* 04h EDRAM */␊ |
45 | "VRAM", /* 05h VRAM */␊ |
46 | "SRAM", /* 06h SRAM */␊ |
47 | "RAM", /* 07h RAM */␊ |
48 | "ROM", /* 08h ROM */␊ |
49 | "FLASH", /* 09h FLASH */␊ |
50 | "EEPROM", /* 0Ah EEPROM */␊ |
51 | "FEPROM", /* 0Bh FEPROM */␊ |
52 | "EPROM", /* 0Ch EPROM */␊ |
53 | "CDRAM", /* 0Dh CDRAM */␊ |
54 | "3DRAM", /* 0Eh 3DRAM */␊ |
55 | "SDRAM", /* 0Fh SDRAM */␊ |
56 | "SGRAM", /* 10h SGRAM */␊ |
57 | "RDRAM", /* 11h RDRAM */␊ |
58 | "DDR SDRAM", /* 12h DDR */␊ |
59 | "DDR2 SDRAM", /* 13h DDR2 */␊ |
60 | "DDR2 FB-DIMM", /* 14h DDR2 FB-DIMM */␊ |
61 | "RAM",␉␉␉/* 15h unused */␊ |
62 | "RAM",␉␉␉/* 16h unused */␊ |
63 | "RAM",␉␉␉/* 17h unused */␊ |
64 | "DDR3",␉␉␉/* 18h DDR3, chosen in [5776134] */␊ |
65 | };␊ |
66 | ␊ |
67 | //-------------------------------------------------------------------------------------------------------------------------␊ |
68 | // BIOSInformation␊ |
69 | //-------------------------------------------------------------------------------------------------------------------------␊ |
70 | static void decodeBIOSInformation(SMBBIOSInformation *structHeader)␊ |
71 | {␊ |
72 | ␉DBG("BIOSInformation:\n");␊ |
73 | ␉DBGSMBIOS("\tvendor: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->vendor));␊ |
74 | ␉DBGSMBIOS("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
75 | ␉DBGSMBIOS("\treleaseDate: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->releaseDate));␊ |
76 | ␉DBG("\n");␊ |
77 | }␊ |
78 | ␊ |
79 | //-------------------------------------------------------------------------------------------------------------------------␊ |
80 | // SystemInformation␊ |
81 | //-------------------------------------------------------------------------------------------------------------------------␊ |
82 | static void decodeSystemInformation(SMBSystemInformation *structHeader)␊ |
83 | {␊ |
84 | ␉DBG("SystemInformation:\n");␊ |
85 | ␉DBGSMBIOS("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
86 | ␉DBGSMBIOS("\tproductName: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->productName));␊ |
87 | ␉DBGSMBIOS("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
88 | ␉DBGSMBIOS("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
89 | ␊ |
90 | ␉if (minorVersion < 1 || structHeader->header.length < 25)␊ |
91 | ␉␉return;␊ |
92 | ␉uint8_t *uuid = structHeader->uuid;␊ |
93 | if (uuid) {␊ |
94 | DBG("\tuuid: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02x%02X-%02X%02X%02X%02X%02X%02X\n",␊ |
95 | ␉␉uuid[0], uuid[1], uuid[2], uuid[3], ␊ |
96 | ␉␉uuid[4], uuid[5], ␊ |
97 | ␉␉uuid[6], uuid[7], ␊ |
98 | ␉␉uuid[8], uuid[9], ␊ |
99 | ␉␉uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);␊ |
100 | }␊ |
101 | ␉␊ |
102 | ␉DBGSMBIOS("\twakeupReason: 0x%x\n", structHeader->wakeupReason);␊ |
103 | ␊ |
104 | ␉if (minorVersion < 4 || structHeader->header.length < 27)␊ |
105 | ␉␉return;␊ |
106 | ␉DBGSMBIOS("\tskuNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->skuNumber));␊ |
107 | ␉DBGSMBIOS("\tfamily: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->family));␊ |
108 | ␉DBG("\n");␊ |
109 | }␊ |
110 | ␊ |
111 | //-------------------------------------------------------------------------------------------------------------------------␊ |
112 | // BaseBoard␊ |
113 | //-------------------------------------------------------------------------------------------------------------------------␊ |
114 | static void decodeBaseBoard(SMBBaseBoard *structHeader)␊ |
115 | {␊ |
116 | ␉DBG("BaseBoard:\n");␊ |
117 | ␉DBGSMBIOS("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
118 | ␉DBGSMBIOS("\tproduct: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->product));␊ |
119 | ␉DBGSMBIOS("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
120 | ␉DBGSMBIOS("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
121 | ␉DBGSMBIOS("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));␊ |
122 | ␉DBGSMBIOS("\tlocationInChassis: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->locationInChassis));␊ |
123 | ␉DBGSMBIOS("\tboardType: 0x%X\n", structHeader->boardType);␊ |
124 | ␉DBG("\n");␊ |
125 | }␊ |
126 | ␊ |
127 | //-------------------------------------------------------------------------------------------------------------------------␊ |
128 | // SystemEnclosure␊ |
129 | //-------------------------------------------------------------------------------------------------------------------------␊ |
130 | static void decodeSystemEnclosure(SMBSystemEnclosure *structHeader)␊ |
131 | {␊ |
132 | ␉DBG("SystemEnclosure:\n");␊ |
133 | ␉DBGSMBIOS("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
134 | ␉DBGSMBIOS("\ttype: %d\n", structHeader->type);␊ |
135 | ␉DBGSMBIOS("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
136 | ␉DBGSMBIOS("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
137 | ␉DBGSMBIOS("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));␊ |
138 | ␉DBG("\n");␊ |
139 | }␊ |
140 | ␊ |
141 | //-------------------------------------------------------------------------------------------------------------------------␊ |
142 | // ProcessorInformation␊ |
143 | //-------------------------------------------------------------------------------------------------------------------------␊ |
144 | static void decodeProcessorInformation(SMBProcessorInformation *structHeader)␊ |
145 | {␊ |
146 | ␉DBG("ProcessorInformation:\n");␊ |
147 | ␉DBGSMBIOS("\tsocketDesignation: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->socketDesignation));␊ |
148 | ␉DBGSMBIOS("\tprocessorType: %d\n", structHeader->processorType);␊ |
149 | ␉DBGSMBIOS("\tprocessorFamily: 0x%X\n", structHeader->processorFamily);␊ |
150 | ␉DBGSMBIOS("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
151 | ␉DBGSMBIOS("\tprocessorID: 0x%llX\n", structHeader->processorID);␊ |
152 | ␉DBGSMBIOS("\tprocessorVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->processorVersion));␊ |
153 | ␉DBGSMBIOS("\texternalClock: %dMHz\n", structHeader->externalClock);␊ |
154 | ␉DBGSMBIOS("\tmaximumClock: %dMHz\n", structHeader->maximumClock);␊ |
155 | ␉DBGSMBIOS("\tcurrentClock: %dMHz\n", structHeader->currentClock);␊ |
156 | ␊ |
157 | ␉if (minorVersion < 3 || structHeader->header.length < 35)␊ |
158 | ␉␉return;␊ |
159 | ␉DBGSMBIOS("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
160 | ␉DBGSMBIOS("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));␊ |
161 | ␉DBGSMBIOS("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));␊ |
162 | ␉DBG("\n");␊ |
163 | }␊ |
164 | ␊ |
165 | //-------------------------------------------------------------------------------------------------------------------------␊ |
166 | // MemoryDevice␊ |
167 | //-------------------------------------------------------------------------------------------------------------------------␊ |
168 | static void decodeMemoryDevice(SMBMemoryDevice *structHeader)␊ |
169 | {␊ |
170 | ␉DBG("MemoryDevice:\n");␊ |
171 | ␉DBGSMBIOS("\tdeviceLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->deviceLocator));␊ |
172 | ␉DBGSMBIOS("\tbankLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->bankLocator));␊ |
173 | ␉DBGSMBIOS("\tmemoryType: %s\n", SMBMemoryDeviceTypes[structHeader->memoryType]);␊ |
174 | ␊ |
175 | ␉if (minorVersion < 3 || structHeader->header.length < 27)␊ |
176 | ␉␉return;␊ |
177 | ␉DBGSMBIOS("\tmemorySpeed: %dMHz\n", structHeader->memorySpeed);␊ |
178 | ␉DBGSMBIOS("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
179 | ␉DBGSMBIOS("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
180 | ␉DBGSMBIOS("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));␊ |
181 | ␉DBGSMBIOS("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));␊ |
182 | ␉DBG("\n");␊ |
183 | }␊ |
184 | ␊ |
185 | //-------------------------------------------------------------------------------------------------------------------------␊ |
186 | // Apple Specific␊ |
187 | //-------------------------------------------------------------------------------------------------------------------------␊ |
188 | static void decodeOemProcessorType(SMBOemProcessorType *structHeader)␊ |
189 | {␊ |
190 | ␉DBG("AppleProcessorType:\n");␊ |
191 | ␉DBGSMBIOS("\tProcessorType: 0x%x\n", ((SMBOemProcessorType *)structHeader)->ProcessorType);␊ |
192 | ␉DBG("\n");␊ |
193 | }␊ |
194 | ␊ |
195 | static void decodeOemProcessorBusSpeed(SMBOemProcessorBusSpeed *structHeader)␊ |
196 | {␊ |
197 | ␉DBG("AppleProcessorBusSpeed:\n");␊ |
198 | ␉DBG("\tProcessorBusSpeed (QPI): %d.%dGT/s\n", ␊ |
199 | ␉␉␉((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000, ␊ |
200 | ␉␉␉(((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10);␊ |
201 | ␉DBG("\n");␊ |
202 | }␊ |
203 | //-------------------------------------------------------------------------------------------------------------------------␊ |
204 | ␊ |
205 | ␊ |
206 | void decodeSMBIOSTable(SMBEntryPoint *eps)␊ |
207 | {␊ |
208 | ␉uint8_t *ptr = (uint8_t *)eps->dmi.tableAddress;␊ |
209 | ␉SMBStructHeader *structHeader = (SMBStructHeader *)ptr;␊ |
210 | ␊ |
211 | ␉minorVersion = eps->minorVersion;␊ |
212 | ␊ |
213 | ␉DBG("\n");␊ |
214 | ␉for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)␊ |
215 | ␉{␊ |
216 | #if DEBUG_SMBIOS␊ |
217 | ␉␉DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
218 | ␉␉␉␉structHeader->type, structHeader->length, structHeader->handle);␊ |
219 | #endif␊ |
220 | ␉␉switch (structHeader->type)␊ |
221 | ␉␉{␊ |
222 | ␉␉␉case kSMBTypeBIOSInformation:␊ |
223 | {␊ |
224 | #if !DEBUG_SMBIOS␊ |
225 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
226 | structHeader->type, structHeader->length, structHeader->handle);␊ |
227 | #endif␊ |
228 | ␉␉␉␉decodeBIOSInformation((SMBBIOSInformation *)structHeader);␊ |
229 | ␉␉␉␉break;␊ |
230 | }␊ |
231 | ␉␉␉case kSMBTypeSystemInformation:␊ |
232 | {␊ |
233 | #if !DEBUG_SMBIOS␊ |
234 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
235 | structHeader->type, structHeader->length, structHeader->handle);␊ |
236 | #endif␊ |
237 | ␉␉␉␉decodeSystemInformation((SMBSystemInformation *)structHeader);␊ |
238 | ␉␉␉␉break;␊ |
239 | }␊ |
240 | ␉␉␉case kSMBTypeBaseBoard:␊ |
241 | {␊ |
242 | #if !DEBUG_SMBIOS␊ |
243 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
244 | structHeader->type, structHeader->length, structHeader->handle);␊ |
245 | #endif␊ |
246 | ␉␉␉␉decodeBaseBoard((SMBBaseBoard *)structHeader);␊ |
247 | ␉␉␉␉break;␊ |
248 | }␊ |
249 | ␉␉␉case kSMBTypeSystemEnclosure:␊ |
250 | {␊ |
251 | #if !DEBUG_SMBIOS␊ |
252 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
253 | structHeader->type, structHeader->length, structHeader->handle);␊ |
254 | #endif␊ |
255 | ␉␉␉␉decodeSystemEnclosure((SMBSystemEnclosure *)structHeader);␊ |
256 | ␉␉␉␉break;␊ |
257 | }␊ |
258 | ␉␉␉case kSMBTypeProcessorInformation:␊ |
259 | {␊ |
260 | #if !DEBUG_SMBIOS␊ |
261 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
262 | structHeader->type, structHeader->length, structHeader->handle);␊ |
263 | #endif␊ |
264 | ␉␉␉␉decodeProcessorInformation((SMBProcessorInformation *)structHeader);␊ |
265 | ␉␉␉␉break;␊ |
266 | }␊ |
267 | ␉␉␉case kSMBTypeMemoryDevice:␊ |
268 | {␊ |
269 | #if !DEBUG_SMBIOS␊ |
270 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
271 | structHeader->type, structHeader->length, structHeader->handle);␊ |
272 | #endif␊ |
273 | ␉␉␉␉decodeMemoryDevice((SMBMemoryDevice *)structHeader);␊ |
274 | ␉␉␉␉break;␊ |
275 | ␊ |
276 | ␉␉␉/* Skip all Apple Specific Structures */␊ |
277 | ␉␉␉case kSMBTypeFirmwareVolume:␊ |
278 | ␉␉␉case kSMBTypeMemorySPD:␊ |
279 | ␉␉␉␉break;␊ |
280 | }␊ |
281 | ␉␉␉case kSMBTypeOemProcessorType:␊ |
282 | {␊ |
283 | #if !DEBUG_SMBIOS␊ |
284 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
285 | structHeader->type, structHeader->length, structHeader->handle);␊ |
286 | #endif␊ |
287 | ␉␉␉␉decodeOemProcessorType((SMBOemProcessorType *)structHeader);␊ |
288 | ␉␉␉␉break;␊ |
289 | }␊ |
290 | ␉␉␉case kSMBTypeOemProcessorBusSpeed:␊ |
291 | {␊ |
292 | #if !DEBUG_SMBIOS ␊ |
293 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
294 | structHeader->type, structHeader->length, structHeader->handle);␊ |
295 | #endif␊ |
296 | ␉␉␉␉if (((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed)␊ |
297 | ␉␉␉␉decodeOemProcessorBusSpeed((SMBOemProcessorBusSpeed *)structHeader);␊ |
298 | ␉␉␉␉break;␊ |
299 | }␊ |
300 | ␉␉␉case kSMBTypeEndOfTable:␊ |
301 | ␉␉␉␉/* Skip, to be added at the end */␊ |
302 | ␉␉␉␉break;␊ |
303 | ␊ |
304 | ␉␉␉default:␊ |
305 | ␉␉␉␉break;␊ |
306 | ␉␉}␊ |
307 | ␊ |
308 | ␉␉ptr = (uint8_t *)((uint32_t)structHeader + structHeader->length);␊ |
309 | ␉␉for (; ((uint16_t *)ptr)[0] != 0; ptr++);␊ |
310 | ␊ |
311 | ␉␉if (((uint16_t *)ptr)[0] == 0)␊ |
312 | ␉␉␉ptr += 2;␊ |
313 | ␊ |
314 | ␉␉structHeader = (SMBStructHeader *)ptr;␊ |
315 | ␉}␊ |
316 | ␉DBG("\n");␊ |
317 | }␊ |
318 | ␊ |
319 | |