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

Archive Download this file

Revision: 1701