Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 177