Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/libsaio/smbios_patcher.c

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

Archive Download this file

Revision: 444