Chameleon

Chameleon Svn Source Tree

Root/branches/i386/libsaio/smbios_patcher.c

Source at commit 162 created 13 years 10 months ago.
By valv, Corrected branch root
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 0x0201; // <01 02> Intel Core Solo/Duo?
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: 162