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 "convert.h"␊ |
10 | #include "efi_tables.h"␊ |
11 | #include "fake_efi.h"␊ |
12 | #include "platform.h"␊ |
13 | #include "smbios_patcher.h"␊ |
14 | #include "SMBIOS.h"␊ |
15 | #include "pci.h"␊ |
16 | ␊ |
17 | #ifndef DEBUG_SMBIOS␊ |
18 | #define DEBUG_SMBIOS 0␊ |
19 | #endif␊ |
20 | ␊ |
21 | #if DEBUG_SMBIOS␊ |
22 | #define DBG(x...)␉verbose(x)␊ |
23 | #else␊ |
24 | #define DBG(x...)␊ |
25 | #endif␊ |
26 | //Slice - for ACPI patcher templates␊ |
27 | int␉␉ModelLength = 0;␊ |
28 | char␉MacModel[8] = "MacBook";␊ |
29 | unsigned int ModelRev = 0x00010001;␊ |
30 | uint64_t smbios_p;␊ |
31 | ␊ |
32 | char* gSMBIOSBoardModel;␊ |
33 | ␊ |
34 | typedef struct {␊ |
35 | const char* key;␊ |
36 | const char* value;␊ |
37 | } SMStrEntryPair;␊ |
38 | //Slice - TODO must be unique UUID for each model?␊ |
39 | /* Random values␊ |
40 | 19422392-C343-4A3A-92A3-AB1F0A6C3E52␊ |
41 | E3314823-659D-42B6-B42C-147E4E3484D4␊ |
42 | C3D73A74-809A-4804-A747-DDB934A737D0␊ |
43 | */␊ |
44 | // defaults for a MacBook␊ |
45 | static const SMStrEntryPair const sm_macbook_defaults[]={␊ |
46 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
47 | ␉{"SMbiosversion",␉"MB41.88Z.0073.B00.0809221748"␉},␊ |
48 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
49 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
50 | ␉{"SMproductname",␉"MacBook4,1"␉␉␉},␊ |
51 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
52 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
53 | ␉{"SMfamily",␉␉"MacBook"␉␉␉},␊ |
54 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
55 | ␉{"SMboardproduct",␉"Mac-F42D89C8"␉␉␉},␊ |
56 | ␉{"SMUUID"␉, "19422392-C343-106B-80A3-001F0A6C3E52"},␊ |
57 | ␉{ "",""␉}␊ |
58 | };␊ |
59 | ␊ |
60 | // defaults for a MacBook Pro␊ |
61 | static const SMStrEntryPair const sm_macbookpro_defaults[]={␊ |
62 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
63 | ␉{"SMbiosversion",␉"MBP41.88Z.0073.B00.0809221748"␉},␊ |
64 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
65 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
66 | ␉{"SMproductname",␉"MacBookPro4,1"␉␉␉},␊ |
67 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
68 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
69 | ␉{"SMfamily",␉␉"MacBookPro"␉␉␉},␊ |
70 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
71 | ␉{"SMboardproduct",␉"Mac-F42D89C8"␉␉␉},␊ |
72 | ␉{"SMUUID"␉, "862F78AF-9B36-106B-807A-00BA8C14A528"},␊ |
73 | ␉{ "",""␉}␊ |
74 | };␊ |
75 | ␊ |
76 | // defaults for a Mac mini ␊ |
77 | static const SMStrEntryPair const sm_macmini_defaults[]={␊ |
78 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
79 | ␉{"SMbiosversion",␉"MM21.88Z.009A.B00.0706281359"␉},␊ |
80 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
81 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
82 | ␉{"SMproductname",␉"Macmini2,1"␉␉␉},␊ |
83 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
84 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
85 | ␉{"SMfamily",␉␉"Napa Mac"␉␉␉},␊ |
86 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
87 | ␉{"SMboardproduct",␉"Mac-F4208EAA"␉␉␉},␊ |
88 | ␉{"SMUUID"␉, "862F78AF-9B36-40AF-B67A-ABBA8C14A528"},␊ |
89 | ␉{ "",""␉}␊ |
90 | };␊ |
91 | ␊ |
92 | // defaults for an iMac␊ |
93 | static const SMStrEntryPair const sm_imac_defaults[]={␊ |
94 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
95 | ␉{"SMbiosversion",␉"IM91.88Z.00C1.B00.0802091538"␉},␊ |
96 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
97 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
98 | ␉{"SMproductname",␉"iMac9,1"␉␉␉␉␉␉},␉␊ |
99 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
100 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
101 | ␉{"SMfamily",␉␉"Mac"␉␉␉␉},␊ |
102 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
103 | ␉{"SMboardproduct",␉"Mac-F227BEC8"␉␉␉},␊ |
104 | ␉{"SMUUID"␉, "862F78AF-9B36-40AF-B67A-ABBA8C14A528"},␊ |
105 | ␉{ "",""␉}␊ |
106 | };␊ |
107 | ␊ |
108 | // defaults for a Mac Pro␊ |
109 | static const SMStrEntryPair const sm_macpro_defaults[]={␊ |
110 | ␉{"SMbiosvendor",␉␉"Apple Computer, Inc."␉␉␉},␊ |
111 | ␉{"SMbiosversion",␉␉"MP31.88Z.006C.B05.0802291410"␉},␊ |
112 | ␉{"SMbiosdate",␉␉␉"04/01/2008"␉␉␉␉␉},␊ |
113 | ␉{"SMmanufacter",␉␉"Apple Computer, Inc."␉␉␉},␊ |
114 | ␉{"SMproductname",␉␉"MacPro3,1"␉␉␉␉␉␉},␊ |
115 | ␉{"SMsystemversion",␉␉"1.0"␉␉␉␉␉␉␉},␊ |
116 | ␉{"SMserial",␉␉␉"SOMESRLNMBR"␉␉␉␉␉},␊ |
117 | ␉{"SMfamily",␉␉␉"MacPro"␉␉␉␉␉␉},␊ |
118 | ␉{"SMboardmanufacter",␉"Apple Computer, Inc."␉␉␉},␊ |
119 | ␉{"SMboardproduct",␉␉"Mac-F4208DC8"␉␉␉␉␉},␊ |
120 | ␉{"SMUUID"␉, "862F78AF-9B36-40AF-B67A-ABBA8C14A528"},␊ |
121 | ␉{ "",""␉}␊ |
122 | };␊ |
123 | ␊ |
124 | // defaults for an iMac11,1 core i3/i5/i7␊ |
125 | static const SMStrEntryPair const sm_imac_core_defaults[]={␊ |
126 | ␉{"SMbiosvendor",␉␉"Apple Inc."␉␉␉␉␉},␊ |
127 | ␉{"SMbiosversion",␉␉"IM111.88Z.0034.B00.0802091538"␉},␊ |
128 | ␉{"SMbiosdate",␉␉␉"06/01/2009"␉␉␉␉␉},␊ |
129 | ␉{"SMmanufacter",␉␉"Apple Inc."␉␉␉␉␉},␊ |
130 | ␉{"SMproductname",␉␉"iMac11,1"␉␉␉␉␉␉},␉␊ |
131 | ␉{"SMsystemversion",␉␉"1.0"␉␉␉␉␉␉␉},␊ |
132 | ␉{"SMserial",␉␉␉"SOMESRLNMBR"␉␉␉␉␉},␊ |
133 | ␉{"SMfamily",␉␉␉"iMac"␉␉␉␉␉␉␉},␊ |
134 | ␉{"SMboardmanufacter",␉"Apple Computer, Inc."␉␉␉},␊ |
135 | ␉{"SMboardproduct",␉␉"Mac-F2268DAE"␉␉␉␉␉},␊ |
136 | ␉{"SMUUID"␉, "862F78AF-9B36-40AF-B67A-ABBA8C14A528"},␊ |
137 | ␉{ "",""␉}␊ |
138 | };␊ |
139 | #if NEVER_USE_MACPRO41␊ |
140 | // defaults for a Mac Pro 4,1 Xeon␊ |
141 | static const SMStrEntryPair const sm_macpro_core_defaults[]={␊ |
142 | ␉{"SMbiosvendor",␉␉"Apple Computer, Inc."␉␉␉},␊ |
143 | ␉{"SMbiosversion",␉␉"MP41.88Z.0081.B04.0903051113"␉},␊ |
144 | ␉{"SMbiosdate",␉␉␉"11/06/2009"␉␉␉␉␉},␊ |
145 | ␉{"SMmanufacter",␉␉"Apple Computer, Inc."␉␉␉},␊ |
146 | ␉{"SMproductname",␉␉"MacPro4,1"␉␉␉␉␉␉},␊ |
147 | ␉{"SMsystemversion",␉␉"1.0"␉␉␉␉␉␉␉},␊ |
148 | ␉{"SMserial",␉␉␉"SOMESRLNMBR"␉␉␉␉␉},␊ |
149 | ␉{"SMfamily",␉␉␉"MacPro"␉␉␉␉␉␉},␊ |
150 | ␉{"SMboardmanufacter",␉"Apple Computer, Inc."␉␉␉},␊ |
151 | ␉{"SMboardproduct",␉␉"Mac-F4208DC8"␉␉␉␉␉},␊ |
152 | ␉{"SMUUID"␉, "862F78AF-9B36-40AF-B67A-ABBA8C14A528"},␊ |
153 | ␉{ "",""␉}␊ |
154 | };␊ |
155 | #endif␊ |
156 | static const char* sm_get_defstr(const char * key, int table_num)␊ |
157 | {␊ |
158 | ␉int␉i;␊ |
159 | ␉const SMStrEntryPair*␉sm_defaults;␊ |
160 | ␊ |
161 | //␉if (platformCPUFeature(CPU_FEATURE_MOBILE)) {␊ |
162 | ␉if (Platform->CPU.Mobile) {␊ |
163 | ␉␉if (Platform->CPU.NoCores > 1) {␊ |
164 | ␉␉␉//TODO if NVidia - MBP else MB␊ |
165 | ␉␉␉sm_defaults=sm_macbookpro_defaults;␊ |
166 | ␉␉} else {␊ |
167 | ␉␉␉sm_defaults=sm_macbook_defaults;␊ |
168 | ␉␉}␊ |
169 | ␉} else {␊ |
170 | ␉␉switch (Platform->CPU.NoCores) ␊ |
171 | ␉␉{␊ |
172 | ␉␉␉case 1: ␊ |
173 | ␉␉␉␉sm_defaults=sm_macmini_defaults; ␊ |
174 | ␉␉␉␉break;␊ |
175 | ␉␉␉case 2:␊ |
176 | ␉␉␉␉sm_defaults=sm_imac_defaults;␊ |
177 | ␉␉␉␉break;␊ |
178 | ␉␉␉default:␊ |
179 | ␉␉␉{␊ |
180 | ␉␉␉␉switch (Platform->CPU.Family) ␊ |
181 | ␉␉␉␉{␊ |
182 | ␉␉␉␉␉case 0x06:␊ |
183 | ␉␉␉␉␉{␊ |
184 | ␉␉␉␉␉␉switch (Platform->CPU.Model)␊ |
185 | ␉␉␉␉␉␉{␊ |
186 | ␉␉␉␉␉␉␉case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)␊ |
187 | ␉␉␉␉␉␉␉case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???␊ |
188 | ␉␉␉␉␉␉␉case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)␊ |
189 | ␉␉␉␉␉␉␉case 0x19: // Intel Core i5 650 @3.20 Ghz ␊ |
190 | ␉␉␉␉␉␉//␉␉sm_defaults=sm_imac_defaults; ␊ |
191 | ␉␉␉␉␉␉//␉␉break;␊ |
192 | ␉␉␉␉␉␉␉case CPU_MODEL_NEHALEM: ␊ |
193 | ␉␉␉␉␉␉␉case CPU_MODEL_NEHALEM_EX:␊ |
194 | ␉␉␉␉␉␉␉case CPU_MODEL_WESTMERE: ␊ |
195 | ␉␉␉␉␉␉␉case CPU_MODEL_WESTMERE_EX:␊ |
196 | ␉␉␉␉␉␉␉␉sm_defaults=sm_imac_core_defaults; ␊ |
197 | ␉␉␉␉␉␉␉␉break;␊ |
198 | ␉␉␉␉␉␉␉default:␊ |
199 | ␉␉␉␉␉␉␉␉sm_defaults=sm_imac_core_defaults; ␊ |
200 | ␉␉␉␉␉␉␉␉break;␊ |
201 | ␉␉␉␉␉␉}␊ |
202 | ␉␉␉␉␉␉break;␊ |
203 | ␉␉␉␉␉}␊ |
204 | ␉␉␉␉␉default:␊ |
205 | ␉␉␉␉␉␉sm_defaults=sm_macpro_defaults; ␊ |
206 | ␉␉␉␉␉␉break;␊ |
207 | ␉␉␉␉}␊ |
208 | ␉␉␉␉break;␊ |
209 | ␉␉␉}␊ |
210 | ␉␉}␊ |
211 | ␉}␊ |
212 | ␉␊ |
213 | ␉for (i=0; sm_defaults[i].key[0]; i++) {␊ |
214 | ␉␉if (!strcmp (sm_defaults[i].key, key)) {␊ |
215 | ␉␉␉return sm_defaults[i].value;␊ |
216 | ␉␉}␊ |
217 | ␉}␊ |
218 | ␊ |
219 | ␉// Shouldn't happen␊ |
220 | ␉printf ("Error: no default for '%s' known\n", key);␊ |
221 | ␉sleep (2);␊ |
222 | ␉return "";␊ |
223 | }␊ |
224 | ␊ |
225 | static int sm_get_fsb(const char *name, int table_num)␊ |
226 | {␊ |
227 | ␉return Platform->CPU.FSBFrequency/1000000;␊ |
228 | }␊ |
229 | ␊ |
230 | static int sm_get_cpu (const char *name, int table_num)␊ |
231 | {␊ |
232 | ␉return Platform->CPU.CPUFrequency/1000000;␊ |
233 | }␊ |
234 | ␊ |
235 | static int sm_get_bus_speed (const char *name, int table_num)␊ |
236 | {␊ |
237 | ␉if (Platform->CPU.Vendor == 0x756E6547) // Intel␊ |
238 | ␉{␉␉␊ |
239 | ␉␉switch (Platform->CPU.Family) ␊ |
240 | ␉␉{␊ |
241 | ␉␉␉case 0x06:␊ |
242 | ␉␉␉{␊ |
243 | ␉␉␉␉switch (Platform->CPU.Model)␊ |
244 | ␉␉␉␉{␊ |
245 | ␉␉␉␉␉case CPU_MODEL_PENTIUM_M: // Pentium M 0x0D␊ |
246 | ␉␉␉␉␉case CPU_MODEL_YONAH:␉// Yonah␉␉0x0E␊ |
247 | ␉␉␉␉␉case CPU_MODEL_MEROM:␉// Merom␉␉0x0F␊ |
248 | ␉␉␉␉␉case CPU_MODEL_PENRYN:␉// Penryn␉␉0x17␊ |
249 | ␉␉␉␉␉case CPU_MODEL_ATOM:␉// Atom 45nm␉0x1C␊ |
250 | ␉␉␉␉␉␉return 0; // TODO: populate bus speed for these processors␊ |
251 | ␉␉␉␉␉␉␊ |
252 | //␉␉␉␉␉case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)␊ |
253 | //␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
254 | //␉␉␉␉␉␉␉return 2500; // Core i5␊ |
255 | //␉␉␉␉␉␉return 4800; // Core i7␊ |
256 | ␉␉␉␉␉␉␊ |
257 | //␉␉␉␉␉case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)␊ |
258 | //␉␉␉␉␉case CPU_MODEL_NEHALEM_EX:␊ |
259 | //␉␉␉␉␉case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???␊ |
260 | //␉␉␉␉␉␉return 4800; // GT/s / 1000␊ |
261 | //␉␉␉␉␉␉␊ |
262 | ␉␉␉␉␉case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???␊ |
263 | ␉␉␉␉␉␉return 0; // TODO: populate bus speed for these processors␊ |
264 | ␉␉␉␉␉␉␊ |
265 | //␉␉␉␉␉case 0x19: // Intel Core i5 650 @3.20 Ghz␊ |
266 | //␉␉␉␉␉␉return 2500; // why? Intel spec says 2.5GT/s ␊ |
267 | ␊ |
268 | ␉␉␉␉␉case 0x19: // Intel Core i5 650 @3.20 Ghz␊ |
269 | ␉␉␉␉␉case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)␊ |
270 | ␉␉␉␉␉case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)␊ |
271 | ␉␉␉␉␉case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ???␊ |
272 | ␉␉␉␉␉case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm)␊ |
273 | ␉␉␉␉␉case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core␊ |
274 | ␉␉␉␉␉case CPU_MODEL_NEHALEM_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???␊ |
275 | ␉␉␉␉␉{ // thanks to dgobe for i3/i5/i7 bus speed detection␊ |
276 | ␉␉␉␉␉␉int nhm_bus = 0x3F;␊ |
277 | ␉␉␉␉␉␉static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};␊ |
278 | ␉␉␉␉␉␉unsigned long did, vid;␊ |
279 | ␉␉␉␉␉␉int i;␊ |
280 | ␉␉␉␉␉␉␊ |
281 | ␉␉␉␉␉␉// Nehalem supports Scrubbing␊ |
282 | ␉␉␉␉␉␉// First, locate the PCI bus where the MCH is located␊ |
283 | ␉␉␉␉␉␉for(i = 0; i < sizeof(possible_nhm_bus); i++)␊ |
284 | ␉␉␉␉␉␉{␊ |
285 | ␉␉␉␉␉␉␉vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00);␊ |
286 | ␉␉␉␉␉␉␉did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02);␊ |
287 | ␉␉␉␉␉␉␉vid &= 0xFFFF;␊ |
288 | ␉␉␉␉␉␉␉did &= 0xFF00;␊ |
289 | ␉␉␉␉␉␉␉␊ |
290 | ␉␉␉␉␉␉␉if(vid == 0x8086 && did >= 0x2C00)␊ |
291 | ␉␉␉␉␉␉␉␉nhm_bus = possible_nhm_bus[i]; ␊ |
292 | ␉␉␉␉␉␉}␊ |
293 | ␉␉␉␉␉␉␊ |
294 | ␉␉␉␉␉␉unsigned long qpimult, qpibusspeed;␊ |
295 | ␉␉␉␉␉␉qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50);␊ |
296 | ␉␉␉␉␉␉qpimult &= 0x7F;␊ |
297 | ␉␉␉␉␉␉DBG("qpimult %d\n", qpimult);␊ |
298 | ␉␉␉␉␉␉qpibusspeed = (qpimult * 2 * (Platform->CPU.FSBFrequency/1000000));␊ |
299 | ␉␉␉␉␉␉// Rek: rounding decimals to match original mac profile info␊ |
300 | ␉␉␉␉␉␉if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100;␊ |
301 | ␉␉␉␉␉␉DBG("qpibusspeed %d\n", qpibusspeed);␊ |
302 | ␉␉␉␉␉␉return qpibusspeed;␊ |
303 | ␉␉␉␉␉}␊ |
304 | ␉␉␉␉}␊ |
305 | ␉␉␉}␊ |
306 | ␉␉}␊ |
307 | ␉}␊ |
308 | ␉return 0;␊ |
309 | }␊ |
310 | ␊ |
311 | static int sm_get_simplecputype()␊ |
312 | {␊ |
313 | ␉if (Platform->CPU.NoCores >= 4) ␊ |
314 | ␉{␊ |
315 | ␉␉return 0x0501; // Quad-Core Xeon␊ |
316 | ␉}␊ |
317 | ␉else if (Platform->CPU.NoCores == 1) ␊ |
318 | ␉{␊ |
319 | ␉␉return 0x0201; // Core Solo␊ |
320 | ␉};␊ |
321 | ␉␊ |
322 | ␉return 0x0301; // Core 2 Duo␊ |
323 | }␊ |
324 | ␊ |
325 | static int sm_get_cputype (const char *name, int table_num)␊ |
326 | {␊ |
327 | ␉static bool done = false;␉␉␊ |
328 | ␉␉␊ |
329 | ␉if (Platform->CPU.Vendor == 0x756E6547) // Intel␊ |
330 | ␉{␊ |
331 | ␉␉if (!done) {␊ |
332 | ␉␉␉verbose("CPU is %s, family 0x%x, model 0x%x\n", Platform->CPU.BrandString, Platform->CPU.Family, Platform->CPU.Model);␊ |
333 | ␉␉␉done = true;␊ |
334 | ␉␉}␊ |
335 | ␉␉␊ |
336 | ␉␉switch (Platform->CPU.Family) ␊ |
337 | ␉␉{␊ |
338 | ␉␉␉case 0x06:␊ |
339 | ␉␉␉{␊ |
340 | ␉␉␉␉switch (Platform->CPU.Model)␊ |
341 | ␉␉␉␉{␊ |
342 | ␉␉␉␉␉case CPU_MODEL_PENTIUM_M: // Pentium M = 0x0D␊ |
343 | ␉␉␉␉␉␉return 0x0101;␊ |
344 | ␉␉␉␉␉case CPU_MODEL_YONAH: // Yonah␊ |
345 | ␉␉␉␉␉case CPU_MODEL_MEROM: // Merom␊ |
346 | ␉␉␉␉␉case CPU_MODEL_PENRYN: // Penryn␊ |
347 | ␉␉␉␉␉case CPU_MODEL_ATOM: // Intel Atom (45nm)␊ |
348 | ␉␉␉␉␉␉return sm_get_simplecputype();␊ |
349 | ␉␉␉␉␉␉␊ |
350 | ␉␉␉␉␉case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)␊ |
351 | ␉␉␉␉␉␉return 0x0701; // Core i7␊ |
352 | ␉␉␉␉␉␉␊ |
353 | ␉␉␉␉␉case CPU_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper␊ |
354 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
355 | ␉␉␉␉␉␉␉return 0x601; // Core i5␊ |
356 | ␉␉␉␉␉␉return 0x701; // Core i7␊ |
357 | ␉␉␉␉␉␉␊ |
358 | ␉␉␉␉␉case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale)␊ |
359 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
360 | ␉␉␉␉␉␉␉return 0x601; // Core i5␊ |
361 | ␉␉␉␉␉␉return 0x0701; // Core i7␊ |
362 | ␉␉␉␉␉␉␊ |
363 | ␉␉␉␉␉case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)␊ |
364 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i3"))␊ |
365 | ␉␉␉␉␉␉␉return 0x901; // Core i3␊ |
366 | ␉␉␉␉␉␉if (strstr(Platform->CPU.BrandString, "Core(TM) i5"))␊ |
367 | ␉␉␉␉␉␉␉return 0x601; // Core i5␊ |
368 | ␉␉␉␉␉␉return 0x0701; // Core i7␊ |
369 | ␉␉␉␉␉␉␊ |
370 | ␉␉␉␉␉case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS)␊ |
371 | ␉␉␉␉␉case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???␊ |
372 | ␉␉␉␉␉␉return 0x0701; // Core i7␊ |
373 | ␉␉␉␉␉␉␊ |
374 | ␉␉␉␉␉case 0x19: // Intel Core i5 650 @3.20 Ghz␊ |
375 | ␉␉␉␉␉␉return 0x601; // Core i5␊ |
376 | ␉␉␉␉}␊ |
377 | ␉␉␉}␊ |
378 | ␉␉}␊ |
379 | ␉}␊ |
380 | ␉␊ |
381 | ␉return sm_get_simplecputype();␊ |
382 | }␊ |
383 | ␊ |
384 | static int sm_get_memtype (const char *name, int table_num)␊ |
385 | {␊ |
386 | ␉int␉map;␊ |
387 | ␊ |
388 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
389 | ␉␉map = Platform->DMI.DIMM[table_num];␊ |
390 | ␉␉if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Type != 0) {␊ |
391 | DBG("RAM Detected Type = %d\n", Platform->RAM.DIMM[map].Type);␊ |
392 | return Platform->RAM.DIMM[map].Type;␊ |
393 | ␉␉}␊ |
394 | ␉}␊ |
395 | ␉␊ |
396 | ␉return SMB_MEM_TYPE_DDR2;␊ |
397 | }␊ |
398 | ␊ |
399 | static int sm_get_memspeed (const char *name, int table_num)␊ |
400 | {␊ |
401 | ␉int␉map;␊ |
402 | ␊ |
403 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
404 | ␉␉map = Platform->DMI.DIMM[table_num];␊ |
405 | ␉␉if (Platform->RAM.DIMM[map].InUse && Platform->RAM.DIMM[map].Frequency != 0) {␊ |
406 | DBG("RAM Detected Freq = %d Mhz\n", Platform->RAM.DIMM[map].Frequency);␊ |
407 | return Platform->RAM.DIMM[map].Frequency;␊ |
408 | ␉␉}␊ |
409 | ␉}␊ |
410 | ␊ |
411 | ␉return 800;␊ |
412 | }␊ |
413 | ␊ |
414 | static const char *sm_get_memvendor (const char *name, int table_num)␊ |
415 | {␊ |
416 | ␉int␉map;␊ |
417 | ␊ |
418 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
419 | ␉␉map = Platform->DMI.DIMM[table_num];␊ |
420 | ␉␉if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].Vendor) > 0) {␊ |
421 | ␉␉␉DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].Vendor);␊ |
422 | ␉␉␉return Platform->RAM.DIMM[map].Vendor;␊ |
423 | ␉␉}␊ |
424 | ␉}␊ |
425 | ␉return "N/A";␊ |
426 | }␊ |
427 | ␉␊ |
428 | static const char *sm_get_memserial (const char *name, int table_num)␊ |
429 | {␊ |
430 | ␉int␉map;␊ |
431 | ␊ |
432 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
433 | ␉␉map = Platform->DMI.DIMM[table_num];␊ |
434 | ␉␉if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].SerialNo) > 0) {␊ |
435 | DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "", ␊ |
436 | map, table_num, Platform->RAM.DIMM[map].SerialNo);␊ |
437 | return Platform->RAM.DIMM[map].SerialNo;␊ |
438 | ␉␉}␊ |
439 | ␉}␊ |
440 | ␉return "N/A";␊ |
441 | }␊ |
442 | ␊ |
443 | static const char *sm_get_mempartno (const char *name, int table_num)␊ |
444 | {␊ |
445 | ␉int␉map;␊ |
446 | ␊ |
447 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
448 | ␉␉map = Platform->DMI.DIMM[table_num];␊ |
449 | ␉␉if (Platform->RAM.DIMM[map].InUse && strlen(Platform->RAM.DIMM[map].PartNo) > 0) {␊ |
450 | ␉␉␉DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform->RAM.DIMM[map].PartNo);␊ |
451 | ␉␉␉return Platform->RAM.DIMM[map].PartNo;␊ |
452 | ␉␉}␊ |
453 | ␉}␊ |
454 | ␉return "N/A";␊ |
455 | }␊ |
456 | ␊ |
457 | static int sm_one (int tablen)␊ |
458 | {␊ |
459 | ␉return 1;␊ |
460 | }␊ |
461 | ␊ |
462 | struct smbios_property smbios_properties[]=␊ |
463 | {␊ |
464 | ␉{.name="SMbiosvendor",␉␉.table_type= 0,␉.value_type=SMSTRING,␉.offset=0x04,␉.auto_str=sm_get_defstr␉},␊ |
465 | ␉{.name="SMbiosversion",␉␉.table_type= 0,␉.value_type=SMSTRING,␉.offset=0x05,␉.auto_str=sm_get_defstr␉},␊ |
466 | ␉{.name="SMbiosdate",␉␉.table_type= 0,␉.value_type=SMSTRING,␉.offset=0x08,␉.auto_str=sm_get_defstr␉},␊ |
467 | ␉{.name="SMmanufacter",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x04,␉.auto_str=sm_get_defstr␉},␊ |
468 | ␉{.name="SMproductname",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x05,␉.auto_str=sm_get_defstr␉},␊ |
469 | ␉{.name="SMsystemversion",␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x06,␉.auto_str=sm_get_defstr␉},␊ |
470 | ␉{.name="SMserial",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x07,␉.auto_str=sm_get_defstr␉},␊ |
471 | ␉{.name="SMUUID",␉␉␉.table_type= 1, .value_type=SMOWORD,␉.offset=0x08,␉.auto_oword=sm_get_defstr},␊ |
472 | ␉{.name="SMfamily",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x1a,␉.auto_str=sm_get_defstr␉},␊ |
473 | ␉{.name="SMboardmanufacter",␉.table_type= 2, .value_type=SMSTRING,␉.offset=0x04,␉.auto_str=sm_get_defstr␉},␊ |
474 | ␉{.name="SMboardproduct",␉.table_type= 2, .value_type=SMSTRING,␉.offset=0x05,␉.auto_str=sm_get_defstr␉},␊ |
475 | ␉{.name="SMexternalclock",␉.table_type= 4,␉.value_type=SMWORD,␉.offset=0x12,␉.auto_int=sm_get_fsb␉},␊ |
476 | ␉{.name="SMmaximalclock",␉.table_type= 4,␉.value_type=SMWORD,␉.offset=0x14,␉.auto_int=sm_get_cpu␉},␊ |
477 | ␉{.name="SMmemdevloc",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x10,␉.auto_str=0␉␉},␊ |
478 | ␉{.name="SMmembankloc",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x11,␉.auto_str=0␉␉},␊ |
479 | ␉{.name="SMmemtype",␉␉.table_type=17,␉.value_type=SMBYTE,␉.offset=0x12,␉.auto_int=sm_get_memtype},␊ |
480 | ␉{.name="SMmemspeed",␉␉.table_type=17,␉.value_type=SMWORD,␉.offset=0x15,␉.auto_int=sm_get_memspeed},␊ |
481 | ␉{.name="SMmemmanufacter",␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x17,␉.auto_str=sm_get_memvendor},␊ |
482 | ␉{.name="SMmemserial",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x18,␉.auto_str=sm_get_memserial},␊ |
483 | ␉{.name="SMmempart",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x1A,␉.auto_str=sm_get_mempartno},␊ |
484 | ␉{.name="SMcputype",␉␉.table_type=131,.value_type=SMWORD,␉.offset=0x04,␉.auto_int=sm_get_cputype},␊ |
485 | ␉{.name="SMbusspeed",␉␉.table_type=132,.value_type=SMWORD,␉.offset=0x04,␉.auto_int=sm_get_bus_speed}␊ |
486 | };␊ |
487 | ␊ |
488 | struct smbios_table_description smbios_table_descriptions[]=␊ |
489 | {␊ |
490 | ␉{.type=kSMBTypeBIOSInformation,␉␉␉.len=0x18,␉.numfunc=sm_one},␊ |
491 | ␉{.type=kSMBTypeSystemInformation,␉␉.len=0x1b,␉.numfunc=sm_one},␊ |
492 | ␉{.type=kSMBTypeBaseBoard,␉␉␉␉.len=0x0f,␉.numfunc=sm_one}, //except kSMBBaseBoardProcessorMemoryModule␊ |
493 | ␉{.type=kSMBTypeProcessorInformation,␉.len=0x2a,␉.numfunc=sm_one},␊ |
494 | //kSMBTypeMemoryModule len=12 obsolete but Used by AppleSMBIOS␉␊ |
495 | //kSMBTypeSystemSlot␉ len=13 Used by AppleSMBIOS␊ |
496 | //kSMBTypePhysicalMemoryArray len=15 Used by AppleSMBIOS␉␊ |
497 | ␉{.type=kSMBTypeMemoryDevice,␉␉␉.len=0x24,␉.numfunc=0},␊ |
498 | //Slice - we are not ready to fill the data␉␊ |
499 | //␉{.type=kSMBTypeFirmwareVolume,␉␉␉.len=0x56,␉.numfunc=0},␊ |
500 | //␉{.type=kSMBTypeMemorySPD,␉␉␉␉.len=0x0c,␉.numfunc=0},␊ |
501 | ␉{.type=kSMBTypeOemProcessorType,␉␉.len=0x06,␉.numfunc=sm_one},␊ |
502 | ␉{.type=kSMBTypeOemProcessorBusSpeed,␉.len=0x06,␉.numfunc=sm_one}␊ |
503 | };␊ |
504 | /* Apple known types␊ |
505 | enum {␊ |
506 | kSMBTypeBIOSInformation = 0,␊ |
507 | kSMBTypeSystemInformation = 1,␊ |
508 | kSMBTypeBaseBoard␉␉␉␉␉ = 2,␊ |
509 | kSMBTypeSystemEnclosure = 3,␊ |
510 | kSMBTypeProcessorInformation = 4,␊ |
511 | kSMBTypeMemoryModule = 6,␊ |
512 | kSMBTypeCacheInformation = 7,␊ |
513 | kSMBTypeSystemSlot = 9,␊ |
514 | kSMBTypePhysicalMemoryArray = 16,␊ |
515 | kSMBTypeMemoryDevice = 17,␊ |
516 | kSMBType32BitMemoryErrorInfo = 18,␊ |
517 | kSMBType64BitMemoryErrorInfo = 33,␊ |
518 | ␊ |
519 | // Apple Specific Structures ␊ |
520 | kSMBTypeFirmwareVolume = 128,␊ |
521 | kSMBTypeMemorySPD = 130,␊ |
522 | kSMBTypeOemProcessorType = 131,␊ |
523 | kSMBTypeOemProcessorBusSpeed = 132␊ |
524 | };␊ |
525 | ␊ |
526 | */␊ |
527 | ␊ |
528 | // getting smbios addr with fast compare ops, late checksum testing ...␊ |
529 | #define COMPARE_DWORD(a,b) ( *((u_int32_t *) a) == *((u_int32_t *) b) )␊ |
530 | static const char * const SMTAG = "_SM_";␊ |
531 | static const char* const DMITAG= "_DMI_";␊ |
532 | ␊ |
533 | static struct SMBEntryPoint *getAddressOfSmbiosTable(void)␊ |
534 | {␊ |
535 | ␉struct SMBEntryPoint␉*smbios;␊ |
536 | ␉/* ␊ |
537 | ␉ * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking␊ |
538 | ␉ * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_").␊ |
539 | ␉ */␊ |
540 | ␉smbios = (struct SMBEntryPoint*) SMBIOS_RANGE_START;␊ |
541 | ␉while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END) {␊ |
542 | if (COMPARE_DWORD(smbios->anchor, SMTAG) && ␊ |
543 | COMPARE_DWORD(smbios->dmi.anchor, DMITAG) &&␊ |
544 | smbios->dmi.anchor[4]==DMITAG[4] &&␊ |
545 | checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0)␊ |
546 | ␉ {␉␉␉␊ |
547 | return smbios;␊ |
548 | ␉ }␊ |
549 | smbios = (struct SMBEntryPoint*) ( ((char*) smbios) + 16 );␊ |
550 | ␉}␊ |
551 | ␉printf("ERROR: Unable to find SMBIOS!\n");␊ |
552 | ␉pause();␊ |
553 | ␉return NULL;␊ |
554 | }␊ |
555 | ␊ |
556 | /** Compute necessary space requirements for new smbios */␊ |
557 | static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)␊ |
558 | {␊ |
559 | ␉struct SMBEntryPoint␉*ret;␊ |
560 | ␉char␉␉␉*smbiostables;␊ |
561 | ␉char␉␉␉*tablesptr;␊ |
562 | ␉int␉␉␉origsmbiosnum;␊ |
563 | ␉int␉␉␉i, j;␊ |
564 | ␉int␉␉␉tablespresent[256];␊ |
565 | ␉bool␉␉␉do_auto=true;␊ |
566 | ␊ |
567 | ␉bzero(tablespresent, sizeof(tablespresent));␊ |
568 | ␊ |
569 | ␉getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);␊ |
570 | ␊ |
571 | ␉ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));␊ |
572 | ␉if (origsmbios) {␊ |
573 | ␉␉smbiostables = (char *)origsmbios->dmi.tableAddress;␊ |
574 | ␉␉origsmbiosnum = origsmbios->dmi.structureCount;␊ |
575 | ␉} else {␊ |
576 | ␉␉smbiostables = NULL;␊ |
577 | ␉␉origsmbiosnum = 0;␊ |
578 | ␉}␊ |
579 | ␊ |
580 | ␉// _SM_␊ |
581 | ␉ret->anchor[0] = 0x5f;␊ |
582 | ␉ret->anchor[1] = 0x53;␊ |
583 | ␉ret->anchor[2] = 0x4d;␊ |
584 | ␉ret->anchor[3] = 0x5f; ␊ |
585 | ␉ret->entryPointLength = sizeof(*ret);␊ |
586 | ␉ret->majorVersion = 2;␊ |
587 | ␉ret->minorVersion = 1;␊ |
588 | ␉ret->maxStructureSize = 0; // will be calculated later in this function␊ |
589 | ␉ret->entryPointRevision = 0;␊ |
590 | ␉for (i=0;i<5;i++) {␊ |
591 | ␉␉ret->formattedArea[i] = 0;␊ |
592 | ␉}␊ |
593 | ␉//_DMI_␊ |
594 | ␉ret->dmi.anchor[0] = 0x5f;␊ |
595 | ␉ret->dmi.anchor[1] = 0x44;␊ |
596 | ␉ret->dmi.anchor[2] = 0x4d;␊ |
597 | ␉ret->dmi.anchor[3] = 0x49;␊ |
598 | ␉ret->dmi.anchor[4] = 0x5f;␊ |
599 | ␉ret->dmi.tableLength = 0; // will be calculated later in this function␊ |
600 | ␉ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()␊ |
601 | ␉ret->dmi.structureCount = 0; // will be calculated later in this function␊ |
602 | ␉ret->dmi.bcdRevision = 0x21;␊ |
603 | ␉tablesptr = smbiostables;␊ |
604 | ␊ |
605 | // add stringlen of overrides to original stringlen, update maxStructure size adequately, ␊ |
606 | // update structure count and tablepresent[type] with count of type. ␊ |
607 | ␉if (smbiostables) {␊ |
608 | ␉␉for (i=0; i<origsmbiosnum; i++) {␊ |
609 | ␉␉␉struct smbios_table_header␉*cur = (struct smbios_table_header *)tablesptr;␊ |
610 | ␉␉␉char␉␉␉␉*stringsptr;␊ |
611 | ␉␉␉int␉␉␉␉stringlen;␊ |
612 | ␊ |
613 | ␉␉␉tablesptr += cur->length;␊ |
614 | ␉␉␉stringsptr = tablesptr;␊ |
615 | ␉␉␉for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);␊ |
616 | ␉␉␉tablesptr += 2;␊ |
617 | ␉␉␉stringlen = tablesptr - stringsptr - 1;␊ |
618 | ␉␉␉if (stringlen == 1) {␊ |
619 | ␉␉␉␉stringlen = 0;␊ |
620 | ␉␉␉}␊ |
621 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
622 | ␉␉␉␉const char␉*str;␊ |
623 | ␉␉␉␉int␉␉size;␊ |
624 | ␉␉␉␉char␉␉altname[40];␊ |
625 | ␊ |
626 | ␉␉␉␉sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);␉␉␉␉␊ |
627 | ␉␉␉␉if (smbios_properties[j].table_type == cur->type &&␊ |
628 | ␉␉␉␉ smbios_properties[j].value_type == SMSTRING &&␊ |
629 | ␉␉␉␉ (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) ||␊ |
630 | ␉␉␉␉ getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))␊ |
631 | ␉␉␉␉{␊ |
632 | ␉␉␉␉␉stringlen += size + 1;␊ |
633 | ␉␉␉␉} else if (smbios_properties[j].table_type == cur->type &&␊ |
634 | ␉␉␉␉ smbios_properties[j].value_type == SMSTRING &&␊ |
635 | ␉␉␉␉ do_auto && smbios_properties[j].auto_str)␊ |
636 | ␉␉␉␉{␊ |
637 | ␉␉␉␉␉stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;␊ |
638 | ␉␉␉␉}␊ |
639 | ␉␉␉}␊ |
640 | ␉␉␉if (stringlen == 0) {␊ |
641 | ␉␉␉␉stringlen = 1;␊ |
642 | ␉␉␉}␊ |
643 | ␉␉␉stringlen++;␊ |
644 | ␉␉␉if (ret->maxStructureSize < cur->length+stringlen) {␊ |
645 | ␉␉␉␉ret->maxStructureSize=cur->length+stringlen;␊ |
646 | ␉␉␉}␊ |
647 | ␉␉␉ret->dmi.tableLength += cur->length+stringlen;␊ |
648 | ␉␉␉ret->dmi.structureCount++;␊ |
649 | ␉␉␉tablespresent[cur->type]++;␊ |
650 | ␉␉}␊ |
651 | ␉}␊ |
652 | // Add eventually table types whose detected count would be < required count, and update ret header with:␊ |
653 | // new stringlen addons, structure count, and tablepresent[type] count adequately␊ |
654 | ␉for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {␊ |
655 | ␉␉int␉numnec=-1;␊ |
656 | ␉␉char␉buffer[40];␊ |
657 | ␊ |
658 | ␉␉sprintf(buffer, "SMtable%d", i);␊ |
659 | ␉␉if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {␊ |
660 | ␉␉␉numnec = -1;␊ |
661 | ␉␉}␊ |
662 | ␉␉if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {␊ |
663 | ␉␉␉numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);␊ |
664 | ␉␉}␊ |
665 | ␉␉while (tablespresent[smbios_table_descriptions[i].type] < numnec) {␊ |
666 | ␉␉␉int␉stringlen = 0;␊ |
667 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
668 | ␉␉␉␉const char␉*str;␊ |
669 | ␉␉␉␉int␉␉size;␊ |
670 | ␉␉␉␉char␉␉altname[40];␊ |
671 | ␊ |
672 | ␉␉␉␉sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);␊ |
673 | ␉␉␉␉if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&␊ |
674 | ␉␉␉␉ smbios_properties[j].value_type == SMSTRING &&␊ |
675 | ␉␉␉␉ (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
676 | ␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)))␊ |
677 | ␉␉␉␉{␊ |
678 | ␉␉␉␉␉stringlen += size + 1;␊ |
679 | ␉␉␉␉} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&␊ |
680 | ␉␉␉␉ smbios_properties[j].value_type==SMSTRING &&␊ |
681 | ␉␉␉␉ do_auto && smbios_properties[j].auto_str)␊ |
682 | ␉␉␉␉{␊ |
683 | ␉␉␉␉␉stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;␊ |
684 | ␉␉␉␉}␊ |
685 | ␉␉␉}␊ |
686 | ␉␉␉if (stringlen == 0) {␊ |
687 | ␉␉␉␉stringlen = 1;␊ |
688 | ␉␉␉}␊ |
689 | ␉␉␉stringlen++;␊ |
690 | ␉␉␉if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {␊ |
691 | ␉␉␉␉ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;␊ |
692 | ␉␉␉}␊ |
693 | ␉␉␉ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;␊ |
694 | ␉␉␉ret->dmi.structureCount++;␊ |
695 | ␉␉␉tablespresent[smbios_table_descriptions[i].type]++;␊ |
696 | ␉␉}␊ |
697 | ␉}␊ |
698 | ␉return ret;␊ |
699 | }␊ |
700 | ␊ |
701 | /** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint ␊ |
702 | * struct has been created by smbios_dry_run, update each table struct content of new smbios␊ |
703 | * int the new allocated table address of size newsmbios->tablelength.␊ |
704 | */␊ |
705 | static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)␊ |
706 | {␊ |
707 | ␉char *smbiostables;␊ |
708 | ␉char *tablesptr, *newtablesptr;␊ |
709 | ␉int origsmbiosnum=0;␊ |
710 | ␉// bitmask of used handles␊ |
711 | ␉uint8_t handles[8192]; ␊ |
712 | ␉uint16_t nexthandle=0;␊ |
713 | ␉int i, j;␊ |
714 | ␉int tablespresent[256];␊ |
715 | ␉bool do_auto=true;␊ |
716 | ␉␊ |
717 | static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info !␊ |
718 | ␊ |
719 | ␉extern void dumpPhysAddr(const char * title, void * a, int len);␊ |
720 | ␉␊ |
721 | ␉bzero(tablespresent, sizeof(tablespresent));␊ |
722 | ␉bzero(handles, sizeof(handles));␊ |
723 | ␊ |
724 | ␉getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);␊ |
725 | ␉␊ |
726 | ␉newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);␊ |
727 | ␉if (origsmbios) {␊ |
728 | ␉␉smbiostables = (char *)origsmbios->dmi.tableAddress;␊ |
729 | ␉␉origsmbiosnum = origsmbios->dmi.structureCount;␊ |
730 | ␉} else {␊ |
731 | ␉␉smbiostables = NULL;␊ |
732 | ␉␉origsmbiosnum = 0;␊ |
733 | ␉}␊ |
734 | ␉tablesptr = smbiostables;␊ |
735 | ␉newtablesptr = (char *)newsmbios->dmi.tableAddress;␊ |
736 | ␊ |
737 | // if old smbios exists then update new smbios with old smbios original content first␊ |
738 | ␉if (smbiostables) {␊ |
739 | ␉␉for (i=0; i<origsmbiosnum; i++) {␊ |
740 | ␉␉␉struct smbios_table_header␉*oldcur = (struct smbios_table_header *) tablesptr;␊ |
741 | ␉␉␉struct smbios_table_header␉*newcur = (struct smbios_table_header *) newtablesptr;␊ |
742 | ␉␉␉char␉␉␉␉*stringsptr;␊ |
743 | ␉␉␉int␉␉␉␉nstrings = 0;␊ |
744 | ␊ |
745 | ␉␉␉handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);␊ |
746 | ␊ |
747 | // copy table length from old table to new table but not the old strings␊ |
748 | ␉␉␉memcpy(newcur,oldcur, oldcur->length);␊ |
749 | ␊ |
750 | ␉␉␉tablesptr += oldcur->length;␊ |
751 | ␉␉␉stringsptr = tablesptr;␊ |
752 | ␉␉␉newtablesptr += oldcur->length;␊ |
753 | ␊ |
754 | // calculate the number of strings in the old content␊ |
755 | ␉␉␉for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {␊ |
756 | ␉␉␉␉if (tablesptr[0] == 0) {␊ |
757 | ␉␉␉␉␉nstrings++;␊ |
758 | ␉␉␉␉}␊ |
759 | ␉␉␉}␊ |
760 | ␉␉␉if (tablesptr != stringsptr) {␊ |
761 | ␉␉␉␉nstrings++;␊ |
762 | ␉␉␉}␊ |
763 | ␉␉␉tablesptr += 2;␊ |
764 | ␊ |
765 | // copy the old strings to new table␊ |
766 | ␉␉␉memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);␊ |
767 | ␊ |
768 | ␉␉␉// point to next possible space for a string (deducting the second 0 char at the end)␊ |
769 | ␉␉␉newtablesptr += tablesptr - stringsptr - 1;␊ |
770 | if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator␊ |
771 | ␉␉␉␉newtablesptr--;␊ |
772 | ␉␉␉}␊ |
773 | ␊ |
774 | // now for each property in the table update the overrides if any (auto or user)␊ |
775 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
776 | ␉␉␉␉const char␉*str;␊ |
777 | ␉␉␉␉int␉␉size;␊ |
778 | ␉␉␉␉int␉␉num;␊ |
779 | ␉␉␉␉char␉␉altname[40];␊ |
780 | ␊ |
781 | ␉␉␉␉sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);␊ |
782 | ␉␉␉␉if (smbios_properties[j].table_type == newcur->type) {␊ |
783 | ␉␉␉␉␉switch (smbios_properties[j].value_type) {␊ |
784 | ␉␉␉␉␉case SMSTRING:␊ |
785 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
786 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
787 | ␉␉␉␉␉␉{␊ |
788 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
789 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
790 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
791 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
792 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_str) {␊ |
793 | ␉␉␉␉␉␉␉str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
794 | ␉␉␉␉␉␉␉size = strlen(str);␊ |
795 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
796 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
797 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
798 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
799 | ␉␉␉␉␉␉}␊ |
800 | ␉␉␉␉␉␉break;␊ |
801 | ␊ |
802 | ␉␉␉␉␉case SMOWORD:␊ |
803 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
804 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
805 | ␉␉␉␉␉␉{␊ |
806 | ␉␉␉␉␉␉␉//int␉␉k=0, t=0, kk=0;␊ |
807 | ␉␉␉␉␉␉␉//const char␉*ptr = str;␊ |
808 | ␉␉␉␉␉␉␉verbose("Set SMUUID to %s\n", str);␊ |
809 | ␉␉␉␉␉␉␉//memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);␊ |
810 | ␉␉␉␉␉␉␉EFI_GUID* p = getUUIDFromString(str);␊ |
811 | ␉␉␉␉␉␉␉memcpy(((char*)newcur) + smbios_properties[j].offset, p, 16);␊ |
812 | ␉␉␉␉␉␉␉/*␊ |
813 | ␉␉␉␉␉␉␉while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {␊ |
814 | ␉␉␉␉␉␉␉␉ptr++;␊ |
815 | ␉␉␉␉␉␉␉}␊ |
816 | ␉␉␉␉␉␉␉if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {␊ |
817 | ␉␉␉␉␉␉␉␉ptr += 2;␊ |
818 | ␉␉␉␉␉␉␉}␊ |
819 | ␉␉␉␉␉␉␉for (;ptr-str<size && *ptr && k<16;ptr++) {␊ |
820 | ␉␉␉␉␉␉␉␉if (*ptr=='-') {␊ |
821 | ␉␉␉␉␉␉␉␉␉continue; //Slice - ignore "-" inside UUID string␊ |
822 | ␉␉␉␉␉␉␉␉}␊ |
823 | ␉␉␉␉␉␉␉␉if (*ptr>='0' && *ptr<='9') {␊ |
824 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'0')),kk++;␊ |
825 | ␉␉␉␉␉␉␉␉}␊ |
826 | ␉␉␉␉␉␉␉␉if (*ptr>='a' && *ptr<='f') {␊ |
827 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'a'+10)),kk++;␊ |
828 | ␉␉␉␉␉␉␉␉}␊ |
829 | ␉␉␉␉␉␉␉␉if (*ptr>='A' && *ptr<='F') {␊ |
830 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'A'+10)),kk++;␊ |
831 | ␉␉␉␉␉␉␉␉}␊ |
832 | ␉␉␉␉␉␉␉␉if (kk == 2) {␊ |
833 | ␉␉␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;␊ |
834 | ␉␉␉␉␉␉␉␉␉k++;␊ |
835 | ␉␉␉␉␉␉␉␉␉kk = 0;␊ |
836 | ␉␉␉␉␉␉␉␉␉t = 0;␊ |
837 | ␉␉␉␉␉␉␉␉}␊ |
838 | ␉␉␉␉␉␉␉}␊ |
839 | ␉␉␉␉␉␉␉ */␊ |
840 | ␉␉␉␉␉␉}␊ |
841 | ␉␉␉␉␉␉break;␊ |
842 | ␊ |
843 | ␉␉␉␉␉case SMBYTE:␊ |
844 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
845 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
846 | ␉␉␉␉␉␉{␊ |
847 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
848 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
849 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␉␉␉␉␉␉␉␊ |
850 | ␉␉␉␉␉␉}␊ |
851 | ␉␉␉␉␉␉break;␊ |
852 | ␊ |
853 | ␉␉␉␉␉case SMWORD:␊ |
854 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
855 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
856 | ␉␉␉␉␉␉{␊ |
857 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
858 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
859 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
860 | ␉␉␉␉␉␉}␊ |
861 | ␉␉␉␉␉␉break;␊ |
862 | ␉␉␉␉␉}␊ |
863 | ␉␉␉␉}␊ |
864 | ␉␉␉}␊ |
865 | ␉␉␉if (nstrings == 0) {␊ |
866 | ␉␉␉␉newtablesptr[0] = 0;␊ |
867 | ␉␉␉␉newtablesptr++;␊ |
868 | ␉␉␉}␊ |
869 | ␉␉␉newtablesptr[0] = 0;␊ |
870 | ␉␉␉newtablesptr++;␊ |
871 | ␉␉␉tablespresent[newcur->type]++;␊ |
872 | ␉␉}␊ |
873 | ␉}␊ |
874 | ␊ |
875 | // for each eventual complementary table not present in the original smbios, do the overrides␊ |
876 | ␉for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {␊ |
877 | ␉␉int␉numnec = -1;␊ |
878 | ␉␉char␉buffer[40];␊ |
879 | ␊ |
880 | ␉␉sprintf(buffer, "SMtable%d", i);␊ |
881 | ␉␉if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {␊ |
882 | ␉␉␉numnec = -1;␊ |
883 | ␉␉}␊ |
884 | ␉␉if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {␊ |
885 | ␉␉␉numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);␊ |
886 | ␉␉}␊ |
887 | ␉␉while (tablespresent[smbios_table_descriptions[i].type] < numnec) {␊ |
888 | ␉␉␉struct smbios_table_header␉*newcur = (struct smbios_table_header *) newtablesptr;␊ |
889 | ␉␉␉int␉␉␉␉nstrings = 0;␊ |
890 | ␊ |
891 | ␉␉␉memset(newcur,0, smbios_table_descriptions[i].len);␊ |
892 | ␉␉␉while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {␊ |
893 | ␉␉␉␉nexthandle++;␊ |
894 | ␉␉␉}␊ |
895 | ␉␉␉newcur->handle = nexthandle;␊ |
896 | ␉␉␉handles[nexthandle / 8] |= 1 << (nexthandle % 8);␊ |
897 | ␉␉␉newcur->type = smbios_table_descriptions[i].type;␊ |
898 | ␉␉␉newcur->length = smbios_table_descriptions[i].len;␊ |
899 | ␉␉␉newtablesptr += smbios_table_descriptions[i].len;␊ |
900 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
901 | ␉␉␉␉const char␉*str;␊ |
902 | ␉␉␉␉int␉␉size;␊ |
903 | ␉␉␉␉int␉␉num;␊ |
904 | ␉␉␉␉char␉␉altname[40];␊ |
905 | ␊ |
906 | ␉␉␉␉sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);␊ |
907 | ␉␉␉␉if (smbios_properties[j].table_type == newcur->type) {␊ |
908 | ␉␉␉␉␉switch (smbios_properties[j].value_type) {␊ |
909 | ␉␉␉␉␉case SMSTRING:␊ |
910 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
911 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
912 | ␉␉␉␉␉␉{␊ |
913 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
914 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
915 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
916 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
917 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_str) {␊ |
918 | ␉␉␉␉␉␉␉str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
919 | ␉␉␉␉␉␉␉size = strlen(str);␊ |
920 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
921 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
922 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
923 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
924 | ␉␉␉␉␉␉}␊ |
925 | ␉␉␉␉␉␉break;␊ |
926 | ␊ |
927 | ␉␉␉␉␉case SMOWORD:␊ |
928 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
929 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
930 | ␉␉␉␉␉␉{␊ |
931 | ␉␉␉␉␉␉␉EFI_GUID* p = getUUIDFromString(str);␊ |
932 | ␉␉␉␉␉␉␉memcpy(((char*)newcur) + smbios_properties[j].offset, p, 16);␊ |
933 | /*␊ |
934 | ␉␉␉␉␉␉␉int␉␉k=0, t=0, kk=0;␊ |
935 | ␉␉␉␉␉␉␉const char␉*ptr = str;␊ |
936 | ␉␉␉␉␉␉␉verbose("Set SMUUID to %s\n", str);␊ |
937 | ␊ |
938 | ␉␉␉␉␉␉␉memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);␊ |
939 | ␉␉␉␉␉␉␉while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {␊ |
940 | ␉␉␉␉␉␉␉␉ptr++;␊ |
941 | ␉␉␉␉␉␉␉}␊ |
942 | ␉␉␉␉␉␉␉if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {␊ |
943 | ␉␉␉␉␉␉␉␉ptr += 2;␊ |
944 | ␉␉␉␉␉␉␉}␊ |
945 | ␉␉␉␉␉␉␉for (;ptr-str<size && *ptr && k<16;ptr++) {␊ |
946 | ␉␉␉␉␉␉␉␉if (*ptr=='-') {␊ |
947 | ␉␉␉␉␉␉␉␉␉continue; //Slice - ignore "-" inside UUID string␊ |
948 | ␉␉␉␉␉␉␉␉}␊ |
949 | ␉␉␉␉␉␉␉␉if (*ptr>='0' && *ptr<='9') {␊ |
950 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'0')),kk++;␊ |
951 | ␉␉␉␉␉␉␉␉}␊ |
952 | ␉␉␉␉␉␉␉␉if (*ptr>='a' && *ptr<='f') {␊ |
953 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'a'+10)),kk++;␊ |
954 | ␉␉␉␉␉␉␉␉}␊ |
955 | ␉␉␉␉␉␉␉␉if (*ptr>='A' && *ptr<='F') {␊ |
956 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'A'+10)),kk++;␊ |
957 | ␉␉␉␉␉␉␉␉}␊ |
958 | ␉␉␉␉␉␉␉␉if (kk == 2) {␊ |
959 | ␉␉␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;␊ |
960 | ␉␉␉␉␉␉␉␉␉k++;␊ |
961 | ␉␉␉␉␉␉␉␉␉kk = 0;␊ |
962 | ␉␉␉␉␉␉␉␉␉t = 0;␊ |
963 | ␉␉␉␉␉␉␉␉}␊ |
964 | ␉␉␉␉␉␉␉}␊ |
965 | */␊ |
966 | ␉␉␉␉␉␉}␊ |
967 | ␉␉␉␉␉␉break;␊ |
968 | ␉␉␉␉␉␉␊ |
969 | ␉␉␉␉␉case SMBYTE:␊ |
970 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
971 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
972 | ␉␉␉␉␉␉{␊ |
973 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
974 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
975 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
976 | ␉␉␉␉␉␉}␊ |
977 | ␉␉␉␉␉␉break;␊ |
978 | ␉␉␉␉␉␉␊ |
979 | ␉␉␉␉␉case SMWORD:␊ |
980 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
981 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
982 | ␉␉␉␉␉␉{␊ |
983 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
984 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
985 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
986 | ␉␉␉␉␉␉}␊ |
987 | ␉␉␉␉␉␉break;␊ |
988 | ␉␉␉␉␉}␊ |
989 | ␉␉␉␉}␊ |
990 | ␉␉␉}␊ |
991 | ␉␉␉if (nstrings == 0) {␊ |
992 | ␉␉␉␉newtablesptr[0] = 0;␊ |
993 | ␉␉␉␉newtablesptr++;␊ |
994 | ␉␉␉}␊ |
995 | ␉␉␉newtablesptr[0] = 0;␊ |
996 | ␉␉␉newtablesptr++;␊ |
997 | ␉␉␉tablespresent[smbios_table_descriptions[i].type]++;␊ |
998 | ␉␉}␊ |
999 | ␉}␊ |
1000 | ␊ |
1001 | // calculate new checksums␊ |
1002 | ␉newsmbios->dmi.checksum = 0;␊ |
1003 | ␉newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));␊ |
1004 | ␉newsmbios->checksum = 0;␊ |
1005 | ␉newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));␊ |
1006 | ␉␊ |
1007 | ␉if (!done) {␊ |
1008 | ␉␉verbose("Patched DMI Table\n");␊ |
1009 | ␉␉done=true;␊ |
1010 | ␉}␊ |
1011 | }␊ |
1012 | ␊ |
1013 | #define MAX_DMI_TABLES 96␊ |
1014 | typedef struct DmiNumAssocTag {␊ |
1015 | struct DMIHeader * dmi;␊ |
1016 | uint8_t type;␊ |
1017 | } DmiNumAssoc;␊ |
1018 | ␊ |
1019 | static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES];␊ |
1020 | static int DmiTablePairCount = 0;␊ |
1021 | static int current_pos=0;␊ |
1022 | static bool ftTablePairInit = true; //use twice first run and after␊ |
1023 | ␊ |
1024 | /** ␊ |
1025 | * Get a table structure entry from a type specification and a smbios address␊ |
1026 | * return NULL if table is not found␊ |
1027 | */␊ |
1028 | static void getSmbiosTableStructure(struct SMBEntryPoint *smbios)␊ |
1029 | {␊ |
1030 | struct DMIHeader * dmihdr=NULL;␊ |
1031 | SMBByte* p;␊ |
1032 | int i;␊ |
1033 | ␊ |
1034 | if (ftTablePairInit && smbios!=NULL) {␊ |
1035 | ftTablePairInit = false;␊ |
1036 | #if DEBUG_SMBIOS␊ |
1037 | verbose(">>> SMBIOSAddr=0x%08x\n", smbios);␊ |
1038 | verbose(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress, ␊ |
1039 | smbios->dmi.tableLength, smbios->dmi.structureCount);␊ |
1040 | #endif␊ |
1041 | p = (SMBByte *) smbios->dmi.tableAddress;␊ |
1042 | for (i=0; ␊ |
1043 | i < smbios->dmi.structureCount && ␊ |
1044 | p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength; ␊ |
1045 | i++) {␊ |
1046 | dmihdr = (struct DMIHeader *) p;␊ |
1047 | ␊ |
1048 | #if DEBUG_SMBIOS␊ |
1049 | // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length);␊ |
1050 | #endif␊ |
1051 | if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break;␊ |
1052 | if (DmiTablePairCount < MAX_DMI_TABLES) {␊ |
1053 | DmiTablePair[DmiTablePairCount].dmi = dmihdr;␊ |
1054 | DmiTablePair[DmiTablePairCount].type = dmihdr->type;␊ |
1055 | DmiTablePairCount++;␊ |
1056 | }␊ |
1057 | else {␊ |
1058 | verbose("DMI table entries list is full! Next entries won't be stored.\n");␊ |
1059 | }␊ |
1060 | #if DEBUG_SMBIOS␊ |
1061 | verbose("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length);␊ |
1062 | #endif␊ |
1063 | p = p + dmihdr->length;␊ |
1064 | while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) {␊ |
1065 | p++;␊ |
1066 | ␉ }␊ |
1067 | p += 2;␊ |
1068 | ␉}␊ |
1069 | ␊ |
1070 | }␊ |
1071 | }␊ |
1072 | ␊ |
1073 | void getSmbiosMacModel(void)␊ |
1074 | {␊ |
1075 | #define MAX_MODEL_LEN␉32␊ |
1076 | ␉␊ |
1077 | ␉//Slice - I want to use MacModel for ACPITables so I need char* representation␊ |
1078 | ␉const char␉*value = getStringForKey("SMproductname", &bootInfo->smbiosConfig);␊ |
1079 | ␉int i, n=0, first=0, rev1=0, rev2=0;␉␉␊ |
1080 | ␉for (i=0; i<8; i++) ␊ |
1081 | ␉{␊ |
1082 | ␉␉char c = value[i];␊ |
1083 | ␉␉if (isalpha(c))␊ |
1084 | ␉␉{␊ |
1085 | ␉␉␉MacModel[i]=c;␊ |
1086 | ␉␉␉n++;␊ |
1087 | ␉␉} else ␊ |
1088 | ␉␉␉if ((c) >= '0' && (c) <= '9')␊ |
1089 | ␉␉␉{␊ |
1090 | ␉␉␉␉if (first)␊ |
1091 | ␉␉␉␉{␊ |
1092 | ␉␉␉␉␉rev1 = rev1 * 10 + (int)(c) & 0xf;␊ |
1093 | ␉␉␉␉} else␊ |
1094 | ␉␉␉␉␉rev2 = rev2 * 10 + (int)(c) & 0xf;␊ |
1095 | ␉␉␉} else ␊ |
1096 | ␉␉␉␉first = 1;␊ |
1097 | ␉␉␉//␉␉␉␉printf("char=%c first=%d rev1=%d rev2=%d\n", c, first, rev1, rev2);␊ |
1098 | ␉}␊ |
1099 | ␉for (i=n; i<8; i++) {␊ |
1100 | ␉␉MacModel[i] = 0x20;␊ |
1101 | ␉}␊ |
1102 | ␉ModelRev = (rev2 << 16) + rev1;␊ |
1103 | //␉␉ModelLength = (len + 1) * 2;␊ |
1104 | //␉␉printf("Model=%s %08x\n", MacModel, ModelRev);␊ |
1105 | //␉␉getc();␊ |
1106 | ␉␉␊ |
1107 | }␊ |
1108 | ␊ |
1109 | static struct SMBEntryPoint *orig = NULL; // cached␊ |
1110 | static struct SMBEntryPoint *patched = NULL; // cached␊ |
1111 | ␊ |
1112 | /** Get original or new smbios entry point, if successful, the addresses are cached for next time */␊ |
1113 | struct SMBEntryPoint *getSmbios(int which)␊ |
1114 | {␊ |
1115 | ␊ |
1116 | // whatever we are called with orig or new flag, initialize asap both structures␊ |
1117 | switch (which) {␊ |
1118 | case SMBIOS_ORIGINAL:␊ |
1119 | if (orig==NULL) {␊ |
1120 | orig = getAddressOfSmbiosTable();␊ |
1121 | getSmbiosTableStructure(orig); // generate tables entry list for fast table finding␊ |
1122 | }␊ |
1123 | return orig;␊ |
1124 | case SMBIOS_PATCHED:␊ |
1125 | if (orig==NULL && (orig = getAddressOfSmbiosTable())==NULL ) {␊ |
1126 | verbose("Could not find original SMBIOS !!\n");␊ |
1127 | pause();␊ |
1128 | } else {␊ |
1129 | patched = smbios_dry_run(orig);␊ |
1130 | if(patched==NULL) {␊ |
1131 | verbose("Could not create new SMBIOS !!\n");␊ |
1132 | pause();␊ |
1133 | }␊ |
1134 | else {␊ |
1135 | smbios_real_run(orig, patched);␊ |
1136 | }␊ |
1137 | }␊ |
1138 | ␉␉␉getSmbiosMacModel();␉//Dunno if it is a right place to do that␊ |
1139 | return patched;␊ |
1140 | default:␊ |
1141 | verbose("ERROR: invalid option for getSmbios() !!\n");␊ |
1142 | break;␊ |
1143 | }␊ |
1144 | ␊ |
1145 | return NULL;␊ |
1146 | }␊ |
1147 | ␊ |
1148 | /** Find first original dmi Table with a particular type */␊ |
1149 | struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength)␊ |
1150 | {␊ |
1151 | current_pos = 0; //static variable␊ |
1152 | ␊ |
1153 | return FindNextDmiTableOfType(type, minlength);␊ |
1154 | };␊ |
1155 | ␊ |
1156 | /** Find next original dmi Table with a particular type */␊ |
1157 | struct DMIHeader* FindNextDmiTableOfType(int type, int minlength)␊ |
1158 | {␊ |
1159 | int i;␊ |
1160 | ␊ |
1161 | if (ftTablePairInit) getSmbios(SMBIOS_ORIGINAL);␊ |
1162 | ␊ |
1163 | for (i=current_pos; i < DmiTablePairCount; i++) {␊ |
1164 | if (type == DmiTablePair[i].type && ␊ |
1165 | DmiTablePair[i].dmi &&␊ |
1166 | DmiTablePair[i].dmi->length >= minlength ) {␊ |
1167 | current_pos = i+1;␊ |
1168 | return DmiTablePair[i].dmi;␊ |
1169 | }␊ |
1170 | }␊ |
1171 | return NULL; // not found␊ |
1172 | };␊ |
1173 | ␊ |
1174 | #if 1 //NOTUSED //Slice -- it is used?␊ |
1175 | const char * smbiosStringAtIndex(DMIHeader* smHeader, int index, int* length )␊ |
1176 | {␊ |
1177 | const char * last = 0;␊ |
1178 | const char * next = (const char *) smHeader + smHeader->length;␊ |
1179 | ␉␊ |
1180 | if ( length ) *length = 0;␊ |
1181 | while ( index-- )␊ |
1182 | {␊ |
1183 | last = 0;␊ |
1184 | ␉␉const char * cp = 0;␊ |
1185 | ␉␉for ( cp = next; *cp || cp[1]; cp++ )␊ |
1186 | {␊ |
1187 | if ( *cp == '\0' )␊ |
1188 | {␊ |
1189 | last = next;␊ |
1190 | next = cp + 1;␊ |
1191 | break;␊ |
1192 | }␊ |
1193 | }␊ |
1194 | if ( last == 0 ) break;␊ |
1195 | }␊ |
1196 | ␉␊ |
1197 | if ( last )␊ |
1198 | {␊ |
1199 | while (*last == ' ') last++;␊ |
1200 | if (length)␊ |
1201 | {␊ |
1202 | UInt8 len;␊ |
1203 | for ( len = next - last - 1; len && last[len - 1] == ' '; len-- )␊ |
1204 | ;␊ |
1205 | *length = len; // number of chars not counting the terminating NULL␊ |
1206 | }␊ |
1207 | }␊ |
1208 | ␉␊ |
1209 | return last ? last : "";␊ |
1210 | }␊ |
1211 | ␊ |
1212 | ␊ |
1213 | void getSmbiosProductName()␊ |
1214 | {␊ |
1215 | //␉struct SMBEntryPoint␉*smbios;␊ |
1216 | ␉DMISystemInformation␉*p;␊ |
1217 | ␉char*␉␉␉␉␉tempString;␊ |
1218 | ␉int␉␉␉␉␉␉tmpLen;␊ |
1219 | ␉␊ |
1220 | //␉smbios = getSmbios(SMBIOS_ORIGINAL);␊ |
1221 | //␉if (smbios==NULL) return 0; ␊ |
1222 | ␉␊ |
1223 | ␉p = (DMISystemInformation*) FindFirstDmiTableOfType(1, 0x19); // Type 1: (3.3.2) System Information␊ |
1224 | ␉if (p==NULL) return; // NULL;␊ |
1225 | ␉␊ |
1226 | ␉␊ |
1227 | ␉tempString = (char*)smbiosStringAtIndex((DMIHeader*)p, p->productName, &tmpLen);␊ |
1228 | ␉tempString[tmpLen] = 0;␊ |
1229 | ␉␊ |
1230 | ␉gSMBIOSBoardModel = malloc(tmpLen + 1);␊ |
1231 | ␉if(gSMBIOSBoardModel)␊ |
1232 | ␉{␊ |
1233 | ␉␉strncpy(gSMBIOSBoardModel, tempString, tmpLen);␊ |
1234 | ␉␉Node* node = DT__FindNode("/", false);␊ |
1235 | ␉␉DT__AddProperty(node, "orig-model", tmpLen, gSMBIOSBoardModel);␊ |
1236 | ␉}␊ |
1237 | ␉verbose("Actual model name is '%s'\n", tempString);␊ |
1238 | }␊ |
1239 | #endif␊ |
1240 | ␊ |
1241 | //Slice␊ |
1242 | //#define MEGA 1000000LL - now in mem.h␊ |
1243 | void scan_cpu_DMI(void) //PlatformInfo_t *p)␊ |
1244 | {␊ |
1245 | ␉// int i=0;␊ |
1246 | ␉int maxClock = 0;␊ |
1247 | struct DMIHeader * dmihdr = NULL; ␊ |
1248 | struct DMIProcessorInformation* cpuInfo; // Type 4␊ |
1249 | ␉␊ |
1250 | ␉for (dmihdr = FindFirstDmiTableOfType(4, 30); dmihdr; dmihdr = FindNextDmiTableOfType(4, 30)) ␊ |
1251 | ␉{␊ |
1252 | ␉␉cpuInfo = (struct DMIProcessorInformation*)dmihdr;␊ |
1253 | ␉␉if (cpuInfo->processorType != 3) { // CPU␊ |
1254 | ␉␉␉continue;␊ |
1255 | ␉␉}␊ |
1256 | ␉␉//TODO validate␊ |
1257 | #if 1 //NOTYET␉␊ |
1258 | ␉␉msglog("Platform CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", Platform->CPU.FSBFrequency/MEGA, Platform->CPU.TSCFrequency/MEGA, Platform->CPU.CPUFrequency/MEGA);␊ |
1259 | ␉␉␊ |
1260 | ␉␉if ((cpuInfo->externalClock) && (cpuInfo->externalClock < 400)) { //<400MHz␊ |
1261 | ␉␉␉Platform->CPU.FSBFrequency = (cpuInfo->externalClock) * MEGA;␊ |
1262 | ␉␉}␊ |
1263 | ␉␉maxClock = cpuInfo->maximumClock;␊ |
1264 | ␉␉if (cpuInfo->maximumClock < cpuInfo->currentClock) {␊ |
1265 | ␉␉␉maxClock = cpuInfo->currentClock;␊ |
1266 | ␉␉}␊ |
1267 | ␉␉if ((maxClock) && (maxClock < 10000)) { //<10GHz␊ |
1268 | ␉␉␉Platform->CPU.TSCFrequency = maxClock * MEGA;␊ |
1269 | ␉␉}␊ |
1270 | ␉␉if ((cpuInfo->currentClock) && (cpuInfo->currentClock < 10000)) { //<10GHz␊ |
1271 | ␉␉␉Platform->CPU.CPUFrequency = cpuInfo->currentClock * MEGA;␊ |
1272 | ␉␉}␊ |
1273 | #endif␊ |
1274 | ␉␉msglog("DMI CPU Info:\n FSB=%d\n MaxSpeed=%d\n CurrentSpeed=%d\n", cpuInfo->externalClock, cpuInfo->maximumClock, cpuInfo->currentClock);␊ |
1275 | ␉␉msglog("DMI CPU Info 2:\n Family=%x\n Socket=%x\n Cores=%d Enabled=%d Threads=%d\n", cpuInfo->processorFamily, cpuInfo->processorUpgrade, cpuInfo->coreCount, cpuInfo->coreEnabled, cpuInfo->Threads);␊ |
1276 | #if 1 //NOTYET␊ |
1277 | ␉␉if ((cpuInfo->coreCount) && (cpuInfo->coreCount<Platform->CPU.NoCores)) {␊ |
1278 | ␉␉␉if (cpuInfo->coreEnabled < cpuInfo->coreCount) {␊ |
1279 | ␉␉␉␉cpuInfo->coreCount = cpuInfo->coreEnabled;␊ |
1280 | ␉␉␉}␊ |
1281 | ␉␉␉Platform->CPU.NoCores = cpuInfo->coreCount;␊ |
1282 | ␉␉}␊ |
1283 | ␉␉if ((cpuInfo->Threads) && (cpuInfo->Threads<Platform->CPU.NoThreads)) {␉␉␊ |
1284 | ␉␉␉Platform->CPU.NoThreads = cpuInfo->Threads;␊ |
1285 | ␉␉}␊ |
1286 | #endif␊ |
1287 | ␉␉␊ |
1288 | ␉␉return;␊ |
1289 | ␉}␊ |
1290 | ␉␊ |
1291 | ␉return;␊ |
1292 | }␊ |
1293 | //Slice - check other DMI info␊ |
1294 | bool scanDMI(void)␊ |
1295 | {␊ |
1296 | ␉struct DMIHeader * dmihdr = NULL; ␊ |
1297 | struct DMISystemEnclosure* encInfo; // Type 3␊ |
1298 | ␉␊ |
1299 | ␉for (dmihdr = FindFirstDmiTableOfType(3, 13); dmihdr; dmihdr = FindNextDmiTableOfType(3, 13)) ␊ |
1300 | ␉{␊ |
1301 | ␉␉encInfo = (struct DMISystemEnclosure*)dmihdr;␊ |
1302 | ␉␉msglog("DMI Chassis Info:\n Type=%x\n Boot-up State=%x\n Power Supply=%x Thermal State=%x\n", encInfo->type, encInfo->bootupState, encInfo->powerSupplyState, encInfo->thermalState);␊ |
1303 | ␉␉switch (encInfo->type) {␊ |
1304 | ␉␉␉case 1:␊ |
1305 | ␉␉␉case 2:␊ |
1306 | ␉␉␉␉return FALSE;␊ |
1307 | ␉␉␉case 3:␊ |
1308 | ␉␉␉case 4:␊ |
1309 | ␉␉␉case 6:␊ |
1310 | ␉␉␉case 7:␊ |
1311 | ␉␉␉␉Platform->CPU.Mobile = FALSE;␊ |
1312 | ␉␉␉␉break;␊ |
1313 | ␉␉␉case 8:␊ |
1314 | ␉␉␉case 9:␊ |
1315 | ␉␉␉case 0x0A:␊ |
1316 | ␉␉␉case 0x0B:␉␉␉␉␊ |
1317 | ␉␉␉case 0x0E:␊ |
1318 | ␉␉␉␉Platform->CPU.Mobile = TRUE;␊ |
1319 | ␉␉␉␉break;␊ |
1320 | ␉␉␉␉␊ |
1321 | ␉␉␉default:␊ |
1322 | ␉␉␉␉break;␊ |
1323 | ␉␉}␊ |
1324 | ␉␉return TRUE;␊ |
1325 | ␉}␊ |
1326 | ␉return FALSE;␉␊ |
1327 | }␊ |
1328 | |