Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 463