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

Archive Download this file

Revision: 2044