Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 701