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 "smbios.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 | #else␊ |
18 | #define DBG(x...)␉msglog(x)␊ |
19 | #endif␊ |
20 | ␊ |
21 | static SMBWord minorVersion;␊ |
22 | ␊ |
23 | extern char *getSMBStringForField(SMBStructHeader *structHeader, uint8_t field);␊ |
24 | ␊ |
25 | static const char *␊ |
26 | SMBMemoryDeviceTypes[] =␊ |
27 | {␊ |
28 | "RAM", /* 00h Undefined */␊ |
29 | "RAM", /* 01h Other */␊ |
30 | "RAM", /* 02h Unknown */␊ |
31 | "DRAM", /* 03h DRAM */␊ |
32 | "EDRAM", /* 04h EDRAM */␊ |
33 | "VRAM", /* 05h VRAM */␊ |
34 | "SRAM", /* 06h SRAM */␊ |
35 | "RAM", /* 07h RAM */␊ |
36 | "ROM", /* 08h ROM */␊ |
37 | "FLASH", /* 09h FLASH */␊ |
38 | "EEPROM", /* 0Ah EEPROM */␊ |
39 | "FEPROM", /* 0Bh FEPROM */␊ |
40 | "EPROM", /* 0Ch EPROM */␊ |
41 | "CDRAM", /* 0Dh CDRAM */␊ |
42 | "3DRAM", /* 0Eh 3DRAM */␊ |
43 | "SDRAM", /* 0Fh SDRAM */␊ |
44 | "SGRAM", /* 10h SGRAM */␊ |
45 | "RDRAM", /* 11h RDRAM */␊ |
46 | "DDR SDRAM", /* 12h DDR */␊ |
47 | "DDR2 SDRAM", /* 13h DDR2 */␊ |
48 | "DDR2 FB-DIMM", /* 14h DDR2 FB-DIMM */␊ |
49 | "RAM",␉␉␉/* 15h unused */␊ |
50 | "RAM",␉␉␉/* 16h unused */␊ |
51 | "RAM",␉␉␉/* 17h unused */␊ |
52 | "DDR3",␉␉␉/* 18h DDR3, chosen in [5776134] */␊ |
53 | "FBD2"␉␉␉/* 19h FBD2 */␊ |
54 | };␊ |
55 | ␊ |
56 | static const int kSMBMemoryDeviceTypeCount = sizeof(SMBMemoryDeviceTypes) /␊ |
57 | sizeof(SMBMemoryDeviceTypes[0]);␊ |
58 | ␊ |
59 | //-------------------------------------------------------------------------------------------------------------------------␊ |
60 | // BIOS Information (Type 0)␊ |
61 | //-------------------------------------------------------------------------------------------------------------------------␊ |
62 | void decodeBIOSInformation(SMBBIOSInformation *structHeader)␊ |
63 | {␊ |
64 | ␉DBG("BIOS Information:\n");␊ |
65 | ␉DBG("\tVendor: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->vendor));␊ |
66 | ␉DBG("\tVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
67 | ␉// Address Segment␊ |
68 | ␉DBG("\tRelease Date: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->releaseDate));␊ |
69 | ␉// ROM Size␊ |
70 | ␉//DBG("\tSupported BIOS functions: (0x%llX) %s\n", structHeader->characteristics, SMBBIOSInfoChar0[structHeader->characteristics]);␊ |
71 | ␉// Major Release␊ |
72 | ␉// Minor Release␊ |
73 | ␉// Firmware Major Release␊ |
74 | ␉// Firmware Minor Release␊ |
75 | ␉//SMBByte characteristicsExt1;␊ |
76 | ␉//SMBByte characteristicsExt2;␊ |
77 | ␉DBG("\n");␊ |
78 | }␊ |
79 | ␊ |
80 | //-------------------------------------------------------------------------------------------------------------------------␊ |
81 | // System Information (Type 1)␊ |
82 | //-------------------------------------------------------------------------------------------------------------------------␊ |
83 | void decodeSystemInformation(SMBSystemInformation *structHeader)␊ |
84 | {␊ |
85 | ␉DBG("System Information:\n");␊ |
86 | ␉DBG("\tManufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
87 | ␉DBG("\tProduct Name: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->productName));␊ |
88 | ␉DBG("\tVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
89 | ␉DBG("\tSerial Number: ** PRIVATE **\n"); //%s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
90 | ␊ |
91 | ␉if (minorVersion < 1 || structHeader->header.length < 25)␊ |
92 | ␉␉return;␊ |
93 | ␉uint8_t *uuid = structHeader->uuid;␊ |
94 | ␉if (uuid) {␊ |
95 | ␉␉DBG("\tuuid: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02x%02X-%02X%02X%02X%02X%02X%02X\n",␊ |
96 | ␉␉␉uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],␊ |
97 | ␉␉␉uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);␊ |
98 | ␉}␊ |
99 | ␉DBG("\tWake-up Type: 0x%x\n", structHeader->wakeupReason);␊ |
100 | ␊ |
101 | ␉if (minorVersion < 4 || structHeader->header.length < 27)␊ |
102 | ␉␉return;␊ |
103 | ␉DBG("\tSKU Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->skuNumber)); // System SKU#␊ |
104 | ␉DBG("\tFamily: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->family));␊ |
105 | ␉DBG("\n");␊ |
106 | }␊ |
107 | ␊ |
108 | //-------------------------------------------------------------------------------------------------------------------------␊ |
109 | // Base Board (or Module) Information (Type 2)␊ |
110 | //-------------------------------------------------------------------------------------------------------------------------␊ |
111 | void decodeBaseBoard(SMBBaseBoard *structHeader)␊ |
112 | {␊ |
113 | ␉DBG("Base Board Information:\n");␊ |
114 | ␉DBG("\tManufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
115 | ␉DBG("\tProduct Name: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->product));␊ |
116 | ␉DBG("\tVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
117 | ␉DBG("\tSerial Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
118 | ␉DBG("\tAsset Tag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));␊ |
119 | ␉// Feature Flags (BYTE)␊ |
120 | ␉DBG("\tLocation In Chassis: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->locationInChassis)); // Part Component␊ |
121 | ␉// Chassis Handle (WORD)␊ |
122 | ␉DBG("\tType: 0x%X\n", structHeader->boardType);␊ |
123 | ␉// Number of Contained Object Handles (n) (BYTE)␊ |
124 | ␉// Contained Object Handles n(WORDs)␊ |
125 | ␉DBG("\n");␊ |
126 | }␊ |
127 | ␊ |
128 | //-------------------------------------------------------------------------------------------------------------------------␊ |
129 | // System Enclosure or Chassis (Type 3)␊ |
130 | //-------------------------------------------------------------------------------------------------------------------------␊ |
131 | void decodeSystemEnclosure(SMBSystemEnclosure *structHeader)␊ |
132 | {␊ |
133 | ␉DBG("Chassis Information:\n");␊ |
134 | ␉DBG("\tManufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
135 | ␉DBG("\tType: %d\n", structHeader->type);␊ |
136 | ␉DBG("\tVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
137 | ␉DBG("\tSerial Number: ** PRIVATE **\n"); //%s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
138 | ␉DBG("\tAsset Tag Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));␊ |
139 | ␉// Boot-up State:␊ |
140 | ␉// Power Supply State␊ |
141 | ␉// Thermal State␊ |
142 | ␉// Security Status:␊ |
143 | ␉// OEM Information:␊ |
144 | ␉// Height;␊ |
145 | ␉// Cords;␊ |
146 | ␉// ElementsCount;␊ |
147 | ␉// ElementLen;␊ |
148 | ␉// Elements[1]; // open array of ElementsCount*ElementLen BYTEs␊ |
149 | ␉DBG("\n");␊ |
150 | }␊ |
151 | ␊ |
152 | //-------------------------------------------------------------------------------------------------------------------------␊ |
153 | // Processor Information (Type 4)␊ |
154 | //-------------------------------------------------------------------------------------------------------------------------␊ |
155 | void decodeProcessorInformation(SMBProcessorInformation *structHeader)␊ |
156 | {␊ |
157 | ␉DBG("Processor Information:\n");␊ |
158 | ␉DBG("\tSocket Designation: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->socketDesignation));␊ |
159 | ␉DBG("\tType: %d\n", structHeader->processorType);␊ |
160 | ␉DBG("\tFamily: 0x%X\n", structHeader->processorFamily);␊ |
161 | ␉DBG("\tManufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
162 | ␉DBG("\tID: 0x%llX\n", structHeader->processorID);␊ |
163 | ␉DBG("\tProcessor Version: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->processorVersion));␊ |
164 | //␉DBG("\tVoltage: 0.%xV\n", structHeader->voltage);␊ |
165 | ␉DBG("\tExternal Clock: %dMHz\n", structHeader->externalClock);␊ |
166 | ␉DBG("\tMaximum Clock: %dMHz\n", structHeader->maximumClock);␊ |
167 | ␉DBG("\tCurrent Clock: %dMHz\n", structHeader->currentClock);␊ |
168 | ␊ |
169 | ␉if (minorVersion < 3 || structHeader->header.length < 35)␊ |
170 | ␉␉return;␊ |
171 | ␉DBG("\tSerial Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
172 | ␉DBG("\tAsset Tag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));␊ |
173 | ␉DBG("\tPart Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));␊ |
174 | //␉DBG("\tProcessor Family 2: %d\n", structHeader->processorFamily2);␊ |
175 | ␉DBG("\n");␊ |
176 | }␊ |
177 | ␊ |
178 | //-------------------------------------------------------------------------------------------------------------------------␊ |
179 | // Memory Module Information (Type 6)␊ |
180 | //-------------------------------------------------------------------------------------------------------------------------␊ |
181 | ␊ |
182 | //-------------------------------------------------------------------------------------------------------------------------␊ |
183 | // OEM Strings (Type 11)␊ |
184 | //-------------------------------------------------------------------------------------------------------------------------␊ |
185 | ␊ |
186 | ␊ |
187 | //-------------------------------------------------------------------------------------------------------------------------␊ |
188 | // MemoryDevice (Type 17)␊ |
189 | //-------------------------------------------------------------------------------------------------------------------------␊ |
190 | void decodeMemoryDevice(SMBMemoryDevice *structHeader)␊ |
191 | {␊ |
192 | ␉DBG("Memory Device:\n");␊ |
193 | ␉DBG("\tDevice Locator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->deviceLocator));␊ |
194 | ␉DBG("\tBank Locator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->bankLocator));␊ |
195 | ␉DBG("\tMemory Type: %s\n", SMBMemoryDeviceTypes[structHeader->memoryType]);␊ |
196 | ␊ |
197 | ␉if (minorVersion < 3 || structHeader->header.length < 27)␊ |
198 | ␉␉return;␊ |
199 | ␉DBG("\tSpeed: %d MHz\n", structHeader->memorySpeed);␊ |
200 | ␉DBG("\tError Handle: %x\n", structHeader->errorHandle);␊ |
201 | ␉DBG("\tManufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
202 | ␉DBG("\tSerial Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
203 | ␉DBG("\tAsset Tag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));␊ |
204 | ␉DBG("\tPart Number: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));␊ |
205 | ␉DBG("\n");␊ |
206 | }␊ |
207 | ␊ |
208 | //-------------------------------------------------------------------------------------------------------------------------␊ |
209 | // Apple Specific␊ |
210 | //-------------------------------------------------------------------------------------------------------------------------␊ |
211 | void decodeOemProcessorType(SMBOemProcessorType *structHeader)␊ |
212 | {␊ |
213 | ␉DBG("AppleProcessorType:\n");␊ |
214 | ␉DBG("\tProcessorType: 0x%x\n", ((SMBOemProcessorType *)structHeader)->ProcessorType);␊ |
215 | ␉DBG("\n");␊ |
216 | }␊ |
217 | ␊ |
218 | void decodeOemProcessorBusSpeed(SMBOemProcessorBusSpeed *structHeader)␊ |
219 | {␊ |
220 | ␉DBG("AppleProcessorBusSpeed:\n");␊ |
221 | ␉DBG("\tProcessorBusSpeed (QPI): %d.%dGT/s\n", ␊ |
222 | ␉␉␉((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000, ␊ |
223 | ␉␉␉(((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10);␊ |
224 | ␉DBG("\n");␊ |
225 | }␊ |
226 | //-------------------------------------------------------------------------------------------------------------------------␊ |
227 | ␊ |
228 | ␊ |
229 | void decodeSMBIOSTable(SMBEntryPoint *eps)␊ |
230 | {␊ |
231 | ␉uint8_t *ptr = (uint8_t *)eps->dmi.tableAddress;␊ |
232 | ␉SMBStructHeader *structHeader = (SMBStructHeader *)ptr;␊ |
233 | ␊ |
234 | ␉minorVersion = eps->minorVersion;␊ |
235 | ␊ |
236 | ␉DBG("\n");␊ |
237 | ␉for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)␊ |
238 | ␉{␊ |
239 | ␉␉DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
240 | ␉␉␉␉structHeader->type, structHeader->length, structHeader->handle);␊ |
241 | ␊ |
242 | ␉␉switch (structHeader->type)␊ |
243 | ␉␉{␊ |
244 | ␉␉␉case kSMBTypeBIOSInformation: // Type 0␊ |
245 | ␉␉␉␉decodeBIOSInformation((SMBBIOSInformation *)structHeader);␊ |
246 | ␉␉␉␉break;␊ |
247 | ␊ |
248 | ␉␉␉case kSMBTypeSystemInformation: // Type 1␊ |
249 | ␉␉␉␉decodeSystemInformation((SMBSystemInformation *)structHeader);␊ |
250 | ␉␉␉␉break;␊ |
251 | ␊ |
252 | ␉␉␉case kSMBTypeBaseBoard: // Type 2␊ |
253 | ␉␉␉␉decodeBaseBoard((SMBBaseBoard *)structHeader);␊ |
254 | ␉␉␉␉break;␊ |
255 | ␊ |
256 | ␉␉␉case kSMBTypeSystemEnclosure: // Type 3␊ |
257 | ␉␉␉␉decodeSystemEnclosure((SMBSystemEnclosure *)structHeader);␊ |
258 | ␉␉␉␉break;␊ |
259 | ␊ |
260 | ␉␉␉case kSMBTypeProcessorInformation: // Type 4␊ |
261 | ␉␉␉␉decodeProcessorInformation((SMBProcessorInformation *)structHeader);␊ |
262 | ␉␉␉␉break;␊ |
263 | ␊ |
264 | ␉␉␉case kSMBTypeMemoryDevice: // Type 17␊ |
265 | ␉␉␉␉decodeMemoryDevice((SMBMemoryDevice *)structHeader);␊ |
266 | ␉␉␉␉break;␊ |
267 | ␊ |
268 | ␉␉␉/* Skip all Apple Specific Structures */␊ |
269 | ␉␉␉case kSMBTypeFirmwareVolume: // Type␊ |
270 | ␉␉␉case kSMBTypeMemorySPD: // Type␊ |
271 | ␉␉␉␉break;␊ |
272 | ␊ |
273 | ␉␉␉case kSMBTypeOemProcessorType: // Type␊ |
274 | ␉␉␉␉decodeOemProcessorType((SMBOemProcessorType *)structHeader);␊ |
275 | ␉␉␉␉break;␊ |
276 | ␊ |
277 | ␉␉␉case kSMBTypeOemProcessorBusSpeed: // Type␊ |
278 | ␉␉␉␉decodeOemProcessorBusSpeed((SMBOemProcessorBusSpeed *)structHeader);␊ |
279 | ␉␉␉␉break;␊ |
280 | ␊ |
281 | ␉␉␉case kSMBTypeEndOfTable: // Type␊ |
282 | ␉␉␉␉/* Skip, to be added at the end */␊ |
283 | ␉␉␉␉break;␊ |
284 | ␊ |
285 | ␉␉␉default:␊ |
286 | ␉␉␉␉break;␊ |
287 | ␉␉}␊ |
288 | ␊ |
289 | ␉␉ptr = (uint8_t *)((uint32_t)structHeader + structHeader->length);␊ |
290 | ␉␉for (; ((uint16_t *)ptr)[0] != 0; ptr++);␊ |
291 | ␊ |
292 | ␉␉if (((uint16_t *)ptr)[0] == 0)␊ |
293 | ␉␉{␊ |
294 | ␉␉␉ptr += 2;␊ |
295 | ␉␉}␊ |
296 | ␊ |
297 | ␉␉structHeader = (SMBStructHeader *)ptr;␊ |
298 | ␉}␊ |
299 | ␉DBG("\n");␊ |
300 | }␊ |
301 | ␊ |
302 | |