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

Archive Download this file

Revision: 698