Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/libsaio/smbios_patcher.c

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

Archive Download this file

Revision: 270