Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 534