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

Archive Download this file

Revision: 275