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

Archive Download this file

Revision: 1840