Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/libsaio/smbios_patcher.c

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

Archive Download this file

Revision: 314