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

Archive Download this file

Revision: 1972