Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/SMBiosPatcher/smbios_patcher.c

1/*
2 * Copyright 2008 mackerintel
3 */
4
5#include "libsaio.h"
6#include "bootstruct.h"
7#include "acpi.h"
8#include "efi_tables.h"
9#include "fake_efi.h"
10#include "platform.h"
11#include "smbios_patcher.h"
12#include "pci.h"
13#include "cpu.h"
14#include "modules.h"
15
16#ifndef DEBUG_SMBIOS
17#define DEBUG_SMBIOS 0
18#endif
19
20#if DEBUG_SMBIOS==2
21#define DBG(x...)printf(x)
22#elif DEBUG_SMBIOS==1
23#define DBG(x...) msglog(x)
24#else
25#define DBG(x...)
26#endif
27
28char* gSMBIOSBoardModel;
29
30static char fake_serial[12];
31
32static char const sn_gen_pn_str[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
33
34typedef struct {
35 const char* key;
36 const char* value;
37} SMStrEntryPair;
38
39// defaults for a MacBook
40static const SMStrEntryPair const sm_macbook_defaults[]={
41{"SMbiosvendor", "Apple Inc." },
42{"SMbiosversion", "MB41.88Z.00C1.B00.0802091535"},
43{"SMbiosdate", "02/09/2008" },
44{"SMmanufacter", "Apple Inc." },
45{"SMproductname", "MacBook4,1" },
46{"SMsystemversion", "1.0" },
47{"SMserial", "RM83064H0P1" },
48 {"SMserialProductCountry","RM" },
49 {"SMserialYear", "8" },
50{"SMserialWeek", "30" },
51{"SMserialProductNumber","64H" },
52{"SMserialModel","0P1" },
53{"SMfamily", "MacBook" },
54{"SMboardmanufacter", "Apple Inc." },
55{"SMboardproduct", "Mac-F22788A9" },
56{ "",""}
57};
58
59// defaults for a MacBook Pro
60static const SMStrEntryPair const sm_macbookpro_defaults[]={
61{"SMbiosvendor", "Apple Inc." },
62{"SMbiosversion", "MBP41.88Z.00C1.B03.0802271651"},
63{"SMbiosdate", "02/27/2008" },
64{"SMmanufacter", "Apple Inc." },
65{"SMproductname", "MacBookPro4,1" },
66{"SMsystemversion", "1.0" },
67{"SMserial", "W88198N6YJX" },
68 {"SMserialProductCountry","W8" },
69 {"SMserialYear", "8" },
70{"SMserialWeek", "19" },
71{"SMserialProductNumber","8N6" },
72{"SMserialModel","YJX" },
73{"SMfamily", "MacBookPro" },
74{"SMboardmanufacter", "Apple Inc." },
75{"SMboardproduct", "Mac-F42C89C8" },
76{ "",""}
77};
78
79// defaults for a Mac mini
80static const SMStrEntryPair const sm_macmini_defaults[]={
81{"SMbiosvendor", "Apple Inc." },
82{"SMbiosversion", "MM21.88Z.009A.B00.0706281359"},
83{"SMbiosdate", "06/28/2007" },
84{"SMmanufacter", "Apple Inc." },
85{"SMproductname", "Macmini2,1" },
86{"SMsystemversion", "1.0" },
87{"SMserial", "YM8054BYYL2" },
88 {"SMserialProductCountry","YM" },
89 {"SMserialYear", "8" },
90{"SMserialWeek", "05" },
91{"SMserialProductNumber","4BY" },
92{"SMserialModel","YL2" },
93{"SMfamily", "Napa Mac" },
94{"SMboardmanufacter", "Apple Inc." },
95{"SMboardproduct", "Mac-F4208EAA" },
96{ "",""}
97};
98
99// defaults for an iMac
100static const SMStrEntryPair const sm_imac_defaults[]={
101{"SMbiosvendor", "Apple Inc." },
102{"SMbiosversion", "IM71.88Z.007A.B03.0803051705"},
103{"SMbiosdate", "03/05/2008" },
104{"SMmanufacter", "Apple Inc." },
105{"SMproductname", "iMac7,1" },
106{"SMsystemversion", "1.0" },
107{"SMserial", "W87410PWX87" },
108 {"SMserialProductCountry","W8" },
109 {"SMserialYear", "7" },
110{"SMserialWeek", "41" },
111{"SMserialProductNumber","0PW" },
112{"SMserialModel","X87" },
113{"SMfamily", "Mac" },
114{"SMboardmanufacter", "Apple Inc." },
115{"SMboardproduct", "Mac-F4238CC8" },
116{ "",""}
117};
118
119// defaults for a Mac Pro
120static const SMStrEntryPair const sm_macpro_defaults[]={
121{"SMbiosvendor", "Apple Computer, Inc."},
122{"SMbiosversion", "MP31.88Z.006C.B02.0801021250"},
123{"SMbiosdate", "01/02/2008"},
124{"SMmanufacter", "Apple Computer, Inc."},
125{"SMproductname", "MacPro3,1"},
126{"SMsystemversion", "1.0"},
127{"SMserial", "G88014V4XYK"},
128 {"SMserialProductCountry","G8" },
129 {"SMserialYear", "8" },
130{"SMserialWeek", "01" },
131{"SMserialProductNumber","4V4" },
132{"SMserialModel","XYK" },
133{"SMfamily", "MacPro"},
134{"SMboardmanufacter", "Apple Computer, Inc."},
135{"SMboardproduct", "Mac-F42C88C8"},
136{ "",""}
137};
138
139// defaults for an iMac11,1 core i3/i5/i7
140static const SMStrEntryPair const sm_imac_core_defaults[]={
141{"SMbiosvendor", "Apple Inc."},
142{"SMbiosversion", "IM111.88Z.0034.B00.0910301727"},
143{"SMbiosdate", "10/30/2009"},
144{"SMmanufacter", "Apple Inc."},
145{"SMproductname", "iMac11,1"},
146{"SMsystemversion", "1.0"},
147{"SMserial", "W89470DZ5RU"},
148 {"SMserialProductCountry", "W8" },
149 {"SMserialYear", "9" },
150{"SMserialWeek", "47" },
151{"SMserialProductNumber", "0DZ" },
152{"SMserialModel", "5RU" },
153{"SMfamily", "iMac"},
154{"SMboardmanufacter", "Apple Inc." },
155{"SMboardproduct", "Mac-F2268DAE"},
156{ "",""}
157};
158
159// defaults for an iMac12,1 : todo: populate correctly
160static const SMStrEntryPair const sm_imac_sandy_defaults[]={
161{"SMbiosvendor", "Apple Inc."},
162{"SMbiosversion", "IM121.88Z.0047.B00.1102091756"},
163{"SMbiosdate", "10/30/2011"},
164{"SMmanufacter", "Apple Inc."},
165{"SMproductname", "iMac12,1"},
166{"SMsystemversion", "1.0"},
167{"SMserial", "W89470DZ5RU"},
168 {"SMserialProductCountry", "W8" },
169 {"SMserialYear", "9" },
170{"SMserialWeek", "47" },
171{"SMserialProductNumber", "0DZ" },
172{"SMserialModel", "5RU" },
173{"SMfamily", "iMac"},
174{"SMboardmanufacter", "Apple Inc." },
175{"SMboardproduct", "Mac-F2268DAE"},
176{ "",""}
177};
178
179// defaults for a Mac Pro 4,1 core i7/Xeon
180static const SMStrEntryPair const sm_macpro_core_defaults[]={
181{"SMbiosvendor", "Apple Computer, Inc."},
182{"SMbiosversion", "MP41.88Z.0081.B03.0902231259"},
183{"SMbiosdate", "02/23/2009"},
184{"SMmanufacter", "Apple Inc." },
185{"SMproductname", "MacPro4,1"},
186{"SMsystemversion", "1.0"},
187{"SMserial", "CK91601V8Q0"},
188 {"SMserialProductCountry","CK" },
189 {"SMserialYear", "9" },
190{"SMserialWeek", "16" },
191{"SMserialProductNumber","01V" },
192{"SMserialModel","8Q0" },
193{"SMfamily", "MacPro"},
194{"SMboardmanufacter", "Apple Computer, Inc."},
195{"SMboardproduct", "Mac-F221BEC8"},
196{ "",""}
197};
198
199// defaults for a Mac Pro 5,1 Westmere
200static const SMStrEntryPair const sm_macpro_westmere_defaults[]={
201{"SMbiosvendor", "Apple Computer, Inc."},
202{"SMbiosversion", "MP51.88Z.007F.B00.1008031144"},
203{"SMbiosdate", "08/03/2010"},
204{"SMmanufacter", "Apple Inc." },
205{"SMproductname", "MacPro5,1"},
206{"SMsystemversion", "0.0"},
207{"SMserial", "YM0330U7EUH"},
208 {"SMserialProductCountry","YM" },
209 {"SMserialYear", "0" },
210{"SMserialWeek", "33" },
211{"SMserialProductNumber","0U7" },
212{"SMserialModel","EUH" },
213{"SMfamily", "MacPro"},
214{"SMboardmanufacter", "Apple Computer, Inc."},
215{"SMboardproduct", "Mac-F221BEC8"},
216{ "",""}
217};
218
219// default for a Xserve
220static const SMStrEntryPair const sm_xserve_defaults[]={
221 {"SMbiosvendor", "Apple Inc."},
222 {"SMbiosversion", "XS21.88Z.006C.B06.0804011317"},
223 {"SMbiosdate", "04/01/2008"},
224 {"SMmanufacter", "Apple Inc."},
225 {"SMproductname", "Xserve2,1"},
226 {"SMsystemversion", "1.0"},
227 {"SMserial", "CK816033X8S"},
228 {"SMserialProductCountry","CK" },
229 {"SMserialYear", "8" },
230{"SMserialWeek", "16" },
231{"SMserialProductNumber","033" },
232{"SMserialModel","X8S" },
233 {"SMfamily", "Xserve"},
234 {"SMboardmanufacter", "Apple Inc."},
235 {"SMboardproduct", "Mac-F42289C8"},
236 { "",""}
237};
238
239typedef struct {
240 const char* code;
241 const char* info;
242} SMProductCountry;
243
244static const SMProductCountry const sm_country_list[]={
245 {"1C","China" },
246 {"2Z","Refurbished" },
247 {"4H","China" },
248 {"5K","China" },
249 {"8H","China" },
250 {"5D","China" },
251 {"7J","China " },
252 {"CK","Cork " },
253 /*{"E","Singapur" },*/
254 {"EE","Taiwan" },
255 /*{"F","Fremont " },*/
256 {"FC","Fountain " },
257 {"G8","USA" },
258 {"GQ","Refurbished" },
259 {"PT","Korea" },
260 {"CY","Korea" },
261 {"QT","Taiwan" },
262 {"QP","China" },
263 {"RN","Mexico" },
264 {"RM","Refurbished/Remanufactured"},
265 {"SG","Singapore" },
266 {"UV","Taiwan" },
267 {"U2","Taiwan" },
268 {"V7","Taiwan" },
269 {"VM","China" },
270 {"W8","Shanghai" },
271 {"WQ","China" },
272 {"XA","Elk Grove Sacramento"},
273 {"XB","Elk Grove Sacramento"},
274 {"YM","China /Konfiguriert"}
275};
276
277const char* sm_search_str(const SMStrEntryPair*sm_defaults, const char * key);
278const char* sm_get_random_productNumber(void);
279const char* sm_get_random_week(void);
280const char* sm_get_random_year(void);
281const char* sm_get_random_country(void);
282
283/* COPYRIGHT NOTICE: checksum8 from AppleSMBIOS */
284static uint8_t checksum8( void * start, unsigned int length )
285{
286 uint8_t csum = 0;
287 uint8_t * cp = (uint8_t *) start;
288 unsigned int i;
289
290 for ( i = 0; i < length; i++)
291 csum += *cp++;
292
293 return csum;
294}
295
296const char* sm_get_random_productNumber(void)
297{
298 static char str[4] = {0x00,0x00,0x00,0x00};
299 if(str[0] == 0)
300 {
301 // Get randomized characters
302 int rand_sn1 ;
303 int rand_sn2 ;
304 int rand_sn3 ;
305
306 rand_sn1 = arc4random_unirange(0,35);
307 rand_sn2 = arc4random_unirange(0,35);
308 rand_sn3 = arc4random_unirange(0,35);
309
310 // Append all charaters to the string
311 char tmp[2];
312 bzero(tmp,sizeof(tmp));
313 snprintf(tmp, sizeof(tmp),"%c",sn_gen_pn_str[rand_sn1]);
314 strlcpy (str, tmp, sizeof(str));
315
316 snprintf(tmp, sizeof(tmp),"%c",sn_gen_pn_str[rand_sn2]);
317 strlcat (str, tmp, sizeof(str));
318
319 snprintf(tmp, sizeof(tmp),"%c",sn_gen_pn_str[rand_sn3]);
320 strlcat (str, tmp, sizeof(str));
321
322 DBG ("fake_productNumber: %s\n",str);
323
324 }
325 return str;
326}
327
328const char* sm_get_random_week(void)
329{
330 static char str[4] = {0x00,0x00,0x00,0x00};
331 if(str[0] == 0)
332 {
333 // Get randomized characters
334 int rand_week ;
335 rand_week = arc4random_unirange(0,47);
336
337 // Append all charaters to the string
338 char tmp[3];
339 bzero(tmp,sizeof(tmp));
340
341 if (rand_week < 10) {
342 snprintf(tmp, sizeof(tmp),"0%d",rand_week);
343 strlcpy (str, tmp, sizeof(str));
344 } else if (rand_week < 100) { // avoid overflow in case random return a number >= 100
345 snprintf(tmp, sizeof(tmp),"%d",rand_week);
346 strlcpy (str, tmp, sizeof(str));
347 }
348
349 DBG ("fake_week: %s\n",str);
350
351 }
352 return str;
353}
354
355const char* sm_get_random_year(void)
356{
357 static char str[2] = {0x00,0x00};
358 if(str[0] == 0)
359 {
360 // Get randomized characters
361 int rand_year ;
362
363 rand_year = arc4random_unirange(0,9);
364
365 // Append all charaters to the string
366 char tmp[2];
367 bzero(tmp,sizeof(tmp));
368
369 if (rand_year < 10) {
370 snprintf(tmp, sizeof(tmp),"%d",rand_year);
371 strlcpy (str, tmp, sizeof(str));
372 }
373
374 DBG ("fake_year: %s\n",str);
375
376 }
377 return str;
378}
379
380const char* sm_get_random_country(void)
381{
382 static char str[3] = {0x00,0x00,0x00};
383 if(str[0] == 0)
384 {
385
386 // Get randomized characters
387 int rand_country ;
388
389 rand_country = arc4random_unirange(0,(sizeof(sm_country_list) / sizeof(sm_country_list[0]))-1);
390
391 strlcpy (str, sm_country_list[rand_country].code,strlen(sm_country_list[rand_country].code)+1);
392
393 DBG ("fake_country: %s (%s)\n",str,sm_country_list[rand_country].info);
394
395 }
396 return str;
397}
398
399const char* sm_search_str(const SMStrEntryPair*sm_defaults, const char * key)
400{
401 int i;
402
403 for (i=0; sm_defaults[i].key[0]; i++) {
404if (!strcmp (sm_defaults[i].key, key)) {
405return sm_defaults[i].value;
406}
407}
408
409 // Shouldn't happen
410 printf ("Error: no default for %s known\n", key);
411 return "";
412}
413
414const char* sm_get_defstr(const char * key, int table_num)
415{
416const SMStrEntryPair*sm_defaults;
417 const SMStrEntryPair*sm_chosen;
418 static bool serial_done = false;
419
420if (get_env(envIsServer))
421 {
422 sm_defaults=sm_xserve_defaults;
423 } else if (get_env(envIsMobile)) {
424if (get_env(envNoCores) > 1) {
425sm_defaults=sm_macbookpro_defaults;
426} else {
427sm_defaults=sm_macbook_defaults;
428}
429} else {
430switch (get_env(envNoCores))
431{
432case 1:
433sm_defaults=sm_macmini_defaults;
434break;
435case 2:
436sm_defaults=sm_imac_defaults;
437break;
438default:
439{
440switch (get_env(envFamily))
441{
442case 0x06:
443{
444switch (get_env(envModel))
445{
446case CPUID_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
447case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???
448case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)
449case 0x19: // Intel Core i5 650 @3.20 Ghz
450sm_defaults=sm_imac_core_defaults;
451break;
452
453 case CPUID_MODEL_SANDYBRIDGE:
454 case CPUID_MODEL_JAKETOWN:
455 sm_defaults=sm_imac_sandy_defaults;
456 break;
457
458case CPUID_MODEL_NEHALEM:
459 case CPUID_MODEL_NEHALEM_EX:
460 sm_defaults=sm_macpro_core_defaults;
461 break;
462
463 case CPUID_MODEL_WESTMERE:
464 case CPUID_MODEL_WESTMERE_EX:
465 sm_defaults=sm_macpro_westmere_defaults;
466 break;
467default:
468sm_defaults=sm_macpro_defaults;
469break;
470}
471break;
472}
473default:
474sm_defaults=sm_macpro_defaults;
475break;
476}
477break;
478}
479}
480}
481
482 {
483 const char*str;
484 intsize;
485
486 if (getValueForKey("SMproductname", &str, &size, DEFAULT_SMBIOS_CONFIG))
487 {
488 if (strstr (str, "MacPro5"))
489 {
490 sm_chosen = sm_macpro_westmere_defaults ;
491 }
492 else if (strstr (str, "MacPro4"))
493 {
494 sm_chosen = sm_macpro_core_defaults ;
495 }
496 else if (strstr (str, "MacPro"))
497 {
498 sm_chosen = sm_macpro_defaults ;
499 }
500 else if (strstr (str,"MacBookPro"))
501 {
502 sm_chosen = sm_macbookpro_defaults ;
503 }
504 else if (strstr (str, "MacBook"))
505 {
506 sm_chosen = sm_macbook_defaults ;
507 }
508 else if (!strncmp ("iMac12,1", str, sizeof("iMac12,1")))
509 {
510 sm_chosen = sm_imac_sandy_defaults ;
511 }
512 else if (!strncmp ("iMac11,1", str,sizeof("iMac11,1")))
513 {
514 sm_chosen = sm_imac_core_defaults ;
515 }
516 else if (strstr (str, "iMac"))
517 {
518 sm_chosen = sm_imac_defaults ;
519 }
520 else if (strstr (str, "Macmini"))
521 {
522 sm_chosen = sm_macmini_defaults ;
523 }
524 else if (strstr (str, "Xserve"))
525 {
526 sm_chosen = sm_xserve_defaults ;
527 }
528 else
529 {
530 sm_chosen = sm_defaults ;
531 }
532 }
533 else
534 sm_chosen = sm_defaults;
535 }
536
537
538 if (!strncmp ("SMserial", key, sizeof("SMserial"))) {
539
540 if (!serial_done) {
541 bzero (fake_serial,sizeof(fake_serial));
542
543 bool randomSerial = false;
544 getBoolForKey(kSMBIOSRandomSerial, &randomSerial, DEFAULT_BOOT_CONFIG) ;
545
546 if ( randomSerial ) // useless
547strlcpy (fake_serial,sm_get_random_country(), strlen(sm_get_random_country())+1);
548else
549strlcpy (fake_serial,sm_search_str(sm_chosen, "SMserialProductCountry"), strlen(sm_search_str(sm_chosen, "SMserialProductCountry"))+1);
550
551if ( randomSerial ) // useless
552strlcat (fake_serial,sm_get_random_year(),sizeof(fake_serial));
553else
554strlcat (fake_serial,sm_search_str(sm_chosen, "SMserialYear"),sizeof(fake_serial));
555
556
557if ( randomSerial ) // useless
558strlcat(fake_serial,sm_get_random_week(),sizeof(fake_serial));
559else
560strlcat (fake_serial,sm_search_str(sm_chosen, "SMserialWeek"),sizeof(fake_serial));
561
562
563if ( randomSerial )
564strlcat (fake_serial,sm_get_random_productNumber(),sizeof(fake_serial));
565else
566strlcat (fake_serial,sm_search_str(sm_chosen, "SMserialProductNumber"),sizeof(fake_serial));
567
568
569strlcat(fake_serial, sm_search_str(sm_chosen, "SMserialModel"),sizeof(fake_serial));
570
571 serial_done = true;
572
573 if ( randomSerial )
574 msglog ("fake_serial: %s\n",fake_serial);
575
576 }
577
578 return fake_serial;
579
580}
581
582 return sm_search_str(sm_chosen, key);
583
584}
585
586static int sm_get_fsb(const char *name, int table_num)
587{
588return (int)(get_env(envFSBFreq) /1000000);
589}
590
591static int sm_get_cpu (const char *name, int table_num)
592{
593return (int)(get_env(envCPUFreq) /1000000);
594}
595
596static int sm_get_bus_speed (const char *name, int table_num)
597{
598if (get_env(envVendor) == CPUID_VENDOR_INTEL)
599{
600switch (get_env(envFamily))
601{
602case 0x06:
603{
604switch (get_env(envModel))
605{
606 case CPUID_MODEL_BANIAS:// Banias0x09
607 case CPUID_MODEL_DOTHAN:// Dothan0x0D
608case CPUID_MODEL_YONAH:// Yonah0x0E
609case CPUID_MODEL_MEROM:// Merom0x0F
610case CPUID_MODEL_PENRYN:// Penryn0x17
611case CPUID_MODEL_ATOM:// Atom 45nm0x1C
612return 0; // TODO: populate bus speed for these processors
613
614 //case CPUID_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
615 //if (strstr(Platform.CPU.BrandString, "Core(TM) i5"))
616 //return 2500; // Core i5
617 //return 4800; // Core i7
618
619 //case CPUID_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
620 //case CPUID_MODEL_NEHALEM_EX:
621 //case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???
622 //return 4800; // GT/s / 1000
623 //
624case CPUID_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
625return 0; // TODO: populate bus speed for these processors
626
627 //case 0x19: // Intel Core i5 650 @3.20 Ghz
628 //return 2500; // why? Intel spec says 2.5GT/s
629
630case 0x19: // Intel Core i5 650 @3.20 Ghz
631case CPUID_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
632case CPUID_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
633case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???
634case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm)
635 case CPUID_MODEL_SANDYBRIDGE:
636 case CPUID_MODEL_JAKETOWN:
637case CPUID_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core
638case CPUID_MODEL_NEHALEM_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
639{ // thanks to dgobe for i3/i5/i7 bus speed detection
640int nhm_bus = 0x3F;
641static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
642unsigned long did, vid;
643int i;
644
645// Nehalem supports Scrubbing
646// First, locate the PCI bus where the MCH is located
647for(i = 0; i < sizeof(possible_nhm_bus); i++)
648{
649vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00);
650did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02);
651vid &= 0xFFFF;
652did &= 0xFF00;
653
654if(vid == 0x8086 && did >= 0x2C00)
655nhm_bus = possible_nhm_bus[i];
656}
657
658unsigned long qpimult, qpibusspeed;
659qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50);
660qpimult &= 0x7F;
661DBG("qpimult %d\n", qpimult);
662qpibusspeed = (qpimult * 2 * (get_env(envFSBFreq) /1000000));
663// Rek: rounding decimals to match original mac profile info
664if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100;
665DBG("qpibusspeed %d\n", qpibusspeed);
666return qpibusspeed;
667}
668}
669}
670}
671}
672return 0;
673}
674
675static int sm_get_simplecputype()
676{
677 uint8_t ncores = get_env(envNoCores);
678if (ncores >= 4)
679{
680return 0x0501; // Quad-Core Xeon
681}
682if (((ncores == 1) || (ncores == 2)) && !(get_env(envExtFeatures) & CPUID_EXTFEATURE_EM64T))
683{
684return 0x0201; // Core Solo / Duo
685}
686
687return 0x0301; // Core 2 Solo / Duo
688}
689
690static int sm_get_cputype (const char *name, int table_num)
691{
692static bool done = false;
693
694 char * BrandString= (char*)get_env_ptr(envBrandString);
695if (get_env(envVendor) == CPUID_VENDOR_INTEL) // Intel
696{
697if (!done) {
698verbose("CPU is %s, family 0x%x, model 0x%x\n", BrandString, (uint32_t)get_env(envFamily), (uint32_t)get_env(envModel));
699done = true;
700}
701
702switch (get_env(envFamily))
703{
704case 0x06:
705{
706switch (get_env(envModel))
707{
708 case CPUID_MODEL_BANIAS: // Banias
709 case CPUID_MODEL_DOTHAN: // Dothan
710case CPUID_MODEL_YONAH: // Yonah
711case CPUID_MODEL_MEROM: // Merom
712case CPUID_MODEL_PENRYN: // Penryn
713case CPUID_MODEL_ATOM: // Intel Atom (45nm)
714return sm_get_simplecputype();
715
716case CPUID_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
717 if (strstr(BrandString, "Core(TM) i7"))
718 return 0x0701; // Core i7
719 return sm_get_simplecputype();
720
721
722case CPUID_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper
723if (strstr(BrandString, "Core(TM) i5"))
724return 0x601; // Core i5
725return 0x701; // Core i7
726
727case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale)
728if (strstr(BrandString, "Core(TM) i5"))
729return 0x601; // Core i5
730return 0x0701; // Core i7
731
732 case CPUID_MODEL_SANDYBRIDGE: // Sandybridge
733case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)
734if (strstr(BrandString, "Core(TM) i3"))
735return 0x901; // Core i3
736if (strstr(BrandString, "Core(TM) i5"))
737return 0x601; // Core i5
738if (strstr(BrandString, "Core(TM) i7"))
739return 0x0701; // Core i7
740return sm_get_simplecputype();
741
742 case CPUID_MODEL_JAKETOWN:
743case CPUID_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS)
744case CPUID_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
745return 0x0701; // Core i7
746
747case 0x19: // Intel Core i5 650 @3.20 Ghz
748return 0x601; // Core i5
749}
750}
751}
752}
753
754return sm_get_simplecputype();
755}
756
757static int sm_get_memtype (const char *name, int table_num)
758{
759if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
760 intmap;
761
762 int * DmiDimm = (int*)get_env_ptr(envDmiDimm);
763 RamSlotInfo_t * RamDimm = (RamSlotInfo_t*)get_env_ptr(envRamDimm);
764
765
766 if (table_num < MAX_RAM_SLOTS) {
767 map = DmiDimm[table_num];
768 if (RamDimm[map].InUse && RamDimm[map].Type != 0) {
769 DBG("RAM Detected Type = %d\n", RamDimm[map].Type);
770 return RamDimm[map].Type;
771 }
772 }
773}
774
775return SMB_MEM_TYPE_DDR2;
776}
777
778static int sm_get_memspeed (const char *name, int table_num)
779{
780if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
781 intmap;
782
783 int * DmiDimm = (int*)get_env_ptr(envDmiDimm);
784 RamSlotInfo_t * RamDimm = (RamSlotInfo_t*)get_env_ptr(envRamDimm);
785
786 if (table_num < MAX_RAM_SLOTS) {
787 map = DmiDimm[table_num];
788 if (RamDimm[map].InUse && RamDimm[map].Frequency != 0) {
789 DBG("RAM Detected Freq = %d Mhz\n", RamDimm[map].Frequency);
790 return RamDimm[map].Frequency;
791 }
792 }
793}
794return 800;
795}
796
797static const char *sm_get_memvendor (const char *name, int table_num)
798{
799if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
800 intmap;
801
802 int * DmiDimm = (int*)get_env_ptr(envDmiDimm);
803 RamSlotInfo_t * RamDimm = (RamSlotInfo_t*)get_env_ptr(envRamDimm);
804
805 if (table_num < MAX_RAM_SLOTS) {
806 map = DmiDimm[table_num];
807 if (RamDimm[map].InUse && strlen(RamDimm[map].Vendor) > 0) {
808 DBG("RAM Detected Vendor[%d]='%s'\n", table_num, RamDimm[map].Vendor);
809 return RamDimm[map].Vendor;
810 }
811 }
812}
813return "N/A";
814}
815
816static const char *sm_get_memserial (const char *name, int table_num)
817{
818if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
819 intmap;
820
821 int * DmiDimm = (int*)get_env_ptr(envDmiDimm);
822 RamSlotInfo_t * RamDimm = (RamSlotInfo_t*)get_env_ptr(envRamDimm);
823
824 if (table_num < MAX_RAM_SLOTS) {
825 map = DmiDimm[table_num];
826 if (RamDimm[map].InUse && strlen(RamDimm[map].SerialNo) > 0) {
827 DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "",
828 map, table_num, RamDimm[map].SerialNo);
829 return RamDimm[map].SerialNo;
830 }
831 }
832 }
833return "N/A";
834}
835
836static const char *sm_get_mempartno (const char *name, int table_num)
837{
838if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
839 intmap;
840
841 int * DmiDimm = (int*)get_env_ptr(envDmiDimm);
842 RamSlotInfo_t * RamDimm = (RamSlotInfo_t*)get_env_ptr(envRamDimm);
843
844 if (table_num < MAX_RAM_SLOTS) {
845 map = DmiDimm[table_num];
846 if (RamDimm[map].InUse && strlen(RamDimm[map].PartNo) > 0) {
847 DBG("Ram Detected PartNo[%d]='%s'\n", table_num, RamDimm[map].PartNo);
848 return RamDimm[map].PartNo;
849 }
850 }
851}
852return "N/A";
853}
854
855static int sm_one (int tablen)
856{
857return 1;
858}
859
860struct smbios_property smbios_properties[]=
861{
862{.name="SMbiosvendor",.table_type= 0,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
863{.name="SMbiosversion",.table_type= 0,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
864{.name="SMbiosdate",.table_type= 0,.value_type=SMSTRING,.offset=0x08,.auto_str=sm_get_defstr},
865{.name="SMmanufacter",.table_type= 1,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
866{.name="SMproductname",.table_type= 1,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
867{.name="SMsystemversion",.table_type= 1,.value_type=SMSTRING,.offset=0x06,.auto_str=sm_get_defstr},
868{.name="SMserial",.table_type= 1,.value_type=SMSTRING,.offset=0x07,.auto_str=sm_get_defstr},
869{.name="SMUUID",.table_type= 1, .value_type=SMOWORD,.offset=0x08,.auto_oword=0},
870{.name="SMfamily",.table_type= 1,.value_type=SMSTRING,.offset=0x1a,.auto_str=sm_get_defstr},
871{.name="SMboardmanufacter",.table_type= 2, .value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
872{.name="SMboardproduct",.table_type= 2, .value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
873{.name="SMexternalclock",.table_type= 4,.value_type=SMWORD,.offset=0x12,.auto_int=sm_get_fsb},
874{.name="SMmaximalclock",.table_type= 4,.value_type=SMWORD,.offset=0x14,.auto_int=sm_get_cpu},
875{.name="SMmemdevloc",.table_type=17,.value_type=SMSTRING,.offset=0x10,.auto_str=0},
876{.name="SMmembankloc",.table_type=17,.value_type=SMSTRING,.offset=0x11,.auto_str=0},
877{.name="SMmemtype",.table_type=17,.value_type=SMBYTE,.offset=0x12,.auto_int=sm_get_memtype},
878{.name="SMmemspeed",.table_type=17,.value_type=SMWORD,.offset=0x15,.auto_int=sm_get_memspeed},
879{.name="SMmemmanufacter",.table_type=17,.value_type=SMSTRING,.offset=0x17,.auto_str=sm_get_memvendor},
880{.name="SMmemserial",.table_type=17,.value_type=SMSTRING,.offset=0x18,.auto_str=sm_get_memserial},
881{.name="SMmempart",.table_type=17,.value_type=SMSTRING,.offset=0x1A,.auto_str=sm_get_mempartno},
882{.name="SMcputype",.table_type=131,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_cputype},
883{.name="SMbusspeed",.table_type=132,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_bus_speed}
884};
885
886struct smbios_table_description smbios_table_descriptions[]=
887{
888{.type=0,.len=0x18,.numfunc=sm_one},
889{.type=1,.len=0x1b,.numfunc=sm_one},
890{.type=2,.len=0x0f,.numfunc=sm_one},
891{.type=4,.len=0x2a,.numfunc=sm_one},
892{.type=17,.len=0x1c,.numfunc=0},
893{.type=131,.len=0x06,.numfunc=sm_one},
894{.type=132,.len=0x06,.numfunc=sm_one}
895};
896
897/** Compute necessary space requirements for new smbios */
898static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)
899{
900struct SMBEntryPoint*ret;
901char*smbiostables;
902char*tablesptr;
903intorigsmbiosnum;
904inti, j;
905inttablespresent[256];
906booldo_auto=true;
907
908bzero(tablespresent, sizeof(tablespresent));
909
910getBoolForKey(kSMBIOSdefaults, &do_auto, DEFAULT_BOOT_CONFIG);
911
912ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));
913if (origsmbios) {
914smbiostables = (char *)origsmbios->dmi.tableAddress;
915origsmbiosnum = origsmbios->dmi.structureCount;
916} else {
917smbiostables = NULL;
918origsmbiosnum = 0;
919}
920
921// _SM_
922ret->anchor[0] = 0x5f;
923ret->anchor[1] = 0x53;
924ret->anchor[2] = 0x4d;
925ret->anchor[3] = 0x5f;
926ret->entryPointLength = sizeof(*ret);
927ret->majorVersion = 2;
928ret->minorVersion = 1;
929ret->maxStructureSize = 0; // will be calculated later in this function
930ret->entryPointRevision = 0;
931for (i=0;i<5;i++) {
932ret->formattedArea[i] = 0;
933}
934//_DMI_
935ret->dmi.anchor[0] = 0x5f;
936ret->dmi.anchor[1] = 0x44;
937ret->dmi.anchor[2] = 0x4d;
938ret->dmi.anchor[3] = 0x49;
939ret->dmi.anchor[4] = 0x5f;
940ret->dmi.tableLength = 0; // will be calculated later in this function
941ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()
942ret->dmi.structureCount = 0; // will be calculated later in this function
943ret->dmi.bcdRevision = 0x21;
944tablesptr = smbiostables;
945
946 bool randomSerial = false;
947 getBoolForKey(kSMBIOSRandomSerial, &randomSerial, DEFAULT_BOOT_CONFIG);
948
949 // add stringlen of overrides to original stringlen, update maxStructure size adequately,
950 // update structure count and tablepresent[type] with count of type.
951if (smbiostables) {
952for (i=0; i<origsmbiosnum; i++) {
953struct smbios_table_header*cur = (struct smbios_table_header *)tablesptr;
954char*stringsptr;
955intstringlen;
956
957tablesptr += cur->length;
958stringsptr = tablesptr;
959for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);
960tablesptr += 2;
961stringlen = tablesptr - stringsptr - 1;
962if (stringlen == 1) {
963stringlen = 0;
964}
965for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
966const char*str;
967intsize;
968charaltname[40];
969
970snprintf(altname, sizeof(altname),"%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);
971 if (smbios_properties[j].table_type == cur->type &&
972 smbios_properties[j].value_type == SMSTRING &&
973 smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name, sizeof("SMserial")))) {
974
975 stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
976
977 } else if (smbios_properties[j].table_type == cur->type &&
978 smbios_properties[j].value_type == SMSTRING &&
979 (getValueForKey(smbios_properties[j].name, &str, &size, DEFAULT_SMBIOS_CONFIG) ||
980 getValueForKey(altname,&str, &size, DEFAULT_SMBIOS_CONFIG)))
981{
982stringlen += size + 1;
983} else if (smbios_properties[j].table_type == cur->type &&
984 smbios_properties[j].value_type == SMSTRING &&
985 do_auto && smbios_properties[j].auto_str)
986{
987stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
988}
989}
990if (stringlen == 0) {
991stringlen = 1;
992}
993stringlen++;
994if (ret->maxStructureSize < cur->length+stringlen) {
995ret->maxStructureSize=cur->length+stringlen;
996}
997ret->dmi.tableLength += cur->length+stringlen;
998ret->dmi.structureCount++;
999tablespresent[cur->type]++;
1000}
1001}
1002 // Add eventually table types whose detected count would be < required count, and update ret header with:
1003 // new stringlen addons, structure count, and tablepresent[type] count adequately
1004for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
1005intnumnec=-1;
1006charbuffer[40];
1007
1008snprintf(buffer, sizeof(buffer),"SMtable%d", i);
1009if (!getIntForKey(buffer, &numnec, DEFAULT_SMBIOS_CONFIG)) {
1010numnec = -1;
1011}
1012if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {
1013numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
1014}
1015while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
1016intstringlen = 0;
1017for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
1018const char*str;
1019intsize;
1020charaltname[40];
1021
1022snprintf(altname, sizeof(altname), "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);
1023 if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
1024 smbios_properties[j].value_type==SMSTRING &&
1025 smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name, sizeof("SMserial")))) {
1026
1027 stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
1028
1029 } else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
1030 smbios_properties[j].value_type == SMSTRING &&
1031 (getValueForKey(altname, &str, &size, DEFAULT_SMBIOS_CONFIG) ||
1032 getValueForKey(smbios_properties[j].name, &str, &size, DEFAULT_SMBIOS_CONFIG)))
1033{
1034stringlen += size + 1;
1035} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
1036 smbios_properties[j].value_type==SMSTRING &&
1037 do_auto && smbios_properties[j].auto_str)
1038{
1039stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
1040}
1041}
1042if (stringlen == 0) {
1043stringlen = 1;
1044}
1045stringlen++;
1046if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {
1047ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;
1048}
1049ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;
1050ret->dmi.structureCount++;
1051tablespresent[smbios_table_descriptions[i].type]++;
1052}
1053}
1054return ret;
1055}
1056
1057/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint
1058 * struct has been created by smbios_dry_run, update each table struct content of new smbios
1059 * int the new allocated table address of size newsmbios->tablelength.
1060 */
1061static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)
1062{
1063char *smbiostables;
1064char *tablesptr, *newtablesptr;
1065int origsmbiosnum;
1066// bitmask of used handles
1067uint8_t handles[8192];
1068uint16_t nexthandle=0;
1069int i, j;
1070int tablespresent[256];
1071bool do_auto=true;
1072
1073 static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info !
1074
1075 bool randomSerial = false;
1076 getBoolForKey(kSMBIOSRandomSerial, &randomSerial, DEFAULT_BOOT_CONFIG);
1077
1078bzero(tablespresent, sizeof(tablespresent));
1079bzero(handles, sizeof(handles));
1080
1081getBoolForKey(kSMBIOSdefaults, &do_auto, DEFAULT_BOOT_CONFIG);
1082
1083newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);
1084if (origsmbios) {
1085smbiostables = (char *)origsmbios->dmi.tableAddress;
1086origsmbiosnum = origsmbios->dmi.structureCount;
1087} else {
1088smbiostables = NULL;
1089origsmbiosnum = 0;
1090}
1091tablesptr = smbiostables;
1092newtablesptr = (char *)newsmbios->dmi.tableAddress;
1093
1094 // if old smbios exists then update new smbios with old smbios original content first
1095if (smbiostables) {
1096for (i=0; i<origsmbiosnum; i++) {
1097struct smbios_table_header*oldcur = (struct smbios_table_header *) tablesptr;
1098struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
1099char*stringsptr;
1100intnstrings = 0;
1101
1102handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);
1103
1104 // copy table length from old table to new table but not the old strings
1105memcpy(newcur,oldcur, oldcur->length);
1106
1107tablesptr += oldcur->length;
1108stringsptr = tablesptr;
1109newtablesptr += oldcur->length;
1110
1111 // calculate the number of strings in the old content
1112for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {
1113if (tablesptr[0] == 0) {
1114nstrings++;
1115}
1116}
1117if (tablesptr != stringsptr) {
1118nstrings++;
1119}
1120tablesptr += 2;
1121
1122 // copy the old strings to new table
1123memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);
1124
1125 // point to next possible space for a string (deducting the second 0 char at the end)
1126newtablesptr += tablesptr - stringsptr - 1;
1127 if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator
1128newtablesptr--;
1129}
1130
1131 // now for each property in the table update the overrides if any (auto or user)
1132for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
1133const char*str;
1134intsize;
1135intnum;
1136charaltname[40];
1137
1138snprintf(altname, sizeof(altname), smbios_properties[j].name, tablespresent[newcur->type] + 1);
1139if (smbios_properties[j].table_type == newcur->type) {
1140switch (smbios_properties[j].value_type) {
1141 case SMSTRING:
1142 if (smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name,sizeof("SMserial"))))
1143 {
1144 str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1145 size = strlen(str);
1146 memcpy(newtablesptr, str, size);
1147 newtablesptr[size] = 0;
1148 newtablesptr += size + 1;
1149 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1150
1151 } else if (getValueForKey(altname, &str, &size, DEFAULT_SMBIOS_CONFIG) ||
1152 getValueForKey(smbios_properties[j].name, &str, &size, DEFAULT_SMBIOS_CONFIG))
1153 {
1154 memcpy(newtablesptr, str, size);
1155 newtablesptr[size] = 0;
1156 newtablesptr += size + 1;
1157 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1158 } else if (do_auto && smbios_properties[j].auto_str) {
1159 str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1160 size = strlen(str);
1161 memcpy(newtablesptr, str, size);
1162 newtablesptr[size] = 0;
1163 newtablesptr += size + 1;
1164 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1165 }
1166 break;
1167
1168 case SMOWORD:
1169 if (getValueForKey(altname, &str, &size, DEFAULT_SMBIOS_CONFIG) ||
1170 getValueForKey(smbios_properties[j].name, &str, &size, DEFAULT_SMBIOS_CONFIG))
1171 {
1172 intk=0, t=0, kk=0;
1173 const char*ptr = str;
1174 memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
1175 while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
1176 ptr++;
1177 }
1178 if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
1179 ptr += 2;
1180 }
1181 for (;ptr-str<size && *ptr && k<16;ptr++) {
1182 if (*ptr>='0' && *ptr<='9') {
1183 (t=(t<<4)|(*ptr-'0')),kk++;
1184 }
1185 if (*ptr>='a' && *ptr<='f') {
1186 (t=(t<<4)|(*ptr-'a'+10)),kk++;
1187 }
1188 if (*ptr>='A' && *ptr<='F') {
1189 (t=(t<<4)|(*ptr-'A'+10)),kk++;
1190 }
1191 if (kk == 2) {
1192 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
1193 k++;
1194 kk = 0;
1195 t = 0;
1196 }
1197 }
1198 }
1199 break;
1200
1201 case SMBYTE:
1202 if (getIntForKey(altname, &num, DEFAULT_SMBIOS_CONFIG) ||
1203 getIntForKey(smbios_properties[j].name, &num, DEFAULT_SMBIOS_CONFIG))
1204 {
1205 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1206 } else if (do_auto && smbios_properties[j].auto_int) {
1207 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1208 }
1209 break;
1210
1211 case SMWORD:
1212 if (getIntForKey(altname, &num, DEFAULT_SMBIOS_CONFIG) ||
1213 getIntForKey(smbios_properties[j].name, &num, DEFAULT_SMBIOS_CONFIG))
1214 {
1215 *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1216 } else if (do_auto && smbios_properties[j].auto_int) {
1217 *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1218 }
1219 break;
1220}
1221}
1222}
1223if (nstrings == 0) {
1224newtablesptr[0] = 0;
1225newtablesptr++;
1226}
1227newtablesptr[0] = 0;
1228newtablesptr++;
1229tablespresent[newcur->type]++;
1230}
1231}
1232
1233 // for each eventual complementary table not present in the original smbios, do the overrides
1234for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
1235intnumnec = -1;
1236charbuffer[40];
1237
1238snprintf(buffer, sizeof(buffer),"SMtable%d", i);
1239if (!getIntForKey(buffer, &numnec, DEFAULT_SMBIOS_CONFIG)) {
1240numnec = -1;
1241}
1242if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {
1243numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
1244}
1245while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
1246struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
1247intnstrings = 0;
1248
1249memset(newcur,0, smbios_table_descriptions[i].len);
1250while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {
1251nexthandle++;
1252}
1253newcur->handle = nexthandle;
1254handles[nexthandle / 8] |= 1 << (nexthandle % 8);
1255newcur->type = smbios_table_descriptions[i].type;
1256newcur->length = smbios_table_descriptions[i].len;
1257newtablesptr += smbios_table_descriptions[i].len;
1258for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
1259const char*str;
1260intsize;
1261intnum;
1262charaltname[40];
1263
1264snprintf(altname, sizeof(altname),"%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
1265if (smbios_properties[j].table_type == newcur->type) {
1266switch (smbios_properties[j].value_type) {
1267 case SMSTRING:
1268 if (smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name,sizeof("SMserial"))))
1269 {
1270 str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1271 size = strlen(str);
1272 memcpy(newtablesptr, str, size);
1273 newtablesptr[size] = 0;
1274 newtablesptr += size + 1;
1275 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1276
1277 } else if (getValueForKey(altname, &str, &size, DEFAULT_SMBIOS_CONFIG) ||
1278 getValueForKey(smbios_properties[j].name, &str, &size, DEFAULT_SMBIOS_CONFIG))
1279 {
1280 memcpy(newtablesptr, str, size);
1281 newtablesptr[size] = 0;
1282 newtablesptr += size + 1;
1283 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1284 } else if (do_auto && smbios_properties[j].auto_str) {
1285 str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1286 size = strlen(str);
1287 memcpy(newtablesptr, str, size);
1288 newtablesptr[size] = 0;
1289 newtablesptr += size + 1;
1290 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1291 }
1292 break;
1293
1294 case SMOWORD:
1295 if (getValueForKey(altname, &str, &size, DEFAULT_SMBIOS_CONFIG) ||
1296 getValueForKey(smbios_properties[j].name, &str, &size, DEFAULT_SMBIOS_CONFIG))
1297 {
1298 intk=0, t=0, kk=0;
1299 const char*ptr = str;
1300
1301 memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
1302 while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
1303 ptr++;
1304 }
1305 if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
1306 ptr += 2;
1307 }
1308 for (;ptr-str<size && *ptr && k<16;ptr++) {
1309 if (*ptr>='0' && *ptr<='9') {
1310 (t=(t<<4)|(*ptr-'0')),kk++;
1311 }
1312 if (*ptr>='a' && *ptr<='f') {
1313 (t=(t<<4)|(*ptr-'a'+10)),kk++;
1314 }
1315 if (*ptr>='A' && *ptr<='F') {
1316 (t=(t<<4)|(*ptr-'A'+10)),kk++;
1317 }
1318 if (kk == 2) {
1319 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
1320 k++;
1321 kk = 0;
1322 t = 0;
1323 }
1324 }
1325 }
1326 break;
1327
1328 case SMBYTE:
1329 if (getIntForKey(altname, &num, DEFAULT_SMBIOS_CONFIG) ||
1330 getIntForKey(smbios_properties[j].name, &num, DEFAULT_SMBIOS_CONFIG))
1331 {
1332 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1333 } else if (do_auto && smbios_properties[j].auto_int) {
1334 *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1335 }
1336 break;
1337
1338 case SMWORD:
1339 if (getIntForKey(altname, &num, DEFAULT_SMBIOS_CONFIG) ||
1340 getIntForKey(smbios_properties[j].name, &num, DEFAULT_SMBIOS_CONFIG))
1341 {
1342 *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1343 } else if (do_auto && smbios_properties[j].auto_int) {
1344 *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1345 }
1346 break;
1347}
1348}
1349}
1350if (nstrings == 0) {
1351newtablesptr[0] = 0;
1352newtablesptr++;
1353}
1354newtablesptr[0] = 0;
1355newtablesptr++;
1356tablespresent[smbios_table_descriptions[i].type]++;
1357}
1358}
1359
1360 // calculate new checksums
1361newsmbios->dmi.checksum = 0;
1362newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));
1363newsmbios->checksum = 0;
1364newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));
1365
1366if (!done) {
1367verbose("Patched DMI Table\n");
1368done=true;
1369}
1370}
1371
1372#define MAX_DMI_TABLES 96
1373typedef struct DmiNumAssocTag {
1374 struct DMIHeader * dmi;
1375 uint8_t type;
1376} DmiNumAssoc;
1377
1378static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES];
1379static int DmiTablePairCount = 0;
1380static int current_pos=0;
1381static bool ftTablePairInit = true;
1382
1383/**
1384 * Get a table structure entry from a type specification and a smbios address
1385 * return NULL if table is not found
1386 */
1387void getSmbiosTableStructure(struct SMBEntryPoint *smbios)
1388{
1389 struct DMIHeader * dmihdr=NULL;
1390 SMBByte* p;
1391 int i;
1392
1393 if (ftTablePairInit && smbios!=NULL) {
1394 ftTablePairInit = false;
1395#if DEBUG_SMBIOS
1396 printf(">>> SMBIOSAddr=0x%08x\n", smbios);
1397 printf(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress,
1398 smbios->dmi.tableLength, smbios->dmi.structureCount);
1399#endif
1400 p = (SMBByte *) smbios->dmi.tableAddress;
1401 for (i=0;
1402 i < smbios->dmi.structureCount &&
1403 p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength;
1404 i++) {
1405 dmihdr = (struct DMIHeader *) p;
1406
1407#if DEBUG_SMBIOS
1408 // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length);
1409#endif
1410 if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break;
1411 if (DmiTablePairCount < MAX_DMI_TABLES) {
1412 DmiTablePair[DmiTablePairCount].dmi = dmihdr;
1413 DmiTablePair[DmiTablePairCount].type = dmihdr->type;
1414 DmiTablePairCount++;
1415 }
1416 else {
1417 printf("DMI table entries list is full! Next entries won't be stored.\n");
1418 }
1419#if DEBUG_SMBIOS
1420 printf("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length);
1421#endif
1422 p = p + dmihdr->length;
1423 while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) {
1424 p++;
1425}
1426 p += 2;
1427}
1428
1429 }
1430}
1431
1432/** Find first original dmi Table with a particular type */
1433struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength)
1434{
1435 current_pos = 0;
1436
1437 return FindNextDmiTableOfType(type, minlength);
1438};
1439
1440/** Find next original dmi Table with a particular type */
1441struct DMIHeader* FindNextDmiTableOfType(int type, int minlength)
1442{
1443 int i;
1444
1445 if (ftTablePairInit) getSmbiosOriginal();
1446
1447 for (i=current_pos; i < DmiTablePairCount; i++) {
1448 if (type == DmiTablePair[i].type &&
1449 DmiTablePair[i].dmi &&
1450 DmiTablePair[i].dmi->length >= minlength ) {
1451 current_pos = i+1;
1452 return DmiTablePair[i].dmi;
1453 }
1454 }
1455 return NULL; // not found
1456};
1457
1458
1459const char * smbiosStringAtIndex(DMIHeader* smHeader, int index, int* length )
1460{
1461 const char * last = 0;
1462 const char * next = (const char *) smHeader + smHeader->length;
1463
1464 if ( length ) *length = 0;
1465 while ( index-- )
1466 {
1467 last = 0;
1468const char * cp = 0;
1469for ( cp = next; *cp || cp[1]; cp++ )
1470 {
1471 if ( *cp == '\0' )
1472 {
1473 last = next;
1474 next = cp + 1;
1475 break;
1476 }
1477 }
1478 if ( last == 0 ) break;
1479 }
1480
1481 if ( last )
1482 {
1483 while (*last == ' ') last++;
1484 if (length)
1485 {
1486 UInt8 len;
1487 for ( len = next - last - 1; len && last[len - 1] == ' '; len-- )
1488 ;
1489 *length = len; // number of chars not counting the terminating NULL
1490 }
1491 }
1492
1493 return last ? last : "";
1494}
1495
1496
1497struct SMBEntryPoint *getSmbiosPatched(struct SMBEntryPoint *orig)
1498{
1499 struct SMBEntryPoint *patched = NULL; // cached
1500
1501patched = smbios_dry_run(orig);
1502 if(patched==NULL) {
1503 printf("Could not create new SMBIOS !!\n");
1504 pause();
1505 }
1506 else {
1507 smbios_real_run(orig, patched);
1508 }
1509
1510
1511 return patched;
1512
1513}
1514
1515/*
1516 char* getSmbiosProductName()
1517 {
1518 struct SMBEntryPoint*smbios;
1519 SMBSystemInformation*p;
1520 char*tempString;
1521 inttmpLen;
1522
1523 smbios = getSmbiosOriginal();
1524 if (smbios==NULL) return NULL;
1525
1526 p = (SMBSystemInformation*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information
1527 if (p==NULL) return NULL;
1528
1529
1530 tempString = (char*)smbiosStringAtIndex((DMIHeader*)p, p->productName, &tmpLen);
1531 tempString[tmpLen] = 0;
1532
1533 gSMBIOSBoardModel = malloc(tmpLen + 1);
1534 if(gSMBIOSBoardModel)
1535 {
1536 strncpy(gSMBIOSBoardModel, tempString, tmpLen);
1537 Node* node = DT__FindNode("/", false);
1538 DT__AddProperty(node, "orig-model", tmpLen, gSMBIOSBoardModel);
1539 }
1540 verbose("Actual model name is '%s'\n", tempString);
1541 return tempString;
1542 }
1543 */
1544
1545void scan_memory(void)
1546{
1547 int i=0;
1548 struct DMIHeader * dmihdr = NULL;
1549
1550 struct DMIMemoryModuleInfo* memInfo[MAX_RAM_SLOTS]; // 6
1551 struct DMIPhysicalMemoryArray* physMemArray; // 16
1552 struct DMIMemoryDevice* memDev[MAX_RAM_SLOTS]; //17
1553
1554 intMaxMemorySlots = 0;// number of memory slots polulated by SMBIOS
1555
1556 /* We mainly don't use obsolete tables 5,6 because most of computers don't handle it anymore */
1557 intMemoryModules = 0;
1558
1559 /* Now lets peek info rom table 16,17 as for some bios, table 5 & 6 are not used */
1560 physMemArray = (struct DMIPhysicalMemoryArray*) FindFirstDmiTableOfType(16, 4);
1561
1562 MaxMemorySlots = physMemArray ? physMemArray->numberOfMemoryDevices : 0;
1563
1564 i = 0;
1565 static RamSlotInfo_tRamDimm[MAX_RAM_SLOTS];// Information about each slot
1566
1567 for(dmihdr = FindFirstDmiTableOfType(17, 4);
1568 dmihdr;
1569 dmihdr = FindNextDmiTableOfType(17, 4) ) {
1570 memDev[i] = (struct DMIMemoryDevice*) dmihdr;
1571 if (memDev[i]->size !=0 ) MemoryModules++;
1572 if (memDev[i]->speed>0) RamDimm[i].Frequency = memDev[i]->speed; // take it here for now but we'll check spd and dmi table 6 as well
1573 i++;
1574 }
1575 // for table 6, we only have a look at the current speed
1576 i = 0;
1577 for(dmihdr = FindFirstDmiTableOfType(6, 4);
1578 dmihdr;
1579 dmihdr = FindNextDmiTableOfType(6, 4) ) {
1580 memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr;
1581 if (memInfo[i]->currentSpeed > RamDimm[i].Frequency)
1582 RamDimm[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any
1583 i++;
1584 }
1585
1586 safe_set_env(envDMIMaxMemorySlots, MaxMemorySlots);
1587 safe_set_env(envDMIMemModules, MemoryModules);
1588 safe_set_env_copy(envRamDimm, RamDimm, sizeof(RamDimm));
1589
1590#if 0
1591 dumpAllTablesOfType(17);
1592 getc();
1593#endif
1594}
1595

Archive Download this file

Revision: 2112