Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/SMBiosPatcher/smbios_patcher.c

1/*
2 * Copyright 2008 mackerintel
3 */
4
5#include "libsaio.h"
6#include "boot.h"
7#include "bootstruct.h"
8#include "acpi.h"
9#include "efi_tables.h"
10#include "fake_efi.h"
11#include "platform.h"
12#include "smbios_patcher.h"
13#include "pci.h"
14#include "cpu.h"
15#include "modules.h"
16
17#ifndef DEBUG_SMBIOS
18#define DEBUG_SMBIOS 0
19#endif
20
21#if DEBUG_SMBIOS==2
22#define DBG(x...)printf(x)
23#elif DEBUG_SMBIOS==1
24#define DBG(x...) msglog(x)
25#else
26#define DBG(x...)
27#endif
28
29char* gSMBIOSBoardModel;
30
31typedef struct {
32 const char* key;
33 const char* value;
34} SMStrEntryPair;
35
36// defaults for a MacBook
37static const SMStrEntryPair const sm_macbook_defaults[]={
38{"SMbiosvendor","Apple Inc."},
39{"SMbiosversion","MB41.88Z.00C1.B00.0802091535"},
40{"SMbiosdate","02/09/2008"},
41{"SMmanufacter","Apple Inc."},
42{"SMproductname","MacBook4,1"},
43{"SMsystemversion","1.0"},
44{"SMserial","RM83064H0P1"},
45{"SMfamily","MacBook"},
46{"SMboardmanufacter","Apple Inc."},
47{"SMboardproduct","Mac-F22788A9"},
48{ "",""}
49};
50
51// defaults for a MacBook Pro
52static const SMStrEntryPair const sm_macbookpro_defaults[]={
53{"SMbiosvendor","Apple Inc."},
54{"SMbiosversion","MBP41.88Z.00C1.B03.0802271651"},
55{"SMbiosdate","02/27/2008"},
56{"SMmanufacter","Apple Inc."},
57{"SMproductname","MacBookPro4,1"},
58{"SMsystemversion","1.0"},
59{"SMserial","W88198N6YJX"},
60{"SMfamily","MacBookPro"},
61{"SMboardmanufacter","Apple Inc."},
62{"SMboardproduct","Mac-F42C89C8"},
63{ "",""}
64};
65
66// defaults for a Mac mini
67static const SMStrEntryPair const sm_macmini_defaults[]={
68{"SMbiosvendor","Apple Inc."},
69{"SMbiosversion","MM21.88Z.009A.B00.0706281359"},
70{"SMbiosdate","06/28/2007"},
71{"SMmanufacter","Apple Inc."},
72{"SMproductname","Macmini2,1"},
73{"SMsystemversion","1.0"},
74{"SMserial","YM8054BYYL2"},
75{"SMfamily","Napa Mac"},
76{"SMboardmanufacter","Apple Inc."},
77{"SMboardproduct","Mac-F4208EAA"},
78{ "",""}
79};
80
81// defaults for an iMac
82static const SMStrEntryPair const sm_imac_defaults[]={
83{"SMbiosvendor","Apple Inc."},
84{"SMbiosversion","IM71.88Z.007A.B03.0803051705"},
85{"SMbiosdate","03/05/2008"},
86{"SMmanufacter","Apple Inc."},
87{"SMproductname","iMac7,1"},
88{"SMsystemversion","1.0"},
89{"SMserial","W87410PWX87"},
90{"SMfamily","Mac"},
91{"SMboardmanufacter","Apple Inc."},
92{"SMboardproduct","Mac-F4238CC8"},
93{ "",""}
94};
95
96// defaults for a Mac Pro
97static const SMStrEntryPair const sm_macpro_defaults[]={
98{"SMbiosvendor","Apple Computer, Inc."},
99{"SMbiosversion","MP31.88Z.006C.B02.0801021250"},
100{"SMbiosdate","01/02/2008"},
101{"SMmanufacter","Apple Computer, Inc."},
102{"SMproductname","MacPro3,1"},
103{"SMsystemversion","1.0"},
104{"SMserial","G88014V4XYK"},
105{"SMfamily","MacPro"},
106{"SMboardmanufacter","Apple Computer, Inc."},
107{"SMboardproduct","Mac-F42C88C8"},
108{ "",""}
109};
110
111// defaults for an iMac11,1 core i3/i5/i7
112static const SMStrEntryPair const sm_imac_core_defaults[]={
113{"SMbiosvendor","Apple Inc."},
114{"SMbiosversion","IM111.88Z.0034.B00.0910301727"},
115{"SMbiosdate","10/30/2009"},
116{"SMmanufacter","Apple Inc."},
117{"SMproductname","iMac11,1"},
118{"SMsystemversion","1.0"},
119{"SMserial","W89470DZ5RU"},
120{"SMfamily","iMac"},
121{"SMboardmanufacter","Apple Inc." },
122{"SMboardproduct","Mac-F2268DAE"},
123{ "",""}
124};
125
126// defaults for an iMac12,1 : todo: populate correctly
127static const SMStrEntryPair const sm_imac_sandy_defaults[]={
128{"SMbiosvendor","Apple Inc."},
129{"SMbiosversion","IM121.88Z.0047.B00.1102091756"},
130{"SMbiosdate","10/30/2011"},
131{"SMmanufacter","Apple Inc."},
132{"SMproductname","iMac12,1"},
133{"SMsystemversion","1.0"},
134{"SMserial","W89470DZ5RU"},
135{"SMfamily","iMac"},
136{"SMboardmanufacter","Apple Inc." },
137{"SMboardproduct","Mac-F2268DAE"},
138{ "",""}
139};
140
141// defaults for a Mac Pro 4,1 core i7/Xeon
142static const SMStrEntryPair const sm_macpro_core_defaults[]={
143{"SMbiosvendor","Apple Computer, Inc."},
144{"SMbiosversion","MP41.88Z.0081.B03.0902231259"},
145{"SMbiosdate","02/23/2009"},
146{"SMmanufacter","Apple Inc." },
147{"SMproductname","MacPro4,1"},
148{"SMsystemversion","1.0"},
149{"SMserial","CK91601V8Q0"},
150{"SMfamily","MacPro"},
151{"SMboardmanufacter","Apple Computer, Inc."},
152{"SMboardproduct","Mac-F221BEC8"},
153{ "",""}
154};
155
156// default for a Xserve
157static const SMStrEntryPair const sm_xserve_defaults[]={
158 {"SMbiosvendor","Apple Inc."},
159 {"SMbiosversion","XS21.88Z.006C.B06.0804011317"},
160 {"SMbiosdate","04/01/2008"},
161 {"SMmanufacter","Apple Inc."},
162 {"SMproductname","Xserve2,1"},
163 {"SMsystemversion","1.0"},
164 {"SMserial","CK816033X8S"},
165 {"SMfamily","Xserve"},
166 {"SMboardmanufacter","Apple Inc."},
167 {"SMboardproduct","Mac-F42289C8"},
168 { "",""}
169};
170
171/*static */const char* sm_get_defstr(const char * key, int table_num)
172{
173inti;
174const SMStrEntryPair*sm_defaults;
175
176if (Platform->CPU.isServer == true)
177 {
178 sm_defaults=sm_xserve_defaults;
179 } else if (Platform->CPU.isMobile == true) {
180if (Platform->CPU.NoCores > 1) {
181sm_defaults=sm_macbookpro_defaults;
182} else {
183sm_defaults=sm_macbook_defaults;
184}
185} else {
186switch (Platform->CPU.NoCores)
187{
188case 1:
189sm_defaults=sm_macmini_defaults;
190break;
191case 2:
192sm_defaults=sm_imac_defaults;
193break;
194default:
195{
196switch (Platform->CPU.Family)
197{
198case 0x06:
199{
200switch (Platform->CPU.Model)
201{
202case CPUID_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
203case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???
204case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)
205case 0x19: // Intel Core i5 650 @3.20 Ghz
206sm_defaults=sm_imac_core_defaults;
207break;
208
209 case CPUID_MODEL_SANDYBRIDGE:
210 case CPUID_MODEL_JAKETOWN:
211 sm_defaults=sm_imac_sandy_defaults;
212 break;
213
214case CPUID_MODEL_NEHALEM:
215case CPUID_MODEL_NEHALEM_EX:
216case CPUID_MODEL_WESTMERE:
217case CPUID_MODEL_WESTMERE_EX:
218sm_defaults=sm_macpro_core_defaults;
219break;
220default:
221sm_defaults=sm_macpro_defaults;
222break;
223}
224break;
225}
226default:
227sm_defaults=sm_macpro_defaults;
228break;
229}
230break;
231}
232}
233}
234
235for (i=0; sm_defaults[i].key[0]; i++) {
236if (!strcmp (sm_defaults[i].key, key)) {
237return sm_defaults[i].value;
238}
239}
240
241// Shouldn't happen
242printf ("Error: no default for '%s' known\n", key);
243sleep (2);
244return "";
245}
246
247static int sm_get_fsb(const char *name, int table_num)
248{
249return Platform->CPU.FSBFrequency/1000000;
250}
251
252static int sm_get_cpu (const char *name, int table_num)
253{
254return Platform->CPU.CPUFrequency/1000000;
255}
256
257static int sm_get_bus_speed (const char *name, int table_num)
258{
259if (Platform->CPU.Vendor == 0x756E6547) // Intel
260{
261switch (Platform->CPU.Family)
262{
263case 0x06:
264{
265switch (Platform->CPU.Model)
266{
267 case CPUID_MODEL_BANIAS:// Banias0x09
268 case CPUID_MODEL_DOTHAN:// Dothan0x0D
269case CPUID_MODEL_YONAH:// Yonah0x0E
270case CPUID_MODEL_MEROM:// Merom0x0F
271case CPUID_MODEL_PENRYN:// Penryn0x17
272case CPUID_MODEL_ATOM:// Atom 45nm0x1C
273return 0; // TODO: populate bus speed for these processors
274
275//case CPUID_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
276//if (strstr(Platform.CPU.BrandString, "Core(TM) i5"))
277//return 2500; // Core i5
278//return 4800; // Core i7
279
280//case CPUID_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
281//case CPUID_MODEL_NEHALEM_EX:
282//case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???
283//return 4800; // GT/s / 1000
284//
285case CPUID_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
286return 0; // TODO: populate bus speed for these processors
287
288//case 0x19: // Intel Core i5 650 @3.20 Ghz
289//return 2500; // why? Intel spec says 2.5GT/s
290
291case 0x19: // Intel Core i5 650 @3.20 Ghz
292case CPUID_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
293case CPUID_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
294case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???
295case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm)
296 case CPUID_MODEL_SANDYBRIDGE:
297 case CPUID_MODEL_JAKETOWN:
298case CPUID_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core
299case CPUID_MODEL_NEHALEM_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
300{ // thanks to dgobe for i3/i5/i7 bus speed detection
301int nhm_bus = 0x3F;
302static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
303unsigned long did, vid;
304int i;
305
306// Nehalem supports Scrubbing
307// First, locate the PCI bus where the MCH is located
308for(i = 0; i < sizeof(possible_nhm_bus); i++)
309{
310vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00);
311did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02);
312vid &= 0xFFFF;
313did &= 0xFF00;
314
315if(vid == 0x8086 && did >= 0x2C00)
316nhm_bus = possible_nhm_bus[i];
317}
318
319unsigned long qpimult, qpibusspeed;
320qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50);
321qpimult &= 0x7F;
322DBG("qpimult %d\n", qpimult);
323qpibusspeed = (qpimult * 2 * (Platform->CPU.FSBFrequency/1000000));
324// Rek: rounding decimals to match original mac profile info
325if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100;
326DBG("qpibusspeed %d\n", qpibusspeed);
327return qpibusspeed;
328}
329}
330}
331}
332}
333return 0;
334}
335
336static int sm_get_simplecputype()
337{
338if (Platform->CPU.NoCores >= 4)
339{
340return 0x0501; // Quad-Core Xeon
341}
342if (((Platform->CPU.NoCores == 1) || (Platform->CPU.NoCores == 2)) && !(platformCPUExtFeature(CPUID_EXTFEATURE_EM64T)))
343{
344return 0x0201; // Core Solo / Duo
345}
346
347return 0x0301; // Core 2 Solo / Duo
348}
349
350static int sm_get_cputype (const char *name, int table_num)
351{
352static bool done = false;
353
354if (Platform->CPU.Vendor == 0x756E6547) // Intel
355{
356if (!done) {
357verbose("CPU is %s, family 0x%x, model 0x%x\n", Platform->CPU.BrandString, Platform->CPU.Family, Platform->CPU.Model);
358done = true;
359}
360
361switch (Platform->CPU.Family)
362{
363case 0x06:
364{
365switch (Platform->CPU.Model)
366{
367 case CPUID_MODEL_BANIAS: // Banias
368 case CPUID_MODEL_DOTHAN: // Dothan
369case CPUID_MODEL_YONAH: // Yonah
370case CPUID_MODEL_MEROM: // Merom
371case CPUID_MODEL_PENRYN: // Penryn
372case CPUID_MODEL_ATOM: // Intel Atom (45nm)
373return sm_get_simplecputype();
374
375case CPUID_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
376return 0x0701; // Core i7
377
378case CPUID_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper
379if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))
380return 0x601; // Core i5
381return 0x701; // Core i7
382
383case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale)
384if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))
385return 0x601; // Core i5
386return 0x0701; // Core i7
387
388 case CPUID_MODEL_SANDYBRIDGE: // Sandybridge
389case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)
390if (strstr(Platform->CPU.BrandString, "Core(TM) i3"))
391return 0x901; // Core i3
392if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))
393return 0x601; // Core i5
394if (strstr(Platform->CPU.BrandString, "Core(TM) i7"))
395return 0x0701; // Core i7
396return sm_get_simplecputype();
397
398 case CPUID_MODEL_JAKETOWN:
399case CPUID_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS)
400case CPUID_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
401return 0x0701; // Core i7
402
403case 0x19: // Intel Core i5 650 @3.20 Ghz
404return 0x601; // Core i5
405}
406}
407}
408}
409
410return sm_get_simplecputype();
411}
412
413static int sm_get_memtype (const char *name, int table_num)
414{
415if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
416intmap;
417
418if (table_num < MAX_RAM_SLOTS) {
419map = Platform->DMI.DIMM[table_num];
420if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Type != 0) {
421 DBG("RAM Detected Type = %d\n", Platform->RAM.DIMM[map].Type);
422 return Platform->RAM.DIMM[map].Type;
423}
424}
425}
426
427return SMB_MEM_TYPE_DDR2;
428}
429
430static int sm_get_memspeed (const char *name, int table_num)
431{
432if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
433intmap;
434
435if (table_num < MAX_RAM_SLOTS) {
436map = Platform->DMI.DIMM[table_num];
437if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Frequency != 0) {
438 DBG("RAM Detected Freq = %d Mhz\n", Platform->RAM.DIMM[map].Frequency);
439 return Platform->RAM.DIMM[map].Frequency;
440}
441}
442}
443return 800;
444}
445
446static const char *sm_get_memvendor (const char *name, int table_num)
447{
448if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
449intmap;
450
451if (table_num < MAX_RAM_SLOTS) {
452map = Platform->DMI.DIMM[table_num];
453if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].Vendor) > 0) {
454DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].Vendor);
455return Platform->RAM.DIMM[map].Vendor;
456}
457}
458}
459return "N/A";
460}
461
462static const char *sm_get_memserial (const char *name, int table_num)
463{
464if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
465intmap;
466
467if (table_num < MAX_RAM_SLOTS) {
468map = Platform->DMI.DIMM[table_num];
469if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].SerialNo) > 0) {
470 DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "",
471 map, table_num, Platform->RAM.DIMM[map].SerialNo);
472 return Platform->RAM.DIMM[map].SerialNo;
473}
474}
475 }
476return "N/A";
477}
478
479static const char *sm_get_mempartno (const char *name, int table_num)
480{
481if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
482intmap;
483
484if (table_num < MAX_RAM_SLOTS) {
485map = Platform->DMI.DIMM[table_num];
486if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].PartNo) > 0) {
487DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].PartNo);
488return Platform->RAM.DIMM[map].PartNo;
489}
490}
491}
492return "N/A";
493}
494
495static int sm_one (int tablen)
496{
497return 1;
498}
499
500struct smbios_property smbios_properties[]=
501{
502{.name="SMbiosvendor",.table_type= 0,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
503{.name="SMbiosversion",.table_type= 0,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
504{.name="SMbiosdate",.table_type= 0,.value_type=SMSTRING,.offset=0x08,.auto_str=sm_get_defstr},
505{.name="SMmanufacter",.table_type= 1,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
506{.name="SMproductname",.table_type= 1,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
507{.name="SMsystemversion",.table_type= 1,.value_type=SMSTRING,.offset=0x06,.auto_str=sm_get_defstr},
508{.name="SMserial",.table_type= 1,.value_type=SMSTRING,.offset=0x07,.auto_str=sm_get_defstr},
509{.name="SMUUID",.table_type= 1, .value_type=SMOWORD,.offset=0x08,.auto_oword=0},
510{.name="SMfamily",.table_type= 1,.value_type=SMSTRING,.offset=0x1a,.auto_str=sm_get_defstr},
511{.name="SMboardmanufacter",.table_type= 2, .value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
512{.name="SMboardproduct",.table_type= 2, .value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
513{.name="SMexternalclock",.table_type= 4,.value_type=SMWORD,.offset=0x12,.auto_int=sm_get_fsb},
514{.name="SMmaximalclock",.table_type= 4,.value_type=SMWORD,.offset=0x14,.auto_int=sm_get_cpu},
515{.name="SMmemdevloc",.table_type=17,.value_type=SMSTRING,.offset=0x10,.auto_str=0},
516{.name="SMmembankloc",.table_type=17,.value_type=SMSTRING,.offset=0x11,.auto_str=0},
517{.name="SMmemtype",.table_type=17,.value_type=SMBYTE,.offset=0x12,.auto_int=sm_get_memtype},
518{.name="SMmemspeed",.table_type=17,.value_type=SMWORD,.offset=0x15,.auto_int=sm_get_memspeed},
519{.name="SMmemmanufacter",.table_type=17,.value_type=SMSTRING,.offset=0x17,.auto_str=sm_get_memvendor},
520{.name="SMmemserial",.table_type=17,.value_type=SMSTRING,.offset=0x18,.auto_str=sm_get_memserial},
521{.name="SMmempart",.table_type=17,.value_type=SMSTRING,.offset=0x1A,.auto_str=sm_get_mempartno},
522{.name="SMcputype",.table_type=131,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_cputype},
523{.name="SMbusspeed",.table_type=132,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_bus_speed}
524};
525
526struct smbios_table_description smbios_table_descriptions[]=
527{
528{.type=0,.len=0x18,.numfunc=sm_one},
529{.type=1,.len=0x1b,.numfunc=sm_one},
530{.type=2,.len=0x0f,.numfunc=sm_one},
531{.type=4,.len=0x2a,.numfunc=sm_one},
532{.type=17,.len=0x1c,.numfunc=0},
533{.type=131,.len=0x06,.numfunc=sm_one},
534{.type=132,.len=0x06,.numfunc=sm_one}
535};
536
537/** Compute necessary space requirements for new smbios */
538static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)
539{
540struct SMBEntryPoint*ret;
541char*smbiostables;
542char*tablesptr;
543intorigsmbiosnum;
544inti, j;
545inttablespresent[256];
546booldo_auto=true;
547
548bzero(tablespresent, sizeof(tablespresent));
549
550getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
551
552ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));
553if (origsmbios) {
554smbiostables = (char *)origsmbios->dmi.tableAddress;
555origsmbiosnum = origsmbios->dmi.structureCount;
556} else {
557smbiostables = NULL;
558origsmbiosnum = 0;
559}
560
561// _SM_
562ret->anchor[0] = 0x5f;
563ret->anchor[1] = 0x53;
564ret->anchor[2] = 0x4d;
565ret->anchor[3] = 0x5f;
566ret->entryPointLength = sizeof(*ret);
567ret->majorVersion = 2;
568ret->minorVersion = 1;
569ret->maxStructureSize = 0; // will be calculated later in this function
570ret->entryPointRevision = 0;
571for (i=0;i<5;i++) {
572ret->formattedArea[i] = 0;
573}
574//_DMI_
575ret->dmi.anchor[0] = 0x5f;
576ret->dmi.anchor[1] = 0x44;
577ret->dmi.anchor[2] = 0x4d;
578ret->dmi.anchor[3] = 0x49;
579ret->dmi.anchor[4] = 0x5f;
580ret->dmi.tableLength = 0; // will be calculated later in this function
581ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()
582ret->dmi.structureCount = 0; // will be calculated later in this function
583ret->dmi.bcdRevision = 0x21;
584tablesptr = smbiostables;
585
586 // add stringlen of overrides to original stringlen, update maxStructure size adequately,
587 // update structure count and tablepresent[type] with count of type.
588if (smbiostables) {
589for (i=0; i<origsmbiosnum; i++) {
590struct smbios_table_header*cur = (struct smbios_table_header *)tablesptr;
591char*stringsptr;
592intstringlen;
593
594tablesptr += cur->length;
595stringsptr = tablesptr;
596for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);
597tablesptr += 2;
598stringlen = tablesptr - stringsptr - 1;
599if (stringlen == 1) {
600stringlen = 0;
601}
602for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
603const char*str;
604intsize;
605charaltname[40];
606
607sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);
608if (smbios_properties[j].table_type == cur->type &&
609 smbios_properties[j].value_type == SMSTRING &&
610 (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) ||
611 getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))
612{
613stringlen += size + 1;
614} else if (smbios_properties[j].table_type == cur->type &&
615 smbios_properties[j].value_type == SMSTRING &&
616 do_auto && smbios_properties[j].auto_str)
617{
618stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
619}
620}
621if (stringlen == 0) {
622stringlen = 1;
623}
624stringlen++;
625if (ret->maxStructureSize < cur->length+stringlen) {
626ret->maxStructureSize=cur->length+stringlen;
627}
628ret->dmi.tableLength += cur->length+stringlen;
629ret->dmi.structureCount++;
630tablespresent[cur->type]++;
631}
632}
633 // Add eventually table types whose detected count would be < required count, and update ret header with:
634 // new stringlen addons, structure count, and tablepresent[type] count adequately
635for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
636intnumnec=-1;
637charbuffer[40];
638
639sprintf(buffer, "SMtable%d", i);
640if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
641numnec = -1;
642}
643if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {
644numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
645}
646while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
647intstringlen = 0;
648for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
649const char*str;
650intsize;
651charaltname[40];
652
653sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);
654if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
655 smbios_properties[j].value_type == SMSTRING &&
656 (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
657 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)))
658{
659stringlen += size + 1;
660} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
661 smbios_properties[j].value_type==SMSTRING &&
662 do_auto && smbios_properties[j].auto_str)
663{
664stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
665}
666}
667if (stringlen == 0) {
668stringlen = 1;
669}
670stringlen++;
671if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {
672ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;
673}
674ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;
675ret->dmi.structureCount++;
676tablespresent[smbios_table_descriptions[i].type]++;
677}
678}
679return ret;
680}
681
682/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint
683 * struct has been created by smbios_dry_run, update each table struct content of new smbios
684 * int the new allocated table address of size newsmbios->tablelength.
685 */
686static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)
687{
688char *smbiostables;
689char *tablesptr, *newtablesptr;
690int origsmbiosnum;
691// bitmask of used handles
692uint8_t handles[8192];
693uint16_t nexthandle=0;
694int i, j;
695int tablespresent[256];
696bool do_auto=true;
697
698 static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info !
699
700bzero(tablespresent, sizeof(tablespresent));
701bzero(handles, sizeof(handles));
702
703getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
704
705newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);
706if (origsmbios) {
707smbiostables = (char *)origsmbios->dmi.tableAddress;
708origsmbiosnum = origsmbios->dmi.structureCount;
709} else {
710smbiostables = NULL;
711origsmbiosnum = 0;
712}
713tablesptr = smbiostables;
714newtablesptr = (char *)newsmbios->dmi.tableAddress;
715
716 // if old smbios exists then update new smbios with old smbios original content first
717if (smbiostables) {
718for (i=0; i<origsmbiosnum; i++) {
719struct smbios_table_header*oldcur = (struct smbios_table_header *) tablesptr;
720struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
721char*stringsptr;
722intnstrings = 0;
723
724handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);
725
726 // copy table length from old table to new table but not the old strings
727memcpy(newcur,oldcur, oldcur->length);
728
729tablesptr += oldcur->length;
730stringsptr = tablesptr;
731newtablesptr += oldcur->length;
732
733 // calculate the number of strings in the old content
734for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {
735if (tablesptr[0] == 0) {
736nstrings++;
737}
738}
739if (tablesptr != stringsptr) {
740nstrings++;
741}
742tablesptr += 2;
743
744 // copy the old strings to new table
745memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);
746
747 // point to next possible space for a string (deducting the second 0 char at the end)
748newtablesptr += tablesptr - stringsptr - 1;
749 if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator
750newtablesptr--;
751}
752
753 // now for each property in the table update the overrides if any (auto or user)
754for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
755const char*str;
756intsize;
757intnum;
758charaltname[40];
759
760sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
761if (smbios_properties[j].table_type == newcur->type) {
762switch (smbios_properties[j].value_type) {
763case SMSTRING:
764if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
765 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
766{
767memcpy(newtablesptr, str, size);
768newtablesptr[size] = 0;
769newtablesptr += size + 1;
770*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
771} else if (do_auto && smbios_properties[j].auto_str) {
772str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
773size = strlen(str);
774memcpy(newtablesptr, str, size);
775newtablesptr[size] = 0;
776newtablesptr += size + 1;
777*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
778}
779break;
780
781case SMOWORD:
782if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
783 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
784{
785intk=0, t=0, kk=0;
786const char*ptr = str;
787memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
788while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
789ptr++;
790}
791if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
792ptr += 2;
793}
794for (;ptr-str<size && *ptr && k<16;ptr++) {
795if (*ptr>='0' && *ptr<='9') {
796(t=(t<<4)|(*ptr-'0')),kk++;
797}
798if (*ptr>='a' && *ptr<='f') {
799(t=(t<<4)|(*ptr-'a'+10)),kk++;
800}
801if (*ptr>='A' && *ptr<='F') {
802(t=(t<<4)|(*ptr-'A'+10)),kk++;
803}
804if (kk == 2) {
805*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
806k++;
807kk = 0;
808t = 0;
809}
810}
811}
812break;
813
814case SMBYTE:
815if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
816 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
817{
818*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
819} else if (do_auto && smbios_properties[j].auto_int) {
820*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
821}
822break;
823
824case SMWORD:
825if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
826 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
827{
828*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
829} else if (do_auto && smbios_properties[j].auto_int) {
830*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
831}
832break;
833}
834}
835}
836if (nstrings == 0) {
837newtablesptr[0] = 0;
838newtablesptr++;
839}
840newtablesptr[0] = 0;
841newtablesptr++;
842tablespresent[newcur->type]++;
843}
844}
845
846 // for each eventual complementary table not present in the original smbios, do the overrides
847for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
848intnumnec = -1;
849charbuffer[40];
850
851sprintf(buffer, "SMtable%d", i);
852if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
853numnec = -1;
854}
855if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {
856numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
857}
858while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
859struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
860intnstrings = 0;
861
862memset(newcur,0, smbios_table_descriptions[i].len);
863while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {
864nexthandle++;
865}
866newcur->handle = nexthandle;
867handles[nexthandle / 8] |= 1 << (nexthandle % 8);
868newcur->type = smbios_table_descriptions[i].type;
869newcur->length = smbios_table_descriptions[i].len;
870newtablesptr += smbios_table_descriptions[i].len;
871for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
872const char*str;
873intsize;
874intnum;
875charaltname[40];
876
877sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
878if (smbios_properties[j].table_type == newcur->type) {
879switch (smbios_properties[j].value_type) {
880case SMSTRING:
881if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
882 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
883{
884memcpy(newtablesptr, str, size);
885newtablesptr[size] = 0;
886newtablesptr += size + 1;
887*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
888} else if (do_auto && smbios_properties[j].auto_str) {
889str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
890size = strlen(str);
891memcpy(newtablesptr, str, size);
892newtablesptr[size] = 0;
893newtablesptr += size + 1;
894*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
895}
896break;
897
898case SMOWORD:
899if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
900 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
901{
902intk=0, t=0, kk=0;
903const char*ptr = str;
904
905memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
906while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
907ptr++;
908}
909if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
910ptr += 2;
911}
912for (;ptr-str<size && *ptr && k<16;ptr++) {
913if (*ptr>='0' && *ptr<='9') {
914(t=(t<<4)|(*ptr-'0')),kk++;
915}
916if (*ptr>='a' && *ptr<='f') {
917(t=(t<<4)|(*ptr-'a'+10)),kk++;
918}
919if (*ptr>='A' && *ptr<='F') {
920(t=(t<<4)|(*ptr-'A'+10)),kk++;
921}
922if (kk == 2) {
923*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
924k++;
925kk = 0;
926t = 0;
927}
928}
929}
930break;
931
932case SMBYTE:
933if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
934 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
935{
936*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
937} else if (do_auto && smbios_properties[j].auto_int) {
938*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
939}
940break;
941
942case SMWORD:
943if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
944 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
945{
946*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
947} else if (do_auto && smbios_properties[j].auto_int) {
948*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
949}
950break;
951}
952}
953}
954if (nstrings == 0) {
955newtablesptr[0] = 0;
956newtablesptr++;
957}
958newtablesptr[0] = 0;
959newtablesptr++;
960tablespresent[smbios_table_descriptions[i].type]++;
961}
962}
963
964 // calculate new checksums
965newsmbios->dmi.checksum = 0;
966newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));
967newsmbios->checksum = 0;
968newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));
969
970if (!done) {
971verbose("Patched DMI Table\n");
972done=true;
973}
974}
975
976#define MAX_DMI_TABLES 96
977typedef struct DmiNumAssocTag {
978 struct DMIHeader * dmi;
979 uint8_t type;
980} DmiNumAssoc;
981
982static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES];
983static int DmiTablePairCount = 0;
984static int current_pos=0;
985static bool ftTablePairInit = true;
986
987/**
988 * Get a table structure entry from a type specification and a smbios address
989 * return NULL if table is not found
990 */
991void getSmbiosTableStructure(struct SMBEntryPoint *smbios)
992{
993 struct DMIHeader * dmihdr=NULL;
994 SMBByte* p;
995 int i;
996
997 if (ftTablePairInit && smbios!=NULL) {
998 ftTablePairInit = false;
999#if DEBUG_SMBIOS
1000 printf(">>> SMBIOSAddr=0x%08x\n", smbios);
1001 printf(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress,
1002 smbios->dmi.tableLength, smbios->dmi.structureCount);
1003#endif
1004 p = (SMBByte *) smbios->dmi.tableAddress;
1005 for (i=0;
1006 i < smbios->dmi.structureCount &&
1007 p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength;
1008 i++) {
1009 dmihdr = (struct DMIHeader *) p;
1010
1011#if DEBUG_SMBIOS
1012 // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length);
1013#endif
1014 if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break;
1015 if (DmiTablePairCount < MAX_DMI_TABLES) {
1016 DmiTablePair[DmiTablePairCount].dmi = dmihdr;
1017 DmiTablePair[DmiTablePairCount].type = dmihdr->type;
1018 DmiTablePairCount++;
1019 }
1020 else {
1021 printf("DMI table entries list is full! Next entries won't be stored.\n");
1022 }
1023#if DEBUG_SMBIOS
1024 printf("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length);
1025#endif
1026 p = p + dmihdr->length;
1027 while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) {
1028 p++;
1029}
1030 p += 2;
1031}
1032
1033 }
1034}
1035
1036/** Find first original dmi Table with a particular type */
1037struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength)
1038{
1039 current_pos = 0;
1040
1041 return FindNextDmiTableOfType(type, minlength);
1042};
1043
1044/** Find next original dmi Table with a particular type */
1045struct DMIHeader* FindNextDmiTableOfType(int type, int minlength)
1046{
1047 int i;
1048
1049 if (ftTablePairInit) getSmbiosOriginal();
1050
1051 for (i=current_pos; i < DmiTablePairCount; i++) {
1052 if (type == DmiTablePair[i].type &&
1053 DmiTablePair[i].dmi &&
1054 DmiTablePair[i].dmi->length >= minlength ) {
1055 current_pos = i+1;
1056 return DmiTablePair[i].dmi;
1057 }
1058 }
1059 return NULL; // not found
1060};
1061
1062
1063const char * smbiosStringAtIndex(DMIHeader* smHeader, int index, int* length )
1064{
1065 const char * last = 0;
1066 const char * next = (const char *) smHeader + smHeader->length;
1067
1068 if ( length ) *length = 0;
1069 while ( index-- )
1070 {
1071 last = 0;
1072const char * cp = 0;
1073for ( cp = next; *cp || cp[1]; cp++ )
1074 {
1075 if ( *cp == '\0' )
1076 {
1077 last = next;
1078 next = cp + 1;
1079 break;
1080 }
1081 }
1082 if ( last == 0 ) break;
1083 }
1084
1085 if ( last )
1086 {
1087 while (*last == ' ') last++;
1088 if (length)
1089 {
1090 UInt8 len;
1091 for ( len = next - last - 1; len && last[len - 1] == ' '; len-- )
1092 ;
1093 *length = len; // number of chars not counting the terminating NULL
1094 }
1095 }
1096
1097 return last ? last : "";
1098}
1099
1100
1101struct SMBEntryPoint *getSmbiosPatched(struct SMBEntryPoint *orig)
1102{
1103 struct SMBEntryPoint *patched = NULL; // cached
1104
1105patched = smbios_dry_run(orig);
1106 if(patched==NULL) {
1107 printf("Could not create new SMBIOS !!\n");
1108 pause();
1109 }
1110 else {
1111 smbios_real_run(orig, patched);
1112 }
1113
1114
1115 return patched;
1116
1117}
1118
1119/*
1120char* getSmbiosProductName()
1121{
1122struct SMBEntryPoint*smbios;
1123SMBSystemInformation*p;
1124char*tempString;
1125inttmpLen;
1126
1127smbios = getSmbiosOriginal();
1128if (smbios==NULL) return NULL;
1129
1130p = (SMBSystemInformation*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information
1131if (p==NULL) return NULL;
1132
1133
1134tempString = (char*)smbiosStringAtIndex((DMIHeader*)p, p->productName, &tmpLen);
1135tempString[tmpLen] = 0;
1136
1137gSMBIOSBoardModel = malloc(tmpLen + 1);
1138if(gSMBIOSBoardModel)
1139{
1140strncpy(gSMBIOSBoardModel, tempString, tmpLen);
1141Node* node = DT__FindNode("/", false);
1142DT__AddProperty(node, "orig-model", tmpLen, gSMBIOSBoardModel);
1143}
1144verbose("Actual model name is '%s'\n", tempString);
1145return tempString;
1146}
1147*/
1148
1149void scan_memory(PlatformInfo_t *p)
1150{
1151 int i=0;
1152 struct DMIHeader * dmihdr = NULL;
1153
1154 struct DMIMemoryModuleInfo* memInfo[MAX_RAM_SLOTS]; // 6
1155 struct DMIPhysicalMemoryArray* physMemArray; // 16
1156 struct DMIMemoryDevice* memDev[MAX_RAM_SLOTS]; //17
1157
1158 /* We mainly don't use obsolete tables 5,6 because most of computers don't handle it anymore */
1159Platform->DMI.MemoryModules = 0;
1160 /* Now lets peek info rom table 16,17 as for some bios, table 5 & 6 are not used */
1161 physMemArray = (struct DMIPhysicalMemoryArray*) FindFirstDmiTableOfType(16, 4);
1162 Platform->DMI.MaxMemorySlots = physMemArray ? physMemArray->numberOfMemoryDevices : 0;
1163
1164 i = 0;
1165 for(dmihdr = FindFirstDmiTableOfType(17, 4);
1166 dmihdr;
1167 dmihdr = FindNextDmiTableOfType(17, 4) ) {
1168 memDev[i] = (struct DMIMemoryDevice*) dmihdr;
1169 if (memDev[i]->size !=0 ) Platform->DMI.MemoryModules++;
1170 if (memDev[i]->speed>0) Platform->RAM.DIMM[i].Frequency = memDev[i]->speed; // take it here for now but we'll check spd and dmi table 6 as well
1171 i++;
1172 }
1173 // for table 6, we only have a look at the current speed
1174 i = 0;
1175 for(dmihdr = FindFirstDmiTableOfType(6, 4);
1176 dmihdr;
1177 dmihdr = FindNextDmiTableOfType(6, 4) ) {
1178 memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr;
1179 if (memInfo[i]->currentSpeed > Platform->RAM.DIMM[i].Frequency)
1180 Platform->RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any
1181 i++;
1182 }
1183#if 0
1184 dumpAllTablesOfType(17);
1185 getc();
1186#endif
1187}
1188

Archive Download this file

Revision: 1119