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

Archive Download this file

Revision: 274