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

Archive Download this file

Revision: 192