Chameleon

Chameleon Svn Source Tree

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

Source at commit 576 created 13 years 6 months ago.
By meklort, Retrieve and store the machine's smbios product name. Load machin.DSDT.aml file if it exists.
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);
1136}
1137
1138

Archive Download this file

Revision: 576