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 | #else␊ |
18 | #define DBG(x...)␉msglog(x)␊ |
19 | #endif␊ |
20 | ␊ |
21 | ␊ |
22 | static SMBWord minorVersion;␊ |
23 | ␊ |
24 | //extern char *getSMBStringForField(SMBStructHeader *structHeader, uint8_t field);␊ |
25 | static void decodeBIOSInformation(SMBBIOSInformation *structHeader);␊ |
26 | static void decodeSystemInformation(SMBSystemInformation *structHeader);␊ |
27 | static void decodeBaseBoard(SMBBaseBoard *structHeader);␊ |
28 | static void decodeSystemEnclosure(SMBSystemEnclosure *structHeader);␊ |
29 | static void decodeProcessorInformation(SMBProcessorInformation *structHeader);␊ |
30 | static void decodeMemoryDevice(SMBMemoryDevice *structHeader);␊ |
31 | static void decodeOemProcessorType(SMBOemProcessorType *structHeader);␊ |
32 | static void decodeOemProcessorBusSpeed(SMBOemProcessorBusSpeed *structHeader);␊ |
33 | ␊ |
34 | //-------------------------------------------------------------------------------------------------------------------------␊ |
35 | // BIOSInformation␊ |
36 | //-------------------------------------------------------------------------------------------------------------------------␊ |
37 | static void decodeBIOSInformation(SMBBIOSInformation *structHeader)␊ |
38 | {␊ |
39 | ␉DBG("BIOSInformation:\n");␊ |
40 | ␉DBG("\tvendor: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->vendor));␊ |
41 | ␉DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
42 | ␉DBG("\treleaseDate: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->releaseDate));␊ |
43 | ␉DBG("\n");␊ |
44 | }␊ |
45 | ␊ |
46 | //-------------------------------------------------------------------------------------------------------------------------␊ |
47 | // SystemInformation␊ |
48 | //-------------------------------------------------------------------------------------------------------------------------␊ |
49 | static void decodeSystemInformation(SMBSystemInformation *structHeader)␊ |
50 | {␊ |
51 | ␉DBG("SystemInformation:\n");␊ |
52 | ␉DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
53 | ␉DBG("\tproductName: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->productName));␊ |
54 | ␉DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
55 | ␉DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
56 | ␊ |
57 | ␉if (minorVersion < 1 || structHeader->header.length < 25)␊ |
58 | ␉␉return;␊ |
59 | ␉uint8_t *uuid = structHeader->uuid;␊ |
60 | ␉DBG("\tuuid: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02x%02X-%02X%02X%02X%02X%02X%02X\n",␊ |
61 | ␉␉uuid[0], uuid[1], uuid[2], uuid[3], ␊ |
62 | ␉␉uuid[4], uuid[5], ␊ |
63 | ␉␉uuid[6], uuid[7], ␊ |
64 | ␉␉uuid[8], uuid[9], ␊ |
65 | ␉␉uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);␊ |
66 | ␉DBG("\twakeupReason: 0x%x\n", structHeader->wakeupReason);␊ |
67 | ␊ |
68 | ␉if (minorVersion < 4 || structHeader->header.length < 27)␊ |
69 | ␉␉return;␊ |
70 | ␉DBG("\tskuNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->skuNumber));␊ |
71 | ␉DBG("\tfamily: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->family));␊ |
72 | ␉DBG("\n");␊ |
73 | }␊ |
74 | ␊ |
75 | //-------------------------------------------------------------------------------------------------------------------------␊ |
76 | // BaseBoard␊ |
77 | //-------------------------------------------------------------------------------------------------------------------------␊ |
78 | static void decodeBaseBoard(SMBBaseBoard *structHeader)␊ |
79 | {␊ |
80 | ␉DBG("BaseBoard:\n");␊ |
81 | ␉DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
82 | ␉DBG("\tproduct: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->product));␊ |
83 | ␉DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
84 | ␉DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
85 | ␉DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));␊ |
86 | ␉DBG("\tlocationInChassis: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->locationInChassis));␊ |
87 | ␉DBG("\tboardType: 0x%X\n", structHeader->boardType);␊ |
88 | ␉DBG("\n");␊ |
89 | }␊ |
90 | ␊ |
91 | //-------------------------------------------------------------------------------------------------------------------------␊ |
92 | // SystemEnclosure␊ |
93 | //-------------------------------------------------------------------------------------------------------------------------␊ |
94 | static void decodeSystemEnclosure(SMBSystemEnclosure *structHeader)␊ |
95 | {␊ |
96 | ␉DBG("SystemEnclosure:\n");␊ |
97 | ␉DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
98 | ␉DBG("\ttype: %d\n", structHeader->type);␊ |
99 | ␉DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version));␊ |
100 | ␉DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
101 | ␉DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber));␊ |
102 | ␉DBG("\n");␊ |
103 | }␊ |
104 | ␊ |
105 | //-------------------------------------------------------------------------------------------------------------------------␊ |
106 | // ProcessorInformation␊ |
107 | //-------------------------------------------------------------------------------------------------------------------------␊ |
108 | static void decodeProcessorInformation(SMBProcessorInformation *structHeader)␊ |
109 | {␊ |
110 | ␉DBG("ProcessorInformation:\n");␊ |
111 | ␉DBG("\tsocketDesignation: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->socketDesignation));␊ |
112 | ␉DBG("\tprocessorType: %d\n", structHeader->processorType);␊ |
113 | ␉DBG("\tprocessorFamily: 0x%X\n", structHeader->processorFamily);␊ |
114 | ␉DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
115 | ␉DBG("\tprocessorID: 0x%llX\n", structHeader->processorID);␊ |
116 | ␉DBG("\tprocessorVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->processorVersion));␊ |
117 | ␉DBG("\texternalClock: %dMHz\n", structHeader->externalClock);␊ |
118 | ␉DBG("\tmaximumClock: %dMHz\n", structHeader->maximumClock);␊ |
119 | ␉DBG("\tcurrentClock: %dMHz\n", structHeader->currentClock);␊ |
120 | ␊ |
121 | ␉if (minorVersion < 3 || structHeader->header.length < 35)␊ |
122 | ␉␉return;␊ |
123 | ␉DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
124 | ␉DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));␊ |
125 | ␉DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));␊ |
126 | ␉DBG("\n");␊ |
127 | }␊ |
128 | ␊ |
129 | //-------------------------------------------------------------------------------------------------------------------------␊ |
130 | // MemoryDevice␊ |
131 | //-------------------------------------------------------------------------------------------------------------------------␊ |
132 | static void decodeMemoryDevice(SMBMemoryDevice *structHeader)␊ |
133 | {␊ |
134 | ␉DBG("MemoryDevice:\n");␊ |
135 | ␉DBG("\tdeviceLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->deviceLocator));␊ |
136 | ␉DBG("\tbankLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->bankLocator));␊ |
137 | ␉DBG("\tmemoryType: %s\n", SMBMemoryDeviceTypes[structHeader->memoryType]);␊ |
138 | ␊ |
139 | ␉if (minorVersion < 3 || structHeader->header.length < 27)␊ |
140 | ␉␉return;␊ |
141 | ␉DBG("\tmemorySpeed: %dMHz\n", structHeader->memorySpeed);␊ |
142 | ␉DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer));␊ |
143 | ␉DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber));␊ |
144 | ␉DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag));␊ |
145 | ␉DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber));␊ |
146 | ␉DBG("\n");␊ |
147 | }␊ |
148 | ␊ |
149 | //-------------------------------------------------------------------------------------------------------------------------␊ |
150 | // Apple Specific␊ |
151 | //-------------------------------------------------------------------------------------------------------------------------␊ |
152 | static void decodeOemProcessorType(SMBOemProcessorType *structHeader)␊ |
153 | {␊ |
154 | ␉DBG("AppleProcessorType:\n");␊ |
155 | ␉DBG("\tProcessorType: 0x%x\n", ((SMBOemProcessorType *)structHeader)->ProcessorType);␊ |
156 | ␉DBG("\n");␊ |
157 | }␊ |
158 | ␊ |
159 | static void decodeOemProcessorBusSpeed(SMBOemProcessorBusSpeed *structHeader)␊ |
160 | {␊ |
161 | ␉DBG("AppleProcessorBusSpeed:\n");␊ |
162 | ␉DBG("\tProcessorBusSpeed (QPI): %d.%dGT/s\n", ␊ |
163 | ␉␉␉((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000, ␊ |
164 | ␉␉␉(((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10);␊ |
165 | ␉DBG("\n");␊ |
166 | }␊ |
167 | //-------------------------------------------------------------------------------------------------------------------------␊ |
168 | ␊ |
169 | ␊ |
170 | void decodeSMBIOSTable(SMBEntryPoint *eps)␊ |
171 | {␊ |
172 | ␉uint8_t *ptr = (uint8_t *)eps->dmi.tableAddress;␊ |
173 | ␉SMBStructHeader *structHeader = (SMBStructHeader *)ptr;␊ |
174 | ␊ |
175 | ␉minorVersion = eps->minorVersion;␊ |
176 | ␊ |
177 | ␉DBG("\n");␊ |
178 | ␉for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));)␊ |
179 | ␉{␊ |
180 | #if DEBUG_SMBIOS␊ |
181 | ␉␉DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
182 | ␉␉␉␉structHeader->type, structHeader->length, structHeader->handle);␊ |
183 | #endif␊ |
184 | ␉␉switch (structHeader->type)␊ |
185 | ␉␉{␊ |
186 | ␉␉␉case kSMBTypeBIOSInformation:␊ |
187 | {␊ |
188 | #if !DEBUG_SMBIOS␊ |
189 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
190 | structHeader->type, structHeader->length, structHeader->handle);␊ |
191 | #endif␊ |
192 | ␉␉␉␉decodeBIOSInformation((SMBBIOSInformation *)structHeader);␊ |
193 | ␉␉␉␉break;␊ |
194 | }␊ |
195 | ␉␉␉case kSMBTypeSystemInformation:␊ |
196 | {␊ |
197 | #if !DEBUG_SMBIOS␊ |
198 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
199 | structHeader->type, structHeader->length, structHeader->handle);␊ |
200 | #endif␊ |
201 | ␉␉␉␉decodeSystemInformation((SMBSystemInformation *)structHeader);␊ |
202 | ␉␉␉␉break;␊ |
203 | }␊ |
204 | ␉␉␉case kSMBTypeBaseBoard:␊ |
205 | {␊ |
206 | #if !DEBUG_SMBIOS␊ |
207 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
208 | structHeader->type, structHeader->length, structHeader->handle);␊ |
209 | #endif␊ |
210 | ␉␉␉␉decodeBaseBoard((SMBBaseBoard *)structHeader);␊ |
211 | ␉␉␉␉break;␊ |
212 | }␊ |
213 | ␉␉␉case kSMBTypeSystemEnclosure:␊ |
214 | {␊ |
215 | #if !DEBUG_SMBIOS␊ |
216 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
217 | structHeader->type, structHeader->length, structHeader->handle);␊ |
218 | #endif␊ |
219 | ␉␉␉␉decodeSystemEnclosure((SMBSystemEnclosure *)structHeader);␊ |
220 | ␉␉␉␉break;␊ |
221 | }␊ |
222 | ␉␉␉case kSMBTypeProcessorInformation:␊ |
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 | ␉␉␉␉decodeProcessorInformation((SMBProcessorInformation *)structHeader);␊ |
229 | ␉␉␉␉break;␊ |
230 | }␊ |
231 | ␉␉␉case kSMBTypeMemoryDevice:␊ |
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 | ␉␉␉␉decodeMemoryDevice((SMBMemoryDevice *)structHeader);␊ |
238 | ␉␉␉␉break;␊ |
239 | ␊ |
240 | ␉␉␉/* Skip all Apple Specific Structures */␊ |
241 | ␉␉␉case kSMBTypeFirmwareVolume:␊ |
242 | ␉␉␉case kSMBTypeMemorySPD:␊ |
243 | ␉␉␉␉break;␊ |
244 | }␊ |
245 | ␉␉␉case kSMBTypeOemProcessorType:␊ |
246 | {␊ |
247 | #if !DEBUG_SMBIOS␊ |
248 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
249 | structHeader->type, structHeader->length, structHeader->handle);␊ |
250 | #endif␊ |
251 | ␉␉␉␉decodeOemProcessorType((SMBOemProcessorType *)structHeader);␊ |
252 | ␉␉␉␉break;␊ |
253 | }␊ |
254 | ␉␉␉case kSMBTypeOemProcessorBusSpeed:␊ |
255 | {␊ |
256 | #if !DEBUG_SMBIOS ␊ |
257 | DBG("Type: %d, Length: %d, Handle: 0x%x\n", ␊ |
258 | structHeader->type, structHeader->length, structHeader->handle);␊ |
259 | #endif␊ |
260 | ␉␉␉␉if (((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed)␊ |
261 | ␉␉␉␉decodeOemProcessorBusSpeed((SMBOemProcessorBusSpeed *)structHeader);␊ |
262 | ␉␉␉␉break;␊ |
263 | }␊ |
264 | ␉␉␉case kSMBTypeEndOfTable:␊ |
265 | ␉␉␉␉/* Skip, to be added at the end */␊ |
266 | ␉␉␉␉break;␊ |
267 | ␊ |
268 | ␉␉␉default:␊ |
269 | ␉␉␉␉break;␊ |
270 | ␉␉}␊ |
271 | ␊ |
272 | ␉␉ptr = (uint8_t *)((uint32_t)structHeader + structHeader->length);␊ |
273 | ␉␉for (; ((uint16_t *)ptr)[0] != 0; ptr++);␊ |
274 | ␊ |
275 | ␉␉if (((uint16_t *)ptr)[0] == 0)␊ |
276 | ␉␉␉ptr += 2;␊ |
277 | ␊ |
278 | ␉␉structHeader = (SMBStructHeader *)ptr;␊ |
279 | ␉}␊ |
280 | ␉DBG("\n");␊ |
281 | }␊ |
282 | ␊ |
283 | |