Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/libsaio/smbios_patcher.c

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

Archive Download this file

Revision: 590