Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 196