Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 762