Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 661