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)
701return 0x0701; // Core i7
702
703case CPUID_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper
704if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))
705return 0x601; // Core i5
706return 0x701; // Core i7
707
708case CPUID_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale)
709if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))
710return 0x601; // Core i5
711return 0x0701; // Core i7
712
713 case CPUID_MODEL_SANDYBRIDGE: // Sandybridge
714case CPUID_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)
715if (strstr(Platform->CPU.BrandString, "Core(TM) i3"))
716return 0x901; // Core i3
717if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))
718return 0x601; // Core i5
719if (strstr(Platform->CPU.BrandString, "Core(TM) i7"))
720return 0x0701; // Core i7
721return sm_get_simplecputype();
722
723 case CPUID_MODEL_JAKETOWN:
724case CPUID_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS)
725case CPUID_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
726return 0x0701; // Core i7
727
728case 0x19: // Intel Core i5 650 @3.20 Ghz
729return 0x601; // Core i5
730}
731}
732}
733}
734
735return sm_get_simplecputype();
736}
737
738static int sm_get_memtype (const char *name, int table_num)
739{
740if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
741intmap;
742
743if (table_num < MAX_RAM_SLOTS) {
744map = Platform->DMI.DIMM[table_num];
745if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Type != 0) {
746 DBG("RAM Detected Type = %d\n", Platform->RAM.DIMM[map].Type);
747 return Platform->RAM.DIMM[map].Type;
748}
749}
750}
751
752return SMB_MEM_TYPE_DDR2;
753}
754
755static int sm_get_memspeed (const char *name, int table_num)
756{
757if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
758intmap;
759
760if (table_num < MAX_RAM_SLOTS) {
761map = Platform->DMI.DIMM[table_num];
762if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Frequency != 0) {
763 DBG("RAM Detected Freq = %d Mhz\n", Platform->RAM.DIMM[map].Frequency);
764 return Platform->RAM.DIMM[map].Frequency;
765}
766}
767}
768return 800;
769}
770
771static const char *sm_get_memvendor (const char *name, int table_num)
772{
773if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
774intmap;
775
776if (table_num < MAX_RAM_SLOTS) {
777map = Platform->DMI.DIMM[table_num];
778if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].Vendor) > 0) {
779DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].Vendor);
780return Platform->RAM.DIMM[map].Vendor;
781}
782}
783}
784return "N/A";
785}
786
787static const char *sm_get_memserial (const char *name, int table_num)
788{
789if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
790intmap;
791
792if (table_num < MAX_RAM_SLOTS) {
793map = Platform->DMI.DIMM[table_num];
794if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].SerialNo) > 0) {
795 DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "",
796 map, table_num, Platform->RAM.DIMM[map].SerialNo);
797 return Platform->RAM.DIMM[map].SerialNo;
798}
799}
800 }
801return "N/A";
802}
803
804static const char *sm_get_mempartno (const char *name, int table_num)
805{
806if (execute_hook("isMemoryRegistred", NULL, NULL, NULL, NULL, NULL, NULL) == EFI_SUCCESS) {
807intmap;
808
809if (table_num < MAX_RAM_SLOTS) {
810map = Platform->DMI.DIMM[table_num];
811if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].PartNo) > 0) {
812DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].PartNo);
813return Platform->RAM.DIMM[map].PartNo;
814}
815}
816}
817return "N/A";
818}
819
820static int sm_one (int tablen)
821{
822return 1;
823}
824
825struct smbios_property smbios_properties[]=
826{
827{.name="SMbiosvendor",.table_type= 0,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
828{.name="SMbiosversion",.table_type= 0,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
829{.name="SMbiosdate",.table_type= 0,.value_type=SMSTRING,.offset=0x08,.auto_str=sm_get_defstr},
830{.name="SMmanufacter",.table_type= 1,.value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
831{.name="SMproductname",.table_type= 1,.value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
832{.name="SMsystemversion",.table_type= 1,.value_type=SMSTRING,.offset=0x06,.auto_str=sm_get_defstr},
833{.name="SMserial",.table_type= 1,.value_type=SMSTRING,.offset=0x07,.auto_str=sm_get_defstr},
834{.name="SMUUID",.table_type= 1, .value_type=SMOWORD,.offset=0x08,.auto_oword=0},
835{.name="SMfamily",.table_type= 1,.value_type=SMSTRING,.offset=0x1a,.auto_str=sm_get_defstr},
836{.name="SMboardmanufacter",.table_type= 2, .value_type=SMSTRING,.offset=0x04,.auto_str=sm_get_defstr},
837{.name="SMboardproduct",.table_type= 2, .value_type=SMSTRING,.offset=0x05,.auto_str=sm_get_defstr},
838{.name="SMexternalclock",.table_type= 4,.value_type=SMWORD,.offset=0x12,.auto_int=sm_get_fsb},
839{.name="SMmaximalclock",.table_type= 4,.value_type=SMWORD,.offset=0x14,.auto_int=sm_get_cpu},
840{.name="SMmemdevloc",.table_type=17,.value_type=SMSTRING,.offset=0x10,.auto_str=0},
841{.name="SMmembankloc",.table_type=17,.value_type=SMSTRING,.offset=0x11,.auto_str=0},
842{.name="SMmemtype",.table_type=17,.value_type=SMBYTE,.offset=0x12,.auto_int=sm_get_memtype},
843{.name="SMmemspeed",.table_type=17,.value_type=SMWORD,.offset=0x15,.auto_int=sm_get_memspeed},
844{.name="SMmemmanufacter",.table_type=17,.value_type=SMSTRING,.offset=0x17,.auto_str=sm_get_memvendor},
845{.name="SMmemserial",.table_type=17,.value_type=SMSTRING,.offset=0x18,.auto_str=sm_get_memserial},
846{.name="SMmempart",.table_type=17,.value_type=SMSTRING,.offset=0x1A,.auto_str=sm_get_mempartno},
847{.name="SMcputype",.table_type=131,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_cputype},
848{.name="SMbusspeed",.table_type=132,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_bus_speed}
849};
850
851struct smbios_table_description smbios_table_descriptions[]=
852{
853{.type=0,.len=0x18,.numfunc=sm_one},
854{.type=1,.len=0x1b,.numfunc=sm_one},
855{.type=2,.len=0x0f,.numfunc=sm_one},
856{.type=4,.len=0x2a,.numfunc=sm_one},
857{.type=17,.len=0x1c,.numfunc=0},
858{.type=131,.len=0x06,.numfunc=sm_one},
859{.type=132,.len=0x06,.numfunc=sm_one}
860};
861
862/** Compute necessary space requirements for new smbios */
863static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)
864{
865struct SMBEntryPoint*ret;
866char*smbiostables;
867char*tablesptr;
868intorigsmbiosnum;
869inti, j;
870inttablespresent[256];
871booldo_auto=true;
872
873bzero(tablespresent, sizeof(tablespresent));
874
875getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
876
877ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));
878if (origsmbios) {
879smbiostables = (char *)origsmbios->dmi.tableAddress;
880origsmbiosnum = origsmbios->dmi.structureCount;
881} else {
882smbiostables = NULL;
883origsmbiosnum = 0;
884}
885
886// _SM_
887ret->anchor[0] = 0x5f;
888ret->anchor[1] = 0x53;
889ret->anchor[2] = 0x4d;
890ret->anchor[3] = 0x5f;
891ret->entryPointLength = sizeof(*ret);
892ret->majorVersion = 2;
893ret->minorVersion = 1;
894ret->maxStructureSize = 0; // will be calculated later in this function
895ret->entryPointRevision = 0;
896for (i=0;i<5;i++) {
897ret->formattedArea[i] = 0;
898}
899//_DMI_
900ret->dmi.anchor[0] = 0x5f;
901ret->dmi.anchor[1] = 0x44;
902ret->dmi.anchor[2] = 0x4d;
903ret->dmi.anchor[3] = 0x49;
904ret->dmi.anchor[4] = 0x5f;
905ret->dmi.tableLength = 0; // will be calculated later in this function
906ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()
907ret->dmi.structureCount = 0; // will be calculated later in this function
908ret->dmi.bcdRevision = 0x21;
909tablesptr = smbiostables;
910
911 bool randomSerial = false;
912 getBoolForKey(kSMBIOSRandomSerial, &randomSerial, &bootInfo->bootConfig);
913
914 // add stringlen of overrides to original stringlen, update maxStructure size adequately,
915 // update structure count and tablepresent[type] with count of type.
916if (smbiostables) {
917for (i=0; i<origsmbiosnum; i++) {
918struct smbios_table_header*cur = (struct smbios_table_header *)tablesptr;
919char*stringsptr;
920intstringlen;
921
922tablesptr += cur->length;
923stringsptr = tablesptr;
924for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);
925tablesptr += 2;
926stringlen = tablesptr - stringsptr - 1;
927if (stringlen == 1) {
928stringlen = 0;
929}
930for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
931const char*str;
932intsize;
933charaltname[40];
934
935sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);
936 if (smbios_properties[j].table_type == cur->type &&
937 smbios_properties[j].value_type == SMSTRING &&
938 smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name))) {
939
940 stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
941
942 } else if (smbios_properties[j].table_type == cur->type &&
943 smbios_properties[j].value_type == SMSTRING &&
944 (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) ||
945 getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))
946{
947stringlen += size + 1;
948} else if (smbios_properties[j].table_type == cur->type &&
949 smbios_properties[j].value_type == SMSTRING &&
950 do_auto && smbios_properties[j].auto_str)
951{
952stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
953}
954}
955if (stringlen == 0) {
956stringlen = 1;
957}
958stringlen++;
959if (ret->maxStructureSize < cur->length+stringlen) {
960ret->maxStructureSize=cur->length+stringlen;
961}
962ret->dmi.tableLength += cur->length+stringlen;
963ret->dmi.structureCount++;
964tablespresent[cur->type]++;
965}
966}
967 // Add eventually table types whose detected count would be < required count, and update ret header with:
968 // new stringlen addons, structure count, and tablepresent[type] count adequately
969for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
970intnumnec=-1;
971charbuffer[40];
972
973sprintf(buffer, "SMtable%d", i);
974if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
975numnec = -1;
976}
977if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {
978numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
979}
980while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
981intstringlen = 0;
982for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
983const char*str;
984intsize;
985charaltname[40];
986
987sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);
988 if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
989 smbios_properties[j].value_type==SMSTRING &&
990 smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name))) {
991
992 stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
993
994 } else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
995 smbios_properties[j].value_type == SMSTRING &&
996 (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
997 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)))
998{
999stringlen += size + 1;
1000} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
1001 smbios_properties[j].value_type==SMSTRING &&
1002 do_auto && smbios_properties[j].auto_str)
1003{
1004stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
1005}
1006}
1007if (stringlen == 0) {
1008stringlen = 1;
1009}
1010stringlen++;
1011if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {
1012ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;
1013}
1014ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;
1015ret->dmi.structureCount++;
1016tablespresent[smbios_table_descriptions[i].type]++;
1017}
1018}
1019return ret;
1020}
1021
1022/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint
1023 * struct has been created by smbios_dry_run, update each table struct content of new smbios
1024 * int the new allocated table address of size newsmbios->tablelength.
1025 */
1026static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)
1027{
1028char *smbiostables;
1029char *tablesptr, *newtablesptr;
1030int origsmbiosnum;
1031// bitmask of used handles
1032uint8_t handles[8192];
1033uint16_t nexthandle=0;
1034int i, j;
1035int tablespresent[256];
1036bool do_auto=true;
1037
1038 static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info !
1039
1040 bool randomSerial = false;
1041 getBoolForKey(kSMBIOSRandomSerial, &randomSerial, &bootInfo->bootConfig);
1042
1043bzero(tablespresent, sizeof(tablespresent));
1044bzero(handles, sizeof(handles));
1045
1046getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);
1047
1048newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);
1049if (origsmbios) {
1050smbiostables = (char *)origsmbios->dmi.tableAddress;
1051origsmbiosnum = origsmbios->dmi.structureCount;
1052} else {
1053smbiostables = NULL;
1054origsmbiosnum = 0;
1055}
1056tablesptr = smbiostables;
1057newtablesptr = (char *)newsmbios->dmi.tableAddress;
1058
1059 // if old smbios exists then update new smbios with old smbios original content first
1060if (smbiostables) {
1061for (i=0; i<origsmbiosnum; i++) {
1062struct smbios_table_header*oldcur = (struct smbios_table_header *) tablesptr;
1063struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
1064char*stringsptr;
1065intnstrings = 0;
1066
1067handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);
1068
1069 // copy table length from old table to new table but not the old strings
1070memcpy(newcur,oldcur, oldcur->length);
1071
1072tablesptr += oldcur->length;
1073stringsptr = tablesptr;
1074newtablesptr += oldcur->length;
1075
1076 // calculate the number of strings in the old content
1077for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {
1078if (tablesptr[0] == 0) {
1079nstrings++;
1080}
1081}
1082if (tablesptr != stringsptr) {
1083nstrings++;
1084}
1085tablesptr += 2;
1086
1087 // copy the old strings to new table
1088memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);
1089
1090 // point to next possible space for a string (deducting the second 0 char at the end)
1091newtablesptr += tablesptr - stringsptr - 1;
1092 if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator
1093newtablesptr--;
1094}
1095
1096 // now for each property in the table update the overrides if any (auto or user)
1097for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
1098const char*str;
1099intsize;
1100intnum;
1101charaltname[40];
1102
1103sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
1104if (smbios_properties[j].table_type == newcur->type) {
1105switch (smbios_properties[j].value_type) {
1106case SMSTRING:
1107 if (smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name)))
1108 {
1109 str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1110size = strlen(str);
1111memcpy(newtablesptr, str, size);
1112newtablesptr[size] = 0;
1113newtablesptr += size + 1;
1114*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1115
1116 } else if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
1117 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
1118{
1119memcpy(newtablesptr, str, size);
1120newtablesptr[size] = 0;
1121newtablesptr += size + 1;
1122*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1123} else if (do_auto && smbios_properties[j].auto_str) {
1124str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1125size = strlen(str);
1126memcpy(newtablesptr, str, size);
1127newtablesptr[size] = 0;
1128newtablesptr += size + 1;
1129*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1130}
1131break;
1132
1133case SMOWORD:
1134if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
1135 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
1136{
1137intk=0, t=0, kk=0;
1138const char*ptr = str;
1139memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
1140while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
1141ptr++;
1142}
1143if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
1144ptr += 2;
1145}
1146for (;ptr-str<size && *ptr && k<16;ptr++) {
1147if (*ptr>='0' && *ptr<='9') {
1148(t=(t<<4)|(*ptr-'0')),kk++;
1149}
1150if (*ptr>='a' && *ptr<='f') {
1151(t=(t<<4)|(*ptr-'a'+10)),kk++;
1152}
1153if (*ptr>='A' && *ptr<='F') {
1154(t=(t<<4)|(*ptr-'A'+10)),kk++;
1155}
1156if (kk == 2) {
1157*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
1158k++;
1159kk = 0;
1160t = 0;
1161}
1162}
1163}
1164break;
1165
1166case SMBYTE:
1167if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
1168 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
1169{
1170*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1171} else if (do_auto && smbios_properties[j].auto_int) {
1172*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1173}
1174break;
1175
1176case SMWORD:
1177if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
1178 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
1179{
1180*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1181} else if (do_auto && smbios_properties[j].auto_int) {
1182*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1183}
1184break;
1185}
1186}
1187}
1188if (nstrings == 0) {
1189newtablesptr[0] = 0;
1190newtablesptr++;
1191}
1192newtablesptr[0] = 0;
1193newtablesptr++;
1194tablespresent[newcur->type]++;
1195}
1196}
1197
1198 // for each eventual complementary table not present in the original smbios, do the overrides
1199for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
1200intnumnec = -1;
1201charbuffer[40];
1202
1203sprintf(buffer, "SMtable%d", i);
1204if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {
1205numnec = -1;
1206}
1207if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {
1208numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);
1209}
1210while (tablespresent[smbios_table_descriptions[i].type] < numnec) {
1211struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
1212intnstrings = 0;
1213
1214memset(newcur,0, smbios_table_descriptions[i].len);
1215while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {
1216nexthandle++;
1217}
1218newcur->handle = nexthandle;
1219handles[nexthandle / 8] |= 1 << (nexthandle % 8);
1220newcur->type = smbios_table_descriptions[i].type;
1221newcur->length = smbios_table_descriptions[i].len;
1222newtablesptr += smbios_table_descriptions[i].len;
1223for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
1224const char*str;
1225intsize;
1226intnum;
1227charaltname[40];
1228
1229sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);
1230if (smbios_properties[j].table_type == newcur->type) {
1231switch (smbios_properties[j].value_type) {
1232case SMSTRING:
1233 if (smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name)))
1234 {
1235 str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1236size = strlen(str);
1237memcpy(newtablesptr, str, size);
1238newtablesptr[size] = 0;
1239newtablesptr += size + 1;
1240*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1241
1242 } else if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
1243 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
1244{
1245memcpy(newtablesptr, str, size);
1246newtablesptr[size] = 0;
1247newtablesptr += size + 1;
1248*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1249} else if (do_auto && smbios_properties[j].auto_str) {
1250str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
1251size = strlen(str);
1252memcpy(newtablesptr, str, size);
1253newtablesptr[size] = 0;
1254newtablesptr += size + 1;
1255*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;
1256}
1257break;
1258
1259case SMOWORD:
1260if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||
1261 getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))
1262{
1263intk=0, t=0, kk=0;
1264const char*ptr = str;
1265
1266memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);
1267while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {
1268ptr++;
1269}
1270if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {
1271ptr += 2;
1272}
1273for (;ptr-str<size && *ptr && k<16;ptr++) {
1274if (*ptr>='0' && *ptr<='9') {
1275(t=(t<<4)|(*ptr-'0')),kk++;
1276}
1277if (*ptr>='a' && *ptr<='f') {
1278(t=(t<<4)|(*ptr-'a'+10)),kk++;
1279}
1280if (*ptr>='A' && *ptr<='F') {
1281(t=(t<<4)|(*ptr-'A'+10)),kk++;
1282}
1283if (kk == 2) {
1284*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;
1285k++;
1286kk = 0;
1287t = 0;
1288}
1289}
1290}
1291break;
1292
1293case SMBYTE:
1294if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
1295 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
1296{
1297*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1298} else if (do_auto && smbios_properties[j].auto_int) {
1299*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1300}
1301break;
1302
1303case SMWORD:
1304if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||
1305 getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))
1306{
1307*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;
1308} else if (do_auto && smbios_properties[j].auto_int) {
1309*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);
1310}
1311break;
1312}
1313}
1314}
1315if (nstrings == 0) {
1316newtablesptr[0] = 0;
1317newtablesptr++;
1318}
1319newtablesptr[0] = 0;
1320newtablesptr++;
1321tablespresent[smbios_table_descriptions[i].type]++;
1322}
1323}
1324
1325 // calculate new checksums
1326newsmbios->dmi.checksum = 0;
1327newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));
1328newsmbios->checksum = 0;
1329newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));
1330
1331if (!done) {
1332verbose("Patched DMI Table\n");
1333done=true;
1334}
1335}
1336
1337#define MAX_DMI_TABLES 96
1338typedef struct DmiNumAssocTag {
1339 struct DMIHeader * dmi;
1340 uint8_t type;
1341} DmiNumAssoc;
1342
1343static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES];
1344static int DmiTablePairCount = 0;
1345static int current_pos=0;
1346static bool ftTablePairInit = true;
1347
1348/**
1349 * Get a table structure entry from a type specification and a smbios address
1350 * return NULL if table is not found
1351 */
1352void getSmbiosTableStructure(struct SMBEntryPoint *smbios)
1353{
1354 struct DMIHeader * dmihdr=NULL;
1355 SMBByte* p;
1356 int i;
1357
1358 if (ftTablePairInit && smbios!=NULL) {
1359 ftTablePairInit = false;
1360#if DEBUG_SMBIOS
1361 printf(">>> SMBIOSAddr=0x%08x\n", smbios);
1362 printf(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress,
1363 smbios->dmi.tableLength, smbios->dmi.structureCount);
1364#endif
1365 p = (SMBByte *) smbios->dmi.tableAddress;
1366 for (i=0;
1367 i < smbios->dmi.structureCount &&
1368 p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength;
1369 i++) {
1370 dmihdr = (struct DMIHeader *) p;
1371
1372#if DEBUG_SMBIOS
1373 // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length);
1374#endif
1375 if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break;
1376 if (DmiTablePairCount < MAX_DMI_TABLES) {
1377 DmiTablePair[DmiTablePairCount].dmi = dmihdr;
1378 DmiTablePair[DmiTablePairCount].type = dmihdr->type;
1379 DmiTablePairCount++;
1380 }
1381 else {
1382 printf("DMI table entries list is full! Next entries won't be stored.\n");
1383 }
1384#if DEBUG_SMBIOS
1385 printf("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length);
1386#endif
1387 p = p + dmihdr->length;
1388 while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) {
1389 p++;
1390}
1391 p += 2;
1392}
1393
1394 }
1395}
1396
1397/** Find first original dmi Table with a particular type */
1398struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength)
1399{
1400 current_pos = 0;
1401
1402 return FindNextDmiTableOfType(type, minlength);
1403};
1404
1405/** Find next original dmi Table with a particular type */
1406struct DMIHeader* FindNextDmiTableOfType(int type, int minlength)
1407{
1408 int i;
1409
1410 if (ftTablePairInit) getSmbiosOriginal();
1411
1412 for (i=current_pos; i < DmiTablePairCount; i++) {
1413 if (type == DmiTablePair[i].type &&
1414 DmiTablePair[i].dmi &&
1415 DmiTablePair[i].dmi->length >= minlength ) {
1416 current_pos = i+1;
1417 return DmiTablePair[i].dmi;
1418 }
1419 }
1420 return NULL; // not found
1421};
1422
1423
1424const char * smbiosStringAtIndex(DMIHeader* smHeader, int index, int* length )
1425{
1426 const char * last = 0;
1427 const char * next = (const char *) smHeader + smHeader->length;
1428
1429 if ( length ) *length = 0;
1430 while ( index-- )
1431 {
1432 last = 0;
1433const char * cp = 0;
1434for ( cp = next; *cp || cp[1]; cp++ )
1435 {
1436 if ( *cp == '\0' )
1437 {
1438 last = next;
1439 next = cp + 1;
1440 break;
1441 }
1442 }
1443 if ( last == 0 ) break;
1444 }
1445
1446 if ( last )
1447 {
1448 while (*last == ' ') last++;
1449 if (length)
1450 {
1451 UInt8 len;
1452 for ( len = next - last - 1; len && last[len - 1] == ' '; len-- )
1453 ;
1454 *length = len; // number of chars not counting the terminating NULL
1455 }
1456 }
1457
1458 return last ? last : "";
1459}
1460
1461
1462struct SMBEntryPoint *getSmbiosPatched(struct SMBEntryPoint *orig)
1463{
1464 struct SMBEntryPoint *patched = NULL; // cached
1465
1466patched = smbios_dry_run(orig);
1467 if(patched==NULL) {
1468 printf("Could not create new SMBIOS !!\n");
1469 pause();
1470 }
1471 else {
1472 smbios_real_run(orig, patched);
1473 }
1474
1475
1476 return patched;
1477
1478}
1479
1480/*
1481char* getSmbiosProductName()
1482{
1483struct SMBEntryPoint*smbios;
1484SMBSystemInformation*p;
1485char*tempString;
1486inttmpLen;
1487
1488smbios = getSmbiosOriginal();
1489if (smbios==NULL) return NULL;
1490
1491p = (SMBSystemInformation*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information
1492if (p==NULL) return NULL;
1493
1494
1495tempString = (char*)smbiosStringAtIndex((DMIHeader*)p, p->productName, &tmpLen);
1496tempString[tmpLen] = 0;
1497
1498gSMBIOSBoardModel = malloc(tmpLen + 1);
1499if(gSMBIOSBoardModel)
1500{
1501strncpy(gSMBIOSBoardModel, tempString, tmpLen);
1502Node* node = DT__FindNode("/", false);
1503DT__AddProperty(node, "orig-model", tmpLen, gSMBIOSBoardModel);
1504}
1505verbose("Actual model name is '%s'\n", tempString);
1506return tempString;
1507}
1508*/
1509
1510void scan_memory(PlatformInfo_t *p)
1511{
1512 int i=0;
1513 struct DMIHeader * dmihdr = NULL;
1514
1515 struct DMIMemoryModuleInfo* memInfo[MAX_RAM_SLOTS]; // 6
1516 struct DMIPhysicalMemoryArray* physMemArray; // 16
1517 struct DMIMemoryDevice* memDev[MAX_RAM_SLOTS]; //17
1518
1519 /* We mainly don't use obsolete tables 5,6 because most of computers don't handle it anymore */
1520Platform->DMI.MemoryModules = 0;
1521 /* Now lets peek info rom table 16,17 as for some bios, table 5 & 6 are not used */
1522 physMemArray = (struct DMIPhysicalMemoryArray*) FindFirstDmiTableOfType(16, 4);
1523 Platform->DMI.MaxMemorySlots = physMemArray ? physMemArray->numberOfMemoryDevices : 0;
1524
1525 i = 0;
1526 for(dmihdr = FindFirstDmiTableOfType(17, 4);
1527 dmihdr;
1528 dmihdr = FindNextDmiTableOfType(17, 4) ) {
1529 memDev[i] = (struct DMIMemoryDevice*) dmihdr;
1530 if (memDev[i]->size !=0 ) Platform->DMI.MemoryModules++;
1531 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
1532 i++;
1533 }
1534 // for table 6, we only have a look at the current speed
1535 i = 0;
1536 for(dmihdr = FindFirstDmiTableOfType(6, 4);
1537 dmihdr;
1538 dmihdr = FindNextDmiTableOfType(6, 4) ) {
1539 memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr;
1540 if (memInfo[i]->currentSpeed > Platform->RAM.DIMM[i].Frequency)
1541 Platform->RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any
1542 i++;
1543 }
1544#if 0
1545 dumpAllTablesOfType(17);
1546 getc();
1547#endif
1548}
1549

Archive Download this file

Revision: 1667