Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/i386/libsaio/smbios_patcher.c

Source at commit 214 created 13 years 5 months ago.
By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings.
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","W8826DJD0P1"},
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","W88261E7YP4"},
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","G8830338YL3"},
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","YM84915LZE2"},
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","W87234JHYA4"},
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","W895154Z5RU"},
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","H09222GU4PD"},
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: 214