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

Archive Download this file

Revision: 269