1 | /*␊ |
2 | * Add (c) here␊ |
3 | *␊ |
4 | * Copyright .... All rights reserved.␊ |
5 | *␊ |
6 | */␊ |
7 | ␊ |
8 | #include "smbios_getters.h"␊ |
9 | #include "bootstruct.h"␊ |
10 | ␊ |
11 | #ifndef DEBUG_SMBIOS␊ |
12 | #define DEBUG_SMBIOS 0␊ |
13 | #endif␊ |
14 | ␊ |
15 | #if DEBUG_SMBIOS␊ |
16 | #define DBG(x...)␉verbose(x)␊ |
17 | #else␊ |
18 | #define DBG(x...)␊ |
19 | #endif␊ |
20 | ␊ |
21 | //Slice - for ACPI patcher templates␊ |
22 | int␉␉ModelLength = 0;␊ |
23 | char␉MacModel[8] = "MacBook";␊ |
24 | unsigned int ModelRev = 0x00010001;␊ |
25 | uint64_t smbios_p;␊ |
26 | char*␉gSMBIOSBoardModel;␊ |
27 | ␊ |
28 | bool getProcessorInformationExternalClock(returnType *value)␊ |
29 | {␊ |
30 | ␉value->word = Platform->CPU.FSBFrequency/MEGA;␊ |
31 | ␉return true;␊ |
32 | }␊ |
33 | ␊ |
34 | bool getProcessorInformationMaximumClock(returnType *value)␊ |
35 | {␊ |
36 | ␉value->word = Platform->CPU.CPUFrequency/MEGA;␊ |
37 | ␉return true;␊ |
38 | }␊ |
39 | ␊ |
40 | bool getSMBOemProcessorBusSpeed(returnType *value)␊ |
41 | {␊ |
42 | ␉value->word = 0;␊ |
43 | ␉if (Platform->CPU.Vendor == 0x756E6547) // Intel␊ |
44 | ␉{␉␉␊ |
45 | ␉␉switch (Platform->CPU.Family) ␊ |
46 | ␉␉{␊ |
47 | ␉␉␉case 0x06:␊ |
48 | ␉␉␉{␊ |
49 | ␉␉␉␉switch (Platform->CPU.Model)␊ |
50 | ␉␉␉␉{␊ |
51 | ␉␉␉␉␉case CPU_MODEL_PENTIUM_M:␉␉␉␉␉// Dotah␊ |
52 | ␉␉␉␉␉case CPU_MODEL_YONAH:␉␉// Intel Mobile Core Solo, Duo␊ |
53 | ␉␉␉␉␉case CPU_MODEL_MEROM:␉␉// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx␊ |
54 | ␉␉␉␉␉case CPU_MODEL_PENRYN:␉␉// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx␊ |
55 | ␉␉␉␉␉case CPU_MODEL_ATOM:␉␉// Intel Atom (45nm)␊ |
56 | ␉␉␉␉␉␉value->word = ((Platform->CPU.FSBFrequency * 4)/1000000); //Slice␊ |
57 | ␉␉␉␉␉␉return true;␊ |
58 | ␊ |
59 | ␉␉␉␉␉case 0x19:␉␉␉␉␉// ??? Intel Core i5 650 @3.20 GHz ␊ |
60 | ␉␉␉␉␉case CPU_MODEL_NEHALEM:␉␉// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)␊ |
61 | ␉␉␉␉␉case CPU_MODEL_FIELDS:␉␉// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)␊ |
62 | ␉␉␉␉␉case CPU_MODEL_DALES:␊ |
63 | ␉␉␉␉␉case CPU_MODEL_DALES_32NM:␉// Intel Core i3, i5 LGA1156 (32nm) Clarkdale␊ |
64 | ␉␉␉␉␉case CPU_MODEL_WESTMERE:␉// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core␊ |
65 | ␉␉␉␉␉case CPU_MODEL_NEHALEM_EX:␉// Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65x␊ |
66 | ␉␉␉␉␉case CPU_MODEL_WESTMERE_EX:␉// Intel Xeon E7␊ |
67 | ␉␉␉␉␉case CPU_MODEL_SANDY:␊ |
68 | ␉␉␉␉␉case CPU_MODEL_SANDY_XEON:␉␊ |
69 | ␉␉␉␉␉{␊ |
70 | ␉␉␉␉␉␉// thanks to dgobe for i3/i5/i7 bus speed detection␊ |
71 | ␉␉␉␉␉␉int nhm_bus = 0x3F;␊ |
72 | ␉␉␉␉␉␉static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};␊ |
73 | ␉␉␉␉␉␉unsigned long did, vid;␊ |
74 | ␉␉␉␉␉␉int i;␊ |
75 | ␉␉␉␉␉␉␊ |
76 | ␉␉␉␉␉␉// Nehalem supports Scrubbing␊ |
77 | ␉␉␉␉␉␉// First, locate the PCI bus where the MCH is located␊ |
78 | ␉␉␉␉␉␉for(i = 0; i < sizeof(possible_nhm_bus); i++)␊ |
79 | ␉␉␉␉␉␉{␊ |
80 | ␉␉␉␉␉␉␉vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00);␊ |
81 | ␉␉␉␉␉␉␉did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02);␊ |
82 | ␉␉␉␉␉␉␉vid &= 0xFFFF;␊ |
83 | ␉␉␉␉␉␉␉did &= 0xFF00;␊ |
84 | ␉␉␉␉␉␉␉␊ |
85 | ␉␉␉␉␉␉␉if(vid == 0x8086 && did >= 0x2C00)␊ |
86 | ␉␉␉␉␉␉␉␉nhm_bus = possible_nhm_bus[i]; ␊ |
87 | ␉␉␉␉␉␉}␊ |
88 | ␉␉␉␉␉␉␊ |
89 | ␉␉␉␉␉␉unsigned long qpimult, qpibusspeed;␊ |
90 | ␉␉␉␉␉␉qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50);␊ |
91 | ␉␉␉␉␉␉qpimult &= 0x7F;␊ |
92 | ␉␉␉␉␉␉DBG("qpimult %d\n", qpimult);␊ |
93 | ␉␉␉␉␉␉qpibusspeed = (qpimult * 2 * (Platform->CPU.FSBFrequency/1000000));␊ |
94 | ␉␉␉␉␉␉// Rek: rounding decimals to match original mac profile info␊ |
95 | ␉␉␉␉␉␉if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100;␊ |
96 | ␉␉␉␉␉␉DBG("qpibusspeed %d\n", qpibusspeed);␊ |
97 | ␉␉␉␉␉␉value->word = qpibusspeed;␊ |
98 | ␉␉␉␉␉␉return true;␊ |
99 | ␉␉␉␉␉}␊ |
100 | ␉␉␉␉}␊ |
101 | ␉␉␉}␊ |
102 | ␉␉}␊ |
103 | ␉}␊ |
104 | ␉return false;␊ |
105 | }␊ |
106 | ␊ |
107 | uint16_t simpleGetSMBOemProcessorType(void)␊ |
108 | {␊ |
109 | ␉if (Platform->CPU.NoCores >= 4) ␊ |
110 | ␉{␊ |
111 | ␉␉return 0x0501;␉// Quad-Core Xeon␊ |
112 | ␉}␊ |
113 | ␉else if (Platform->CPU.NoCores == 1) ␊ |
114 | ␉{␊ |
115 | ␉␉return 0x0201;␉// Core Solo␊ |
116 | ␉};␊ |
117 | ␉␊ |
118 | ␉return 0x0301;␉␉// Core 2 Duo␊ |
119 | }␊ |
120 | ␊ |
121 | bool getSMBOemProcessorType(returnType *value)␊ |
122 | {␊ |
123 | ␉static bool done = false;␉␉␊ |
124 | ␉␉␊ |
125 | ␉value->word = simpleGetSMBOemProcessorType();␊ |
126 | ␊ |
127 | ␉if (Platform->CPU.Vendor == 0x756E6547) // Intel␊ |
128 | ␉{␊ |
129 | ␉␉if (!done)␊ |
130 | ␉␉{␊ |
131 | ␉␉␉verbose("CPU is %s, family 0x%x, model 0x%x\n", Platform->CPU.BrandString, Platform->CPU.Family, Platform->CPU.Model);␊ |
132 | ␉␉␉done = true;␊ |
133 | ␉␉}␊ |
134 | ␉␉␊ |
135 | ␉␉switch (Platform->CPU.Family) ␊ |
136 | ␉␉{␊ |
137 | ␉␉␉case 0x06:␊ |
138 | ␉␉␉{␊ |
139 | ␉␉␉␉switch (Platform->CPU.Model)␊ |
140 | ␉␉␉␉{␊ |
141 | ␉␉␉␉␉case CPU_MODEL_PENTIUM_M:␉␉␉␉␉␉␉// Dothan␊ |
142 | ␉␉␉␉␉case CPU_MODEL_YONAH:␉␉␉␉// Intel Mobile Core Solo, Duo␊ |
143 | ␉␉␉␉␉case CPU_MODEL_MEROM:␉␉␉␉// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx␊ |
144 | ␉␉␉␉␉case CPU_MODEL_PENRYN:␉␉␉␉// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx␊ |
145 | ␉␉␉␉␉case CPU_MODEL_ATOM:␉␉␉␉// Intel Atom (45nm)␊ |
146 | ␉␉␉␉␉␉return true;␊ |
147 | ␊ |
148 | ␉␉␉␉␉case CPU_MODEL_NEHALEM:␉␉␉␉// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)␊ |
149 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Xeon(R)"))␊ |
150 | ␉␉␉␉␉␉␉value->word = 0x0501;␉␉␉// Xeon ␊ |
151 | ␉␉␉␉␉␉else␊ |
152 | ␉␉␉␉␉␉␉value->word = 0x0701;␉␉␉// Core i7␊ |
153 | ␊ |
154 | ␉␉␉␉␉␉return true;␊ |
155 | ␊ |
156 | ␉␉␉␉␉case CPU_MODEL_FIELDS:␉␉␉␉// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)␊ |
157 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
158 | ␉␉␉␉␉␉␉value->word = 0x0601;␉␉␉// Core i5␊ |
159 | ␉␉␉␉␉␉else␊ |
160 | ␉␉␉␉␉␉␉value->word = 0x0701;␉␉␉// Core i7␊ |
161 | ␉␉␉␉␉␉return true;␊ |
162 | ␊ |
163 | ␉␉␉␉␉case CPU_MODEL_DALES:␊ |
164 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
165 | ␉␉␉␉␉␉␉value->word = 0x0601;␉␉␉// Core i5␊ |
166 | ␉␉␉␉␉␉else␊ |
167 | ␉␉␉␉␉␉␉value->word = 0x0701;␉␉␉// Core i7␊ |
168 | ␉␉␉␉␉␉return true;␊ |
169 | ␊ |
170 | ␉␉␉␉␉case CPU_MODEL_SANDY:␉␉␉␉// Intel Core i3, i5, i7 LGA1155 (32nm)␊ |
171 | case CPU_MODEL_SANDY_XEON:␉␉␉// Intel Xeon E3␊ |
172 | ␉␉␉␉␉case CPU_MODEL_DALES_32NM:␉␉␉// Intel Core i3, i5 LGA1156 (32nm)␊ |
173 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i3"))␊ |
174 | ␉␉␉␉␉␉␉value->word = 0x0901;␉␉␉// Core i3␊ |
175 | ␉␉␉␉␉␉else␊ |
176 | ␉␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
177 | ␉␉␉␉␉␉␉␉value->word = 0x0601;␉␉// Core i5␊ |
178 | ␉␉␉␉␉␉␉else␊ |
179 | ␉␉␉␉␉␉␉␉value->word = 0x0701;␉␉// Core i7␊ |
180 | ␉␉␉␉␉␉return true;␊ |
181 | ␊ |
182 | ␉␉␉␉␉case CPU_MODEL_WESTMERE:␉␉␉// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core␊ |
183 | ␉␉␉␉␉case CPU_MODEL_WESTMERE_EX:␉␉␉// Intel Xeon E7␊ |
184 | ␉␉␉␉␉␉value->word = 0x0501;␉␉␉␉// Core i7␊ |
185 | ␉␉␉␉␉␉return true;␊ |
186 | ␊ |
187 | ␉␉␉␉␉case 0x19:␉␉␉␉␉␉␉// ??? Intel Core i5 650 @3.20 GHz␊ |
188 | ␉␉␉␉␉␉value->word = 0x0601;␉␉␉␉// Core i5␊ |
189 | ␉␉␉␉␉␉return true;␊ |
190 | ␉␉␉␉}␊ |
191 | ␉␉␉}␊ |
192 | ␉␉}␊ |
193 | ␉}␊ |
194 | ␉␊ |
195 | ␉return false;␊ |
196 | }␊ |
197 | ␊ |
198 | bool getSMBMemoryDeviceMemoryType(returnType *value)␊ |
199 | {␊ |
200 | ␉static int idx = -1;␊ |
201 | ␉int␉map;␊ |
202 | ␊ |
203 | ␉idx++;␊ |
204 | ␉if (idx < MAX_RAM_SLOTS)␊ |
205 | ␉{␊ |
206 | ␉␉map = Platform->DMI.DIMM[idx];␊ |
207 | ␉␉if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Type != 0)␊ |
208 | ␉␉{␊ |
209 | ␉␉␉msglog("RAM Detected Type = %d\n", Platform->RAM.DIMM[map].Type);␊ |
210 | ␉␉␉value->byte = Platform->RAM.DIMM[map].Type;␊ |
211 | ␉␉␉return true;␊ |
212 | ␉␉}␊ |
213 | ␉}␊ |
214 | ␉␊ |
215 | ␉return false;␊ |
216 | //␉value->byte = SMB_MEM_TYPE_DDR2;␊ |
217 | //␉return true;␊ |
218 | }␊ |
219 | ␊ |
220 | bool getSMBMemoryDeviceMemorySpeed(returnType *value)␊ |
221 | {␊ |
222 | //Slice - do not use SPD value for memory speed. DMI has real value.␊ |
223 | //return false;␊ |
224 | ␉static int idx = -1;␊ |
225 | ␉int␉map;␊ |
226 | ␉idx++;␊ |
227 | ␉if (idx < MAX_RAM_SLOTS)␊ |
228 | ␉{␊ |
229 | ␉␉map = Platform->DMI.DIMM[idx];␊ |
230 | ␉␉if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Frequency != 0)␊ |
231 | ␉␉{␊ |
232 | ␉␉␉msglog("RAM Detected Freq = %d Mhz\n", Platform->RAM.DIMM[map].Frequency);␊ |
233 | ␉␉␉value->dword = Platform->RAM.DIMM[map].Frequency;␊ |
234 | ␉␉␉return true;␊ |
235 | ␉␉}␊ |
236 | ␉}␊ |
237 | ␊ |
238 | ␉return false; ␊ |
239 | //␉value->dword = 800;␊ |
240 | //␉return true;␊ |
241 | }␊ |
242 | ␊ |
243 | bool getSMBMemoryDeviceManufacturer(returnType *value)␊ |
244 | {␊ |
245 | ␉static int idx = -1;␊ |
246 | ␉int␉map;␊ |
247 | ␊ |
248 | ␉idx++;␊ |
249 | ␉if (idx < MAX_RAM_SLOTS)␊ |
250 | ␉{␊ |
251 | ␉␉map = Platform->DMI.DIMM[idx];␊ |
252 | ␉␉if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].Vendor) > 0)␊ |
253 | ␉␉{␊ |
254 | ␉␉␉DBG("RAM Detected Vendor[%d]='%s'\n", idx, Platform->RAM.DIMM[map].Vendor);␊ |
255 | ␉␉␉value->string = Platform->RAM.DIMM[map].Vendor;␊ |
256 | ␉␉␉return true;␊ |
257 | ␉␉}␊ |
258 | ␉}␊ |
259 | ␊ |
260 | ␉if (!bootInfo->memDetect)␊ |
261 | ␉␉return false;␊ |
262 | ␉value->string = NOT_AVAILABLE;␊ |
263 | ␉return true;␊ |
264 | }␊ |
265 | ␉␊ |
266 | bool getSMBMemoryDeviceSerialNumber(returnType *value)␊ |
267 | {␊ |
268 | ␉static int idx = -1;␊ |
269 | ␉int␉map;␊ |
270 | ␊ |
271 | ␉idx++;␊ |
272 | ␊ |
273 | DBG("getSMBMemoryDeviceSerialNumber index: %d, MAX_RAM_SLOTS: %d\n",idx,MAX_RAM_SLOTS);␊ |
274 | ␊ |
275 | ␉if (idx < MAX_RAM_SLOTS)␊ |
276 | ␉{␊ |
277 | ␉␉map = Platform->DMI.DIMM[idx];␊ |
278 | ␉␉if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].SerialNo) > 0)␊ |
279 | ␉␉{␊ |
280 | ␉␉␉DBG("map=%d, RAM Detected SerialNo[%d]='%s'\n", map, idx, Platform->RAM.DIMM[map].SerialNo);␊ |
281 | ␉␉␉value->string = Platform->RAM.DIMM[map].SerialNo;␊ |
282 | ␉␉␉return true;␊ |
283 | ␉␉}␊ |
284 | ␉}␊ |
285 | ␊ |
286 | ␉if (!bootInfo->memDetect)␊ |
287 | ␉␉return false;␊ |
288 | ␉value->string = NOT_AVAILABLE;␊ |
289 | ␉return true;␊ |
290 | }␊ |
291 | ␊ |
292 | bool getSMBMemoryDevicePartNumber(returnType *value)␊ |
293 | {␊ |
294 | ␉static int idx = -1;␊ |
295 | ␉int␉map;␊ |
296 | ␊ |
297 | ␉idx++;␊ |
298 | ␉if (idx < MAX_RAM_SLOTS)␊ |
299 | ␉{␊ |
300 | ␉␉map = Platform->DMI.DIMM[idx];␊ |
301 | ␉␉if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].PartNo) > 0)␊ |
302 | ␉␉{␊ |
303 | ␉␉␉DBG("map=%d, RAM Detected PartNo[%d]='%s'\n", map, idx, Platform->RAM.DIMM[map].PartNo);␊ |
304 | ␉␉␉value->string = Platform->RAM.DIMM[map].PartNo;␊ |
305 | ␉␉␉return true;␊ |
306 | ␉␉}␊ |
307 | ␉}␊ |
308 | ␊ |
309 | ␉if (!bootInfo->memDetect)␊ |
310 | ␉␉return false;␊ |
311 | ␉value->string = NOT_AVAILABLE;␊ |
312 | ␉return true;␊ |
313 | }␊ |
314 | ␊ |
315 | ␊ |
316 | // getting smbios addr with fast compare ops, late checksum testing ...␊ |
317 | #define COMPARE_DWORD(a,b) ( *((uint32_t *) a) == *((uint32_t *) b) )␊ |
318 | static const char * const SMTAG = "_SM_";␊ |
319 | static const char* const DMITAG = "_DMI_";␊ |
320 | ␊ |
321 | SMBEntryPoint *getAddressOfSmbiosTable(void)␊ |
322 | {␊ |
323 | ␉SMBEntryPoint␉*smbios;␊ |
324 | ␉/* ␊ |
325 | ␉ * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking␊ |
326 | ␉ * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_").␊ |
327 | ␉ */␊ |
328 | ␉smbios = (SMBEntryPoint*)SMBIOS_RANGE_START;␊ |
329 | ␉while (smbios <= (SMBEntryPoint *)SMBIOS_RANGE_END) {␊ |
330 | ␉␉if (COMPARE_DWORD(smbios->anchor, SMTAG) && ␊ |
331 | ␉␉␉COMPARE_DWORD(smbios->dmi.anchor, DMITAG) &&␊ |
332 | ␉␉␉smbios->dmi.anchor[4] == DMITAG[4] &&␊ |
333 | ␉␉␉checksum8(smbios, sizeof(SMBEntryPoint)) == 0)␊ |
334 | ␉ {␊ |
335 | ␉␉␉return smbios;␊ |
336 | ␉ }␊ |
337 | ␉␉smbios = (SMBEntryPoint*)(((char*)smbios) + 16);␊ |
338 | ␉}␊ |
339 | ␉printf("ERROR: Unable to find SMBIOS!\n");␊ |
340 | ␉pause();␊ |
341 | ␉return NULL;␊ |
342 | }␊ |
343 | ␊ |
344 | void getSmbiosMacModel(void)␊ |
345 | {␊ |
346 | #define MAX_MODEL_LEN␉32␊ |
347 | ␉␊ |
348 | ␉//Slice - I want to use MacModel for ACPITables so I need char* representation␊ |
349 | ␉const char␉*value = getStringForKey("SMproductname", &bootInfo->smbiosConfig);␊ |
350 | ␉int i, n=0, first=0, rev1=0, rev2=0;␉␉␊ |
351 | ␉for (i=0; i<8; i++) ␊ |
352 | ␉{␊ |
353 | ␉␉char c = value[i];␊ |
354 | ␉␉if (isalpha(c))␊ |
355 | ␉␉{␊ |
356 | ␉␉␉MacModel[i]=c;␊ |
357 | ␉␉␉n++;␊ |
358 | ␉␉} else ␊ |
359 | ␉␉␉if ((c) >= '0' && (c) <= '9')␊ |
360 | ␉␉␉{␊ |
361 | ␉␉␉␉if (first)␊ |
362 | ␉␉␉␉{␊ |
363 | ␉␉␉␉␉rev1 = rev1 * 10 + (int)(c) & 0xf;␊ |
364 | ␉␉␉␉} else␊ |
365 | ␉␉␉␉␉rev2 = rev2 * 10 + (int)(c) & 0xf;␊ |
366 | ␉␉␉} else ␊ |
367 | ␉␉␉␉first = 1;␊ |
368 | ␉␉//␉␉␉␉printf("char=%c first=%d rev1=%d rev2=%d\n", c, first, rev1, rev2);␊ |
369 | ␉}␊ |
370 | ␉for (i=n; i<8; i++) {␊ |
371 | ␉␉MacModel[i] = 0x20;␊ |
372 | ␉}␊ |
373 | ␉ModelRev = (rev2 << 16) + rev1;␊ |
374 | ␉//␉␉ModelLength = (len + 1) * 2;␊ |
375 | ␉//␉␉printf("Model=%s %08x\n", MacModel, ModelRev);␊ |
376 | ␉//␉␉getc();␊ |
377 | ␉␊ |
378 | }␊ |
379 | ␊ |
380 | //static struct SMBEntryPoint *orig = NULL; // cached␊ |
381 | //static struct SMBEntryPoint *patched = NULL; // cached␊ |
382 | void getSmbiosProductName()␊ |
383 | {␊ |
384 | ␉//␉struct SMBEntryPoint␉*smbios;␊ |
385 | ␉SMBSystemInformation␉*p;␊ |
386 | ␉char*␉␉␉␉␉tempString;␊ |
387 | ␉int␉␉␉␉␉␉tmpLen;␊ |
388 | ␉␊ |
389 | ␉//␉smbios = getSmbios(SMBIOS_ORIGINAL);␊ |
390 | ␉//␉if (smbios==NULL) return 0; ␊ |
391 | ␉␊ |
392 | ␉p = (SMBSystemInformation*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information␊ |
393 | ␉if (p==NULL) return; // NULL;␊ |
394 | ␉␊ |
395 | ␉tempString = (char*)smbiosStringAtIndex((SMBStructHeader*)p, p->productName, &tmpLen);␊ |
396 | ␉tempString[tmpLen] = 0;␊ |
397 | ␉␊ |
398 | ␉gSMBIOSBoardModel = malloc(tmpLen + 1);␊ |
399 | ␉if(gSMBIOSBoardModel)␊ |
400 | ␉{␊ |
401 | ␉␉strncpy(gSMBIOSBoardModel, tempString, tmpLen);␊ |
402 | ␉␉Node* node = DT__FindNode("/", false);␊ |
403 | ␉␉DT__AddProperty(node, "orig-model", tmpLen, gSMBIOSBoardModel);␊ |
404 | ␉}␊ |
405 | ␉verbose("Actual model name is '%s'\n", tempString);␊ |
406 | }␊ |
407 | ␊ |
408 | const char * smbiosStringAtIndex(SMBStructHeader* smHeader, int index, int* length )␊ |
409 | {␊ |
410 | const char * last = 0;␊ |
411 | const char * next = (const char *) smHeader + smHeader->length;␊ |
412 | ␉␊ |
413 | if ( length ) *length = 0;␊ |
414 | while ( index-- )␊ |
415 | {␊ |
416 | last = 0;␊ |
417 | ␉␉const char * cp = 0;␊ |
418 | ␉␉for ( cp = next; *cp || cp[1]; cp++ )␊ |
419 | {␊ |
420 | if ( *cp == '\0' )␊ |
421 | {␊ |
422 | last = next;␊ |
423 | next = cp + 1;␊ |
424 | break;␊ |
425 | }␊ |
426 | }␊ |
427 | if ( last == 0 ) break;␊ |
428 | }␊ |
429 | ␉␊ |
430 | if ( last )␊ |
431 | {␊ |
432 | while (*last == ' ') last++;␊ |
433 | if (length)␊ |
434 | {␊ |
435 | UInt8 len;␊ |
436 | for ( len = next - last - 1; len && last[len - 1] == ' '; len-- )␊ |
437 | ;␊ |
438 | *length = len; // number of chars not counting the terminating NULL␊ |
439 | }␊ |
440 | }␊ |
441 | ␉␊ |
442 | return last ? last : "";␊ |
443 | }␊ |
444 | ␊ |
445 | //Slice␊ |
446 | //#define MEGA 1000000LL - now in platform.h␊ |
447 | void scan_cpu_DMI(void) //PlatformInfo_t *p)␊ |
448 | {␊ |
449 | ␉// int i=0;␊ |
450 | ␉int maxClock = 0;␊ |
451 | SMBStructHeader * dmihdr = NULL; ␊ |
452 | SMBProcessorInformation* cpuInfo; // Type 4␊ |
453 | ␉␊ |
454 | ␉for (dmihdr = FindFirstDmiTableOfType(4, 30); dmihdr; dmihdr = FindNextDmiTableOfType(4, 30)) ␊ |
455 | ␉{␊ |
456 | ␉␉cpuInfo = (SMBProcessorInformation*)dmihdr;␊ |
457 | ␉␉if (cpuInfo->processorType != 3) { // CPU␊ |
458 | ␉␉␉continue;␊ |
459 | ␉␉}␊ |
460 | ␉␉//TODO validate␊ |
461 | #if DEBUG_SMBIOS␉␊ |
462 | ␉␉msglog("Platform CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", Platform->CPU.FSBFrequency/MEGA, Platform->CPU.TSCFrequency/MEGA, Platform->CPU.CPUFrequency/MEGA);␊ |
463 | ␉␉␊ |
464 | ␉␉if ((cpuInfo->externalClock) && (cpuInfo->externalClock < 400)) { //<400MHz␊ |
465 | ␉␉␉Platform->CPU.FSBFrequency = (cpuInfo->externalClock) * MEGA;␊ |
466 | ␉␉}␊ |
467 | ␉␉maxClock = cpuInfo->maximumClock;␊ |
468 | ␉␉if (cpuInfo->maximumClock < cpuInfo->currentClock) {␊ |
469 | ␉␉␉maxClock = cpuInfo->currentClock;␊ |
470 | ␉␉}␊ |
471 | ␉␉if ((maxClock) && (maxClock < 10000)) { //<10GHz␊ |
472 | ␉␉␉Platform->CPU.TSCFrequency = maxClock * MEGA;␊ |
473 | ␉␉}␊ |
474 | ␉␉if ((cpuInfo->currentClock) && (cpuInfo->currentClock < 10000)) { //<10GHz␊ |
475 | ␉␉␉Platform->CPU.CPUFrequency = cpuInfo->currentClock * MEGA;␊ |
476 | ␉␉}␊ |
477 | #endif␊ |
478 | ␉␉maxClock = cpuInfo->maximumClock;␊ |
479 | ␉␉Platform->CPU.CPUFrequency = cpuInfo->currentClock * MEGA;␊ |
480 | ␉␉msglog("DMI CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", cpuInfo->externalClock, maxClock, cpuInfo->currentClock);␊ |
481 | ␉␉msglog("DMI CPU Info 2:\n Family=%x\n Socket=%x\n Cores=%d Enabled=%d Threads=%d\n", cpuInfo->processorFamily, cpuInfo->processorUpgrade, cpuInfo->coreCount, cpuInfo->coreEnabled, cpuInfo->Threads);␊ |
482 | #if 1 //NOTYET␊ |
483 | ␉␉if ((cpuInfo->coreCount) && (cpuInfo->coreCount<Platform->CPU.NoCores)) {␊ |
484 | ␉␉␉if (cpuInfo->coreEnabled < cpuInfo->coreCount) {␊ |
485 | ␉␉␉␉cpuInfo->coreCount = cpuInfo->coreEnabled;␊ |
486 | ␉␉␉}␊ |
487 | ␉␉␉Platform->CPU.NoCores = cpuInfo->coreCount;␊ |
488 | ␉␉}␊ |
489 | ␉␉if ((cpuInfo->Threads) && (cpuInfo->Threads<Platform->CPU.NoThreads)) {␉␉␊ |
490 | ␉␉␉Platform->CPU.NoThreads = cpuInfo->Threads;␊ |
491 | ␉␉}␊ |
492 | #endif␊ |
493 | ␉␉␊ |
494 | ␉␉return;␊ |
495 | ␉}␊ |
496 | ␉␊ |
497 | ␉return;␊ |
498 | }␊ |
499 | |