Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 311