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