Chameleon

Chameleon Svn Source Tree

Root/branches/meklortOld/i386/libsaio/smbios_patcher.c

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

Archive Download this file

Revision: 1146