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

Archive Download this file

Revision: 272