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
24
25// defaults for a MacBook
26static char sm_macbook_defaults[][2][40]={
27{"SMbiosvendor","Apple Inc."},
28{"SMbiosversion","MB41.88Z.0073.B00.0809221748"},
29{"SMbiosdate","04/01/2008"},
30{"SMmanufacter","Apple Inc."},
31{"SMproductname","MacBook4,1"},
32{"SMsystemversion","1.0"},
33{"SMserial","SOMESRLNMBR"},
34{"SMfamily","MacBook"},
35{"SMboardmanufacter","Apple Inc."},
36{"SMboardproduct","Mac-F42D89C8"},
37{ "",""}
38};
39
40// defaults for a MacBook Pro
41static char sm_macbookpro_defaults[][2][40]={
42{"SMbiosvendor","Apple Inc."},
43{"SMbiosversion","MBP41.88Z.0073.B00.0809221748"},
44{"SMbiosdate","04/01/2008"},
45{"SMmanufacter","Apple Inc."},
46{"SMproductname","MacBookPro4,1"},
47{"SMsystemversion","1.0"},
48{"SMserial","SOMESRLNMBR"},
49{"SMfamily","MacBookPro"},
50{"SMboardmanufacter","Apple Inc."},
51{"SMboardproduct","Mac-F42D89C8"},
52{ "",""}
53};
54
55// defaults for a Mac mini
56static char sm_macmini_defaults[][2][40]={
57{"SMbiosvendor","Apple Inc."},
58{"SMbiosversion","MM21.88Z.009A.B00.0706281359"},
59{"SMbiosdate","04/01/2008"},
60{"SMmanufacter","Apple Inc."},
61{"SMproductname","Macmini2,1"},
62{"SMsystemversion","1.0"},
63{"SMserial","SOMESRLNMBR"},
64{"SMfamily","Napa Mac"},
65{"SMboardmanufacter","Apple Inc."},
66{"SMboardproduct","Mac-F4208EAA"},
67{ "",""}
68};
69
70// defaults for an iMac
71static char sm_imac_defaults[][2][40]={
72{"SMbiosvendor","Apple Inc."},
73{"SMbiosversion","IM81.88Z.00C1.B00.0802091538"},
74{"SMbiosdate","04/01/2008"},
75{"SMmanufacter","Apple Inc."},
76{"SMproductname","iMac8,1"},
77{"SMsystemversion","1.0"},
78{"SMserial","SOMESRLNMBR"},
79{"SMfamily","Mac"},
80{"SMboardmanufacter","Apple Inc."},
81{"SMboardproduct","Mac-F227BEC8"},
82{ "",""}
83};
84
85// defaults for a Mac Pro
86static char sm_macpro_defaults[][2][40]={
87{"SMbiosvendor","Apple Computer, Inc."},
88{"SMbiosversion","MP31.88Z.006C.B05.0802291410"},
89{"SMbiosdate","04/01/2008"},
90{"SMmanufacter","Apple Computer, Inc."},
91{"SMproductname","MacPro3,1"},
92{"SMsystemversion","1.0"},
93{"SMserial","SOMESRLNMBR"},
94{"SMfamily","MacPro"},
95{"SMboardmanufacter","Apple Computer, Inc."},
96{"SMboardproduct","Mac-F4208DC8"},
97{ "",""}
98};
99
100static char *sm_get_defstr(char *name, int table_num)
101{
102inti;
103char(*sm_defaults)[2][40];
104
105if (platformCPUFeature(CPU_FEATURE_MOBILE)) {
106if (Platform.CPU.NoCores > 1) {
107sm_defaults=sm_macbookpro_defaults;
108} else {
109sm_defaults=sm_macbook_defaults;
110}
111} else {
112switch (Platform.CPU.NoCores) {
113case 1: sm_defaults=sm_macmini_defaults; break;
114case 2: sm_defaults=sm_imac_defaults; break;
115default: sm_defaults=sm_macpro_defaults; break;
116}
117}
118
119for (i=0;sm_defaults[i][0][0];i++) {
120if (!strcmp (sm_defaults[i][0],name)) {
121return sm_defaults[i][1];
122}
123}
124
125// Shouldn't happen
126printf ("Error: no default for '%s' known\n", name);
127sleep (2);
128return "";
129}
130
131static int sm_get_fsb(char *name, int table_num)
132{
133return Platform.CPU.FSBFrequency/1000000;
134}
135
136static int sm_get_cpu (char *name, int table_num)
137{
138return Platform.CPU.CPUFrequency/1000000;
139}
140
141static int sm_get_cputype (char *name, int table_num)
142{
143if (Platform.CPU.NoCores == 1) {
144return 0x0101; // <01 01> Intel Core Solo?
145} else if (Platform.CPU.NoCores == 2) {
146return 0x0301; // <01 03> Intel Core 2 Duo
147} else if (Platform.CPU.NoCores >= 4) {
148return 0x0501; // <01 05> Quad-Core Intel Xeon
149} else {
150return 0x0301; // Default to Core 2 Duo
151}
152}
153
154static int sm_get_memtype (char *name, int table_num)
155{
156intmap;
157
158if (table_num < MAX_RAM_SLOTS) {
159map = Platform.DMI.DIMM[table_num];
160if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Type != 0) {
161 DBG("RAM Detected Type = %d\n", Platform.RAM.DIMM[map].Type);
162 return Platform.RAM.DIMM[map].Type;
163}
164}
165return SMB_MEM_TYPE_DDR2;
166}
167
168static int sm_get_memspeed (char *name, int table_num)
169{
170intmap;
171
172if (table_num < MAX_RAM_SLOTS) {
173map = Platform.DMI.DIMM[table_num];
174if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Type != 0) {
175 DBG("RAM Detected Freq = %d Mhz\n", Platform.RAM.DIMM[map].Frequency);
176 return Platform.RAM.DIMM[map].Frequency;
177}
178}
179
180return 800;
181}
182
183static char *sm_get_memvendor (char *name, int table_num)
184{
185intmap;
186
187if (table_num < MAX_RAM_SLOTS) {
188map = Platform.DMI.DIMM[table_num];
189if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].Vendor) > 0) {
190DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].Vendor);
191return Platform.RAM.DIMM[map].Vendor;
192}
193}
194return "N/A";
195}
196
197static char *sm_get_memserial (char *name, int table_num)
198{
199intmap;
200
201if (table_num < MAX_RAM_SLOTS) {
202map = Platform.DMI.DIMM[table_num];
203if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].SerialNo) > 0) {
204 DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "",
205 map, table_num, Platform.RAM.DIMM[map].SerialNo);
206 return Platform.RAM.DIMM[map].SerialNo;
207}
208}
209return "N/A";
210}
211
212static char *sm_get_mempartno (char *name, int table_num)
213{
214intmap;
215
216if (table_num < MAX_RAM_SLOTS) {
217map = Platform.DMI.DIMM[table_num];
218if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].PartNo) > 0) {
219DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].PartNo);
220return Platform.RAM.DIMM[map].PartNo;
221}
222}
223return "N/A";
224}
225
226static int sm_one (int tablen)
227{
228return 1;
229}
230
231struct smbios_property smbios_properties[]=
232{
233{.name="SMbiosvendor",.table_type= 0,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
234{.name="SMbiosversion",.table_type= 0,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
235{.name="SMbiosdate",.table_type= 0,.value_type=SMSTRING,.offset=0x08,.auto_str=sm_get_defstr},
236{.name="SMmanufacter",.table_type= 1,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
237{.name="SMproductname",.table_type= 1,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
238{.name="SMsystemversion",.table_type= 1,.value_type=SMSTRING,.offset=0x06,.auto_str=sm_get_defstr},
239{.name="SMserial",.table_type= 1,.value_type=SMSTRING,.offset=0x07,.auto_str=sm_get_defstr},
240{.name="SMUUID",.table_type= 1, .value_type=SMOWORD,.offset=0x08,.auto_oword=0},
241{.name="SMfamily",.table_type= 1,.value_type=SMSTRING,.offset=0x1a,.auto_str=sm_get_defstr},
242{.name="SMboardmanufacter",.table_type= 2, .value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
243{.name="SMboardproduct",.table_type= 2, .value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
244{.name="SMexternalclock",.table_type= 4,.value_type=SMWORD,.offset=0x12,.auto_int=sm_get_fsb},
245{.name="SMmaximalclock",.table_type= 4,.value_type=SMWORD,.offset=0x14,.auto_int=sm_get_cpu},
246{.name="SMmemdevloc",.table_type=17,.value_type=SMSTRING,.offset=0x10,.auto_str=0},
247{.name="SMmembankloc",.table_type=17,.value_type=SMSTRING,.offset=0x11,.auto_str=0},
248{.name="SMmemtype",.table_type=17,.value_type=SMBYTE,.offset=0x12,.auto_int=sm_get_memtype},
249{.name="SMmemspeed",.table_type=17,.value_type=SMWORD,.offset=0x15,.auto_int=sm_get_memspeed},
250{.name="SMmemmanufacter",.table_type=17,.value_type=SMSTRING,.offset=0x17,.auto_str=sm_get_memvendor},
251{.name="SMmemserial",.table_type=17,.value_type=SMSTRING,.offset=0x18,.auto_str=sm_get_memserial},
252{.name="SMmempart",.table_type=17,.value_type=SMSTRING,.offset=0x1A,.auto_str=sm_get_mempartno},
253{.name="SMcputype",.table_type=131,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_cputype},
254{.name="SMbusspeed",.table_type=132,.value_type=SMWORD,.offset=0x04,.auto_str=0}
255};
256
257struct smbios_table_description smbios_table_descriptions[]=
258{
259{.type=0,.len=0x18,.numfunc=sm_one},
260{.type=1,.len=0x1b,.numfunc=sm_one},
261{.type=2,.len=0x0f,.numfunc=sm_one},
262{.type=4,.len=0x2a,.numfunc=sm_one},
263{.type=17,.len=0x1c,.numfunc=0},
264{.type=131,.len=0x06,.numfunc=sm_one},
265{.type=132,.len=0x06,.numfunc=sm_one}
266};
267
268// getting smbios addr with fast compare ops, late checksum testing ...
269#define COMPARE_DWORD(a,b) ( *((u_int32_t *) a) == *((u_int32_t *) b) )
270static const char * const SMTAG = "_SM_";
271static const char* const DMITAG= "_DMI_";
272
273static struct SMBEntryPoint *getAddressOfSmbiosTable(void)
274{
275struct SMBEntryPoint*smbios;
276
277/*
278 * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking
279 * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_").
280 */
281smbios = (struct SMBEntryPoint*) SMBIOS_RANGE_START;
282while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END) {
283 if (COMPARE_DWORD(smbios->anchor, SMTAG) && COMPARE_DWORD(smbios->dmi.anchor, DMITAG) &&
284 checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0)
285 {
286 return smbios;
287 }
288 smbios = (((void*) smbios) + 16);
289}
290printf("ERROR: Unable to find SMBIOS!\n");
291sleep(5);
292return NULL;
293}
294
295/** Compute necessary space requirements for new smbios */
296struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)
297{
298struct SMBEntryPoint*ret;
299char*smbiostables;
300char*tablesptr;
301intorigsmbiosnum;
302inti, j;
303inttablespresent[256];
304booldo_auto=true;
305
306bzero(tablespresent, sizeof(tablespresent));
307
308getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
309
310ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));
311if (origsmbios) {
312smbiostables = (char *)origsmbios->dmi.tableAddress;
313origsmbiosnum = origsmbios->dmi.structureCount;
314} else {
315smbiostables = NULL;
316origsmbiosnum = 0;
317}
318
319// _SM_
320ret->anchor[0] = 0x5f;
321ret->anchor[1] = 0x53;
322ret->anchor[2] = 0x4d;
323ret->anchor[3] = 0x5f;
324ret->entryPointLength = sizeof(*ret);
325ret->majorVersion = 2;
326ret->minorVersion = 1;
327ret->maxStructureSize = 0; // will be calculated later in this function
328ret->entryPointRevision = 0;
329for (i=0;i<5;i++) {
330ret->formattedArea[i] = 0;
331}
332//_DMI_
333ret->dmi.anchor[0] = 0x5f;
334ret->dmi.anchor[1] = 0x44;
335ret->dmi.anchor[2] = 0x4d;
336ret->dmi.anchor[3] = 0x49;
337ret->dmi.anchor[4] = 0x5f;
338ret->dmi.tableLength = 0; // will be calculated later in this function
339ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()
340ret->dmi.structureCount = 0; // will be calculated later in this function
341ret->dmi.bcdRevision = 0x21;
342tablesptr = smbiostables;
343
344 // add stringlen of overrides to original stringlen, update maxStructure size adequately,
345 // update structure count and tablepresent[type] with count of type.
346if (smbiostables) {
347for (i=0; i<origsmbiosnum; i++) {
348struct smbios_table_header*cur = (struct smbios_table_header *)tablesptr;
349char*stringsptr;
350intstringlen;
351
352tablesptr += cur->length;
353stringsptr = tablesptr;
354for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);
355tablesptr += 2;
356stringlen = tablesptr - stringsptr - 1;
357if (stringlen == 1) {
358stringlen = 0;
359}
360for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
361const char*str;
362intsize;
363charaltname[40];
364
365sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);
366if (smbios_properties[j].table_type == cur->type &&
367 smbios_properties[j].value_type == SMSTRING &&
368 (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) ||
369 getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))
370{
371stringlen += size + 1;
372} else if (smbios_properties[j].table_type == cur->type &&
373 smbios_properties[j].value_type == SMSTRING &&
374 do_auto && smbios_properties[j].auto_str)
375{
376stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
377}
378}
379if (stringlen == 0) {
380stringlen = 1;
381}
382stringlen++;
383if (ret->maxStructureSize < cur->length+stringlen) {
384ret->maxStructureSize=cur->length+stringlen;
385}
386ret->dmi.tableLength += cur->length+stringlen;
387ret->dmi.structureCount++;
388tablespresent[cur->type]++;
389}
390}
391 // Add eventually table types whose detected count would be < required count, and update ret header with:
392 // new stringlen addons, structure count, and tablepresent[type] count adequately
393for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
394intnumnec=-1;
395charbuffer[40];
396
397sprintf(buffer, "SMtable%d", i);
398if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
399numnec = -1;
400}
401if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {
402numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
403}
404while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
405intstringlen = 0;
406for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
407const char*str;
408intsize;
409charaltname[40];
410
411sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);
412if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
413 smbios_properties[j].value_type == SMSTRING &&
414 (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
415 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)))
416{
417stringlen += size + 1;
418} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
419 smbios_properties[j].value_type==SMSTRING &&
420 do_auto && smbios_properties[j].auto_str)
421{
422stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
423}
424}
425if (stringlen == 0) {
426stringlen = 1;
427}
428stringlen++;
429if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {
430ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;
431}
432ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;
433ret->dmi.structureCount++;
434tablespresent[smbios_table_descriptions[i].type]++;
435}
436}
437return ret;
438}
439
440/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint
441 * struct has been created by smbios_dry_run, update each table struct content of new smbios
442 * int the new allocated table address of size newsmbios->tablelength.
443 */
444void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)
445{
446char *smbiostables;
447char *tablesptr, *newtablesptr;
448int origsmbiosnum;
449// bitmask of used handles
450uint8_t handles[8192];
451uint16_t nexthandle=0;
452int i, j;
453int tablespresent[256];
454bool do_auto=true;
455
456 extern void dumpPhysAddr(const char * title, void * a, int len);
457
458bzero(tablespresent, sizeof(tablespresent));
459bzero(handles, sizeof(handles));
460
461getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
462
463newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);
464if (origsmbios) {
465smbiostables = (char *)origsmbios->dmi.tableAddress;
466origsmbiosnum = origsmbios->dmi.structureCount;
467} else {
468smbiostables = NULL;
469origsmbiosnum = 0;
470}
471tablesptr = smbiostables;
472newtablesptr = (char *)newsmbios->dmi.tableAddress;
473
474 // if old smbios exists then update new smbios with old smbios original content first
475if (smbiostables) {
476for (i=0; i<origsmbiosnum; i++) {
477struct smbios_table_header*oldcur = (struct smbios_table_header *) tablesptr;
478struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
479char*stringsptr;
480intnstrings = 0;
481
482handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);
483
484 // copy table length from old table to new table but not the old strings
485memcpy(newcur,oldcur, oldcur->length);
486
487tablesptr += oldcur->length;
488stringsptr = tablesptr;
489newtablesptr += oldcur->length;
490
491 // calculate the number of strings in the old content
492for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {
493if (tablesptr[0] == 0) {
494nstrings++;
495}
496}
497if (tablesptr != stringsptr) {
498nstrings++;
499}
500tablesptr += 2;
501
502 // copy the old strings to new table
503memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);
504
505 #if 0
506 // DEBUG: display this original table 17
507
508 if (oldcur->type==6 || oldcur->type==17)
509 {
510 dumpPhysAddr("orig table:", oldcur, oldcur->length + ( tablesptr-stringsptr));
511 }
512#endif
513// point to next possible space for a string (deducting the second 0 char at the end)
514newtablesptr += tablesptr - stringsptr - 1;
515 if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator
516newtablesptr--;
517}
518
519 // now for each property in the table update the overrides if any (auto or user)
520for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
521const char*str;
522intsize;
523intnum;
524charaltname[40];
525
526sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
527if (smbios_properties[j].table_type == newcur->type) {
528switch (smbios_properties[j].value_type) {
529case SMSTRING:
530if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
531 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
532{
533memcpy(newtablesptr, str, size);
534newtablesptr[size] = 0;
535newtablesptr += size + 1;
536*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
537} else if (do_auto && smbios_properties[j].auto_str) {
538str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
539size = strlen(str);
540memcpy(newtablesptr, str, size);
541newtablesptr[size] = 0;
542newtablesptr += size + 1;
543*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
544}
545break;
546
547case SMOWORD:
548if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
549 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
550{
551intk=0, t=0, kk=0;
552const char*ptr = str;
553memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
554while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
555ptr++;
556}
557if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
558ptr += 2;
559}
560for (;ptr-str<size && *ptr && k<16;ptr++) {
561if (*ptr>='0' && *ptr<='9') {
562(t=(t<<4)|(*ptr-'0')),kk++;
563}
564if (*ptr>='a' && *ptr<='f') {
565(t=(t<<4)|(*ptr-'a'+10)),kk++;
566}
567if (*ptr>='A' && *ptr<='F') {
568(t=(t<<4)|(*ptr-'A'+10)),kk++;
569}
570if (kk == 2) {
571*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
572k++;
573kk = 0;
574t = 0;
575}
576}
577}
578break;
579
580case SMBYTE:
581if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
582 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
583{
584*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
585} else if (do_auto && smbios_properties[j].auto_int) {
586*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
587}
588break;
589
590case SMWORD:
591if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
592 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
593{
594*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
595} else if (do_auto && smbios_properties[j].auto_int) {
596*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
597}
598break;
599}
600}
601}
602if (nstrings == 0) {
603newtablesptr[0] = 0;
604newtablesptr++;
605}
606newtablesptr[0] = 0;
607newtablesptr++;
608tablespresent[newcur->type]++;
609}
610}
611
612 // for each eventual complementary table not present in the original smbios, do the overrides
613for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
614intnumnec = -1;
615charbuffer[40];
616
617sprintf(buffer, "SMtable%d", i);
618if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
619numnec = -1;
620}
621if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {
622numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
623}
624while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
625struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
626intnstrings = 0;
627
628memset(newcur,0, smbios_table_descriptions[i].len);
629while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {
630nexthandle++;
631}
632newcur->handle = nexthandle;
633handles[nexthandle / 8] |= 1 << (nexthandle % 8);
634newcur->type = smbios_table_descriptions[i].type;
635newcur->length = smbios_table_descriptions[i].len;
636newtablesptr += smbios_table_descriptions[i].len;
637for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
638const char*str;
639intsize;
640intnum;
641charaltname[40];
642
643sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
644if (smbios_properties[j].table_type == newcur->type) {
645switch (smbios_properties[j].value_type) {
646case SMSTRING:
647if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
648 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
649{
650memcpy(newtablesptr, str, size);
651newtablesptr[size] = 0;
652newtablesptr += size + 1;
653*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
654} else if (do_auto && smbios_properties[j].auto_str) {
655str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
656size = strlen(str);
657memcpy(newtablesptr, str, size);
658newtablesptr[size] = 0;
659newtablesptr += size + 1;
660*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
661}
662break;
663
664case SMOWORD:
665if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
666 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
667{
668intk=0, t=0, kk=0;
669const char*ptr = str;
670
671memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
672while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
673ptr++;
674}
675if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
676ptr += 2;
677}
678for (;ptr-str<size && *ptr && k<16;ptr++) {
679if (*ptr>='0' && *ptr<='9') {
680(t=(t<<4)|(*ptr-'0')),kk++;
681}
682if (*ptr>='a' && *ptr<='f') {
683(t=(t<<4)|(*ptr-'a'+10)),kk++;
684}
685if (*ptr>='A' && *ptr<='F') {
686(t=(t<<4)|(*ptr-'A'+10)),kk++;
687}
688if (kk == 2) {
689*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
690k++;
691kk = 0;
692t = 0;
693}
694}
695}
696break;
697
698case SMBYTE:
699if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
700 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
701{
702*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
703} else if (do_auto && smbios_properties[j].auto_int) {
704*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
705}
706break;
707
708case SMWORD:
709if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
710 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
711{
712*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
713} else if (do_auto && smbios_properties[j].auto_int) {
714*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
715}
716break;
717}
718}
719}
720if (nstrings == 0) {
721newtablesptr[0] = 0;
722newtablesptr++;
723}
724newtablesptr[0] = 0;
725newtablesptr++;
726tablespresent[smbios_table_descriptions[i].type]++;
727}
728}
729
730 // calculate new checksums
731newsmbios->dmi.checksum = 0;
732newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));
733newsmbios->checksum = 0;
734newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));
735verbose("Patched DMI Table\n");
736}
737
738struct SMBEntryPoint *getSmbios(int which)
739{
740 static struct SMBEntryPoint *orig = NULL; // cached
741 static struct SMBEntryPoint *patched = NULL; // cached
742
743if (orig == NULL) orig = getAddressOfSmbiosTable();
744
745switch (which) {
746case SMBIOS_ORIGINAL:
747 return orig;
748case SMBIOS_PATCHED:
749 if (patched == NULL) {
750 if (orig==NULL) orig = getAddressOfSmbiosTable();
751 patched = smbios_dry_run(orig);
752 smbios_real_run(orig, patched);
753 }
754 return patched;
755default:
756 printf("ERROR: invalid option for getSmbios() !!\n");
757 return NULL;
758}
759}
760
761#define MAX_DMI_TABLES 64
762typedef struct DmiNumAssocTag {
763 struct DMIHeader * dmi;
764 uint8_t type;
765} DmiNumAssoc;
766
767static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES];
768static int DmiTablePairCount = 0;
769static int current_pos=0;
770static bool ftTablePairInit = true;
771
772/** Find first original dmi Table with a particular type */
773struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength)
774{
775 if (ftTablePairInit)
776 return getSmbiosTableStructure(getSmbios(SMBIOS_ORIGINAL),
777 type, minlength);
778 current_pos = 0;
779 return FindNextDmiTableOfType(type, minlength);
780};
781
782/** Find next original dmi Table with a particular type */
783struct DMIHeader* FindNextDmiTableOfType(int type, int minlength)
784{
785 int i;
786
787 for (i=current_pos; i < DmiTablePairCount; i++) {
788 if (type == DmiTablePair[i].type &&
789 DmiTablePair[i].dmi &&
790 DmiTablePair[i].dmi->length >= minlength ) {
791 current_pos = i+1;
792 return DmiTablePair[i].dmi;
793 }
794 }
795 return NULL; // not found
796};
797
798/**
799 * Get a table structure entry from a type specification and a smbios address
800 * return NULL if table is not found
801 */
802struct DMIHeader *getSmbiosTableStructure(struct SMBEntryPoint*smbios, int type, int min_length)
803{
804 struct DMIHeader * dmihdr=NULL;
805 SMBByte* p;
806 int i;
807
808 if (!ftTablePairInit) {
809 return FindFirstDmiTableOfType(type, min_length);
810 } else {
811 ftTablePairInit = false;
812 bzero(DmiTablePair, sizeof(DmiTablePair));
813
814 if (smbios == NULL || type < 0 ) return NULL;
815#if DEBUG_SMBIOS
816 printf(">>> SMBIOSAddr=0x%08x\n", smbios);
817 printf(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress,
818 smbios->dmi.tableLength, smbios->dmi.structureCount);
819#endif
820 p = (SMBByte *) smbios->dmi.tableAddress;
821 for (i=0;
822 i < smbios->dmi.structureCount &&
823 p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength;
824 i++) {
825 dmihdr = (struct DMIHeader *) p;
826
827#if DEBUG_SMBIOS
828 // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length);
829#endif
830 if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break;
831 DmiTablePair[DmiTablePairCount].dmi = dmihdr;
832 DmiTablePair[DmiTablePairCount].type = dmihdr->type;
833 DmiTablePairCount++;
834#if DEBUG_SMBIOS
835 printf("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length);
836#endif
837 p = p + dmihdr->length;
838 while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) {
839 p++;
840 }
841 p += 2;
842}
843
844 }
845 return FindFirstDmiTableOfType(type, min_length);
846}
847

Archive Download this file

Revision: 97