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

Archive Download this file

Revision: 789