1 | /*␊ |
2 | * platform_env.c␊ |
3 | * ␊ |
4 | * Copyright 2012 Cadet-petit Armel <armelcadetpetit@gmail.com>. All rights reserved.␊ |
5 | */␊ |
6 | ␊ |
7 | #include "libsaio.h"␊ |
8 | #include "bootstruct.h"␊ |
9 | #include "pci.h"␊ |
10 | #include "platform.h"␊ |
11 | #include "cpu.h"␊ |
12 | ␊ |
13 | #ifndef DEBUG_PLATFORM␊ |
14 | #define DEBUG_PLATFORM 0␊ |
15 | #endif␊ |
16 | ␊ |
17 | #if DEBUG_PLATFORM␊ |
18 | #define DBG(x...)␉printf(x)␊ |
19 | #else␊ |
20 | #define DBG(x...)␊ |
21 | #endif␊ |
22 | ␊ |
23 | #ifndef DEBUG_PLATFORM_CPU␊ |
24 | #define DEBUG_PLATFORM_CPU 0␊ |
25 | #endif␊ |
26 | ␊ |
27 | static char *gboardproduct = NULL;␊ |
28 | static char *gPlatformName = NULL;␊ |
29 | static char *gRootDevice = NULL;␊ |
30 | ␊ |
31 | void SetgRootDevice(const char * str)␊ |
32 | {␊ |
33 | gRootDevice = (char*)str;␊ |
34 | }␊ |
35 | void Setgboardproduct(const char * str)␊ |
36 | {␊ |
37 | gboardproduct = (char*)str;␊ |
38 | }␊ |
39 | void SetgPlatformName(const char * str)␊ |
40 | {␊ |
41 | gPlatformName = (char*)str;␊ |
42 | }␊ |
43 | ␊ |
44 | char * GetgPlatformName(void)␊ |
45 | {␊ |
46 | return gPlatformName ;␊ |
47 | }␊ |
48 | char * Getgboardproduct(void)␊ |
49 | {␊ |
50 | return gboardproduct;␊ |
51 | }␊ |
52 | char * GetgRootDevice(void)␊ |
53 | {␊ |
54 | return gRootDevice;␊ |
55 | }␊ |
56 | ␊ |
57 | #ifdef rootpath␊ |
58 | static char gRootPath[ROOT_PATH_LEN];␊ |
59 | void SetgRootPath(const char * str)␊ |
60 | {␊ |
61 | bzero(gRootPath,sizeof(gRootPath));␊ |
62 | memcpy(gRootPath,str, sizeof(gRootPath));␊ |
63 | }␊ |
64 | char * GetgRootPath(void)␊ |
65 | {␊ |
66 | return gRootPath ;␊ |
67 | }␊ |
68 | #endif␊ |
69 | ␊ |
70 | typedef enum envtype {␊ |
71 | kEnvPtr = 0,␊ |
72 | kEnvValue = 1␊ |
73 | } envtype;␊ |
74 | ␊ |
75 | struct env_struct {␊ |
76 | unsigned long long value; ␊ |
77 | char *name; ␊ |
78 | void * ptr;␊ |
79 | //int lock;␊ |
80 | enum envtype Type;␊ |
81 | UT_hash_handle hh; /* makes this structure hashable */␊ |
82 | };␊ |
83 | ␊ |
84 | static int CopyVarPtr (struct env_struct *var, void* ptr, size_t size);␊ |
85 | static struct env_struct *find_env(const char *name);␊ |
86 | static void _re_set_env_copy(struct env_struct *var , void* ptr,size_t size);␊ |
87 | struct env_struct *platform_env = NULL;␊ |
88 | ␊ |
89 | ␊ |
90 | static int CopyVarPtr (struct env_struct *var, void* ptr, size_t size)␊ |
91 | {␊ |
92 | var->ptr = malloc(size);␊ |
93 | if (!var->ptr) {␊ |
94 | return 0;␊ |
95 | }␊ |
96 | memcpy(var->ptr, ptr, size);␊ |
97 | return 1;␊ |
98 | }␊ |
99 | ␊ |
100 | static struct env_struct *find_env(const char *name) {␊ |
101 | struct env_struct *var;␊ |
102 | ␊ |
103 | ␉if (setjmp(uterror) == -1) {␊ |
104 | #if DEBUG_PLATFORM␊ |
105 | ␉␉printf("find_env: Unable to find environement variable\n"); ␊ |
106 | getc();␊ |
107 | #endif␊ |
108 | ␉␉return NULL;␊ |
109 | ␉} else {␊ |
110 | ␉␉HASH_FIND_STR( platform_env, name, var ); ␊ |
111 | ␉}␊ |
112 | return var;␊ |
113 | }␊ |
114 | ␊ |
115 | static void _re_set_env_copy(struct env_struct *var , void* ptr,size_t size) {␊ |
116 | ␊ |
117 | ␉if (var->Type == kEnvPtr) {␊ |
118 | ␉␉return ;␊ |
119 | ␉} ␊ |
120 | ␊ |
121 | if (var->ptr) {␊ |
122 | free(var->ptr);␊ |
123 | var->ptr = NULL;␊ |
124 | }␊ |
125 | ␊ |
126 | CopyVarPtr(var, ptr, size);␊ |
127 | ␉␊ |
128 | ␉return; ␊ |
129 | }␊ |
130 | ␊ |
131 | void re_set_env_copy(const char *name , void* ptr,size_t size) {␊ |
132 | ␉struct env_struct *var;␊ |
133 | ␊ |
134 | ␉var = find_env(name);␊ |
135 | ␉if (!var|| (var->Type == kEnvPtr)) {␊ |
136 | ␉␉printf("re_set_env_copy: Unable to find environement variable %s\n",name);␊ |
137 | #if DEBUG_PLATFORM␊ |
138 | getc();␊ |
139 | #endif␊ |
140 | ␉␉return ;␊ |
141 | ␉} ␊ |
142 | ␊ |
143 | _re_set_env_copy(var , ptr, size);␊ |
144 | ␉␊ |
145 | ␉return; ␊ |
146 | }␊ |
147 | ␊ |
148 | static void _set_env(const char *name, unsigned long long value, enum envtype Type, void* ptr, size_t size ) {␊ |
149 | struct env_struct *var;␊ |
150 | ␊ |
151 | var = (struct env_struct*)malloc(sizeof(struct env_struct));␊ |
152 | if (!var) {␊ |
153 | return;␊ |
154 | }␊ |
155 | if (Type == kEnvPtr) {␊ |
156 | if (!CopyVarPtr( var, ptr, size)) return;␊ |
157 | } ␊ |
158 | else if (Type == kEnvValue) ␊ |
159 | var->value = value;␊ |
160 | else␊ |
161 | return;␊ |
162 | ␊ |
163 | var->Type = Type; ␊ |
164 | ␊ |
165 | var->name = newString(name);␊ |
166 | if (!var->name) { ␊ |
167 | free(var);␊ |
168 | return;␊ |
169 | }␊ |
170 | ␉␊ |
171 | ␉if (setjmp(uterror) == -1) {␊ |
172 | ␉␉printf("_set_env: Unable to set environement variable"); // don't try to acces to the string 'name', ␊ |
173 | ␉␉//'cause we just returned from the longjump, stack as already changed state.␊ |
174 | #if DEBUG_PLATFORM␊ |
175 | ␉␉getc();␊ |
176 | #endif␊ |
177 | ␉␉return;␊ |
178 | ␉} else {␊ |
179 | HASH_ADD_KEYPTR( hh, platform_env, name, strlen(var->name), var );␊ |
180 | ␉}␊ |
181 | }␊ |
182 | ␊ |
183 | /* Warning: set_env will create a new variable each time it will be called, ␊ |
184 | * if you want to set again an existing variable, please use safe_set_env or re_set_env .␊ |
185 | * NOTE: If you set several times the "same variable" by using this function,␊ |
186 | * the HASH_COUNT will grow up, ␊ |
187 | * but hopefully find_env will return the last variable that you have set with the same name␊ |
188 | * ex: set_env("test",10);␊ |
189 | * set_env("test",20);␊ |
190 | *␊ |
191 | * HASH_COUNT will be equal to 2, get_env("test") will return 20␊ |
192 | *␊ |
193 | * safe_set_env("test",10);␊ |
194 | * safe_set_env("test",20);␊ |
195 | * ␊ |
196 | * HASH_COUNT will be equal to 1, get_env("test") will return 20␊ |
197 | *␊ |
198 | * set_env("test",10);␊ |
199 | * re_set_env("test",20);␊ |
200 | *␊ |
201 | * HASH_COUNT will be equal to 1, get_env("test") will return 20␊ |
202 | *␊ |
203 | */␊ |
204 | void set_env(const char *name, unsigned long long value ) {␊ |
205 | _set_env(name, value, kEnvValue,0,0);␊ |
206 | }␊ |
207 | ␊ |
208 | void set_env_copy(const char *name, void * ptr, size_t size ) {␊ |
209 | _set_env(name, 0, kEnvPtr,ptr,size);␊ |
210 | }␊ |
211 | ␊ |
212 | unsigned long long get_env_var(const char *name) {␊ |
213 | ␉struct env_struct *var;␊ |
214 | ␊ |
215 | ␉var = find_env(name);␊ |
216 | ␉if (!var) {␊ |
217 | #if DEBUG_PLATFORM␊ |
218 | ␉␉printf("get_env_var: Unable to find environement variable %s\n",name);␊ |
219 | getc();␊ |
220 | #endif␊ |
221 | ␉␉return 0;␊ |
222 | ␉}␊ |
223 | ␊ |
224 | if (var->Type != kEnvValue) {␊ |
225 | printf("get_env_var: Variable %s is not a value\n",name);␊ |
226 | #if DEBUG_PLATFORM␊ |
227 | getc();␊ |
228 | #endif␊ |
229 | return 0;␊ |
230 | }␊ |
231 | ␉␊ |
232 | ␉return var->value;␊ |
233 | ␊ |
234 | }␊ |
235 | ␊ |
236 | unsigned long long get_env(const char *name) {␉␊ |
237 | ␉␊ |
238 | ␉return get_env_var(name);;␊ |
239 | ␊ |
240 | }␊ |
241 | ␊ |
242 | void * get_env_ptr(const char *name) {␊ |
243 | ␉struct env_struct *var;␊ |
244 | ␊ |
245 | ␉var = find_env(name);␊ |
246 | ␉if (!var) {␊ |
247 | #if DEBUG_PLATFORM␊ |
248 | ␉␉printf("get_env_ptr: Unable to get environement ptr variable %s\n",name);␊ |
249 | getc();␊ |
250 | #endif␊ |
251 | ␉␉return 0;␊ |
252 | ␉}␊ |
253 | ␊ |
254 | if (var->Type != kEnvPtr) {␊ |
255 | printf("get_env_ptr: Variable %s is not a ptr\n",name);␊ |
256 | #if DEBUG_PLATFORM␊ |
257 | getc();␊ |
258 | #endif␊ |
259 | return 0;␊ |
260 | }␊ |
261 | ␉␊ |
262 | ␉return var->ptr;␊ |
263 | ␊ |
264 | }␊ |
265 | ␊ |
266 | /* If no specified variable exist, safe_set_env will create one, else it only modify the value */␊ |
267 | static void _safe_set_env(const char *name, unsigned long long value, enum envtype Type, void* ptr, size_t size )␊ |
268 | {␊ |
269 | ␉struct env_struct *var;␊ |
270 | ␊ |
271 | ␉var = find_env(name);␊ |
272 | ␊ |
273 | if (!var) {␊ |
274 | if (Type == kEnvPtr) {␊ |
275 | _set_env(name, 0, kEnvPtr,ptr,size);␊ |
276 | } ␊ |
277 | else if (Type == kEnvValue) {␊ |
278 | _set_env(name, value, kEnvValue,0,0);␊ |
279 | }␊ |
280 | } ␊ |
281 | else if (var->Type != Type) {␊ |
282 | return; ␊ |
283 | ␉} ␊ |
284 | else {␊ |
285 | if (Type == kEnvValue) ␊ |
286 | var->value = value;␊ |
287 | else if (Type == kEnvPtr)␊ |
288 | _re_set_env_copy(var,ptr,size); ␊ |
289 | }␊ |
290 | ␉␊ |
291 | ␉return; ␊ |
292 | }␊ |
293 | ␊ |
294 | void safe_set_env_copy(const char *name , void * ptr, size_t size ) {␊ |
295 | ␊ |
296 | _safe_set_env(name, 0, kEnvPtr,ptr,size);␊ |
297 | ␉␊ |
298 | ␉return; ␊ |
299 | }␊ |
300 | ␊ |
301 | void safe_set_env(const char *name , unsigned long long value) {␊ |
302 | ␊ |
303 | _safe_set_env(name, value, kEnvValue,0,0);␊ |
304 | ␉␊ |
305 | ␉return; ␊ |
306 | }␊ |
307 | ␊ |
308 | void re_set_env(const char *name , unsigned long long value) {␊ |
309 | ␉struct env_struct *var;␊ |
310 | ␊ |
311 | ␉var = find_env(name);␊ |
312 | ␉if (!var || (var->Type == kEnvValue)) {␊ |
313 | ␉␉printf("re_set_env: Unable to reset environement value variable %s\n",name);␊ |
314 | #if DEBUG_PLATFORM␊ |
315 | getc();␊ |
316 | #endif␊ |
317 | ␉␉return ;␊ |
318 | ␉} ␊ |
319 | ␊ |
320 | var->value = value;␊ |
321 | ␉␊ |
322 | ␉return; ␊ |
323 | }␊ |
324 | ␊ |
325 | static void delete_env(struct env_struct *var) {␊ |
326 | ␉␊ |
327 | ␉if (setjmp(uterror) == -1) {␊ |
328 | ␉␉printf("delete_env: Unable to delete environement variable\n");␊ |
329 | #if DEBUG_PLATFORM␊ |
330 | getc();␉␊ |
331 | #endif␊ |
332 | ␉␉return;␊ |
333 | ␉} else {␊ |
334 | ␉␉HASH_DEL( platform_env, var);␊ |
335 | if (var->name) free(var->name); ␊ |
336 | free(var);␊ |
337 | ␊ |
338 | ␉}␊ |
339 | }␊ |
340 | ␊ |
341 | void unset_env(const char *name) {␊ |
342 | struct env_struct *var;␊ |
343 | ␊ |
344 | if ((var = find_env(name))) {␊ |
345 | delete_env(var);␊ |
346 | } ␊ |
347 | }␊ |
348 | ␊ |
349 | void free_platform_env(void) {␊ |
350 | struct env_struct *current_var, *tmp; ␊ |
351 | ␊ |
352 | ␉if (setjmp(uterror) == -1) {␊ |
353 | ␉␉printf("free_platform_env: Unable to delete all environement variables\n"); ␊ |
354 | #if DEBUG_PLATFORM␊ |
355 | ␉␉getc();␊ |
356 | #endif␊ |
357 | ␉␉return;␊ |
358 | ␉} else {␊ |
359 | ␉␉HASH_ITER(hh, platform_env, current_var, tmp) { ␊ |
360 | ␉␉␉HASH_DEL(platform_env,current_var);␊ |
361 | if (current_var->name) free(current_var->name);␊ |
362 | ␉␉␉free(current_var); ␊ |
363 | ␉␉}␊ |
364 | ␉} ␊ |
365 | }␊ |
366 | ␊ |
367 | #if DEBUG_PLATFORM␊ |
368 | void debug_platform_env(void)␊ |
369 | {␊ |
370 | struct env_struct *current_var;␊ |
371 | for(current_var=platform_env;current_var;current_var=(struct env_struct*)(current_var->hh.next)) ␊ |
372 | {␊ |
373 | #if DEBUG_PLATFORM >= 2␊ |
374 | if (current_var->Type == kEnvValue)␊ |
375 | printf(" Name = %s | Type = VALUE | Value = 0x%04x\n",current_var->name,(uint32_t)current_var->value);␊ |
376 | else if (current_var->Type == kEnvPtr )␊ |
377 | printf(" Name = %s | Type = PTR(Copy) | Value = 0x%x\n",current_var->name,(uint32_t)current_var->ptr);␊ |
378 | #else␊ |
379 | ␊ |
380 | if (current_var->Type == kEnvValue)␊ |
381 | printf("%s: 0x%04x\n",current_var->name,(uint32_t)current_var->value);␊ |
382 | else if (current_var->Type == kEnvPtr )␊ |
383 | printf("%s(ptr): 0x%x\n",current_var->name,(uint32_t)current_var->ptr);␊ |
384 | #endif␊ |
385 | ␊ |
386 | }␊ |
387 | getc();␊ |
388 | }␊ |
389 | #endif␊ |
390 | ␊ |
391 | void showError(void)␊ |
392 | {␊ |
393 | struct env_struct *current_var;␊ |
394 | for(current_var=platform_env;current_var;current_var=(struct env_struct*)(current_var->hh.next)) ␊ |
395 | {␊ |
396 | ␉␉if (strcmp(current_var->name, envConsoleErr) == 0) {␊ |
397 | ␉␉␉if (current_var->Type == kEnvPtr) {␊ |
398 | ␉␉␉␉printf("stderr: %s \n",(char*)(uint32_t)current_var->ptr);␊ |
399 | ␉␉␉}␊ |
400 | ␉␉} ␊ |
401 | }␊ |
402 | }␊ |
403 | ␊ |
404 | /** ␊ |
405 | Scan platform hardware information, called by the main entry point (common_boot() ) ␊ |
406 | _before_ bootConfig xml parsing settings are loaded␊ |
407 | */␊ |
408 | void scan_platform(void)␊ |
409 | {␉␊ |
410 | ␉build_pci_dt();␊ |
411 | ␉scan_cpu();␊ |
412 | ␊ |
413 | #if DEBUG_PLATFORM_CPU␊ |
414 | printf("CPU: %s\n", (char*)get_env_ptr(envBrandString));␊ |
415 | if (get_env(envVendor) == CPUID_VENDOR_AMD)␊ |
416 | printf("CPU: Vendor/Model/ExtModel: 0x%x/0x%x/0x%x\n", (uint32_t)get_env(envVendor), (uint32_t)get_env(envModel), (uint32_t)get_env(envExtModel));␊ |
417 | ␉printf("CPU: Family/ExtFamily: 0x%x/0x%x\n", (uint32_t)get_env(envFamily), (uint32_t)get_env(envExtFamily));␊ |
418 | if (get_env(envVendor) == CPUID_VENDOR_AMD) {␊ |
419 | printf("CPU (AMD): TSCFreq: %dMHz\n", (uint32_t)(get_env(envTSCFreq) / 1000000));␊ |
420 | printf("CPU (AMD): FSBFreq: %dMHz\n", (uint32_t)(get_env(envFSBFreq) / 1000000));␊ |
421 | printf("CPU (AMD): CPUFreq: %dMHz\n", (uint32_t)(get_env(envCPUFreq) / 1000000));␊ |
422 | printf("CPU (AMD): MaxCoef/CurrCoef: 0x%x/0x%x\n", (uint32_t)get_env(envMaxCoef), (uint32_t)get_env(envCurrCoef));␊ |
423 | printf("CPU (AMD): MaxDiv/CurrDiv: 0x%x/0x%x\n", (uint32_t)get_env(envMaxDiv), (uint32_t)get_env(envCurrDiv));␊ |
424 | } else if (get_env(envVendor) == CPUID_VENDOR_INTEL){␊ |
425 | printf("CPU: TSCFreq: %dMHz\n", (uint32_t)(get_env(envTSCFreq) / 1000000));␊ |
426 | printf("CPU: FSBFreq: %dMHz\n", (uint32_t)(get_env(envFSBFreq) / 1000000));␊ |
427 | printf("CPU: CPUFreq: %dMHz\n", (uint32_t)(get_env(envCPUFreq) / 1000000));␊ |
428 | printf("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", (uint32_t)(get_env(envMaxCoef)), (uint32_t)(get_env(envCurrCoef)));␊ |
429 | printf("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", (uint32_t)(get_env(envMaxDiv)), (uint32_t)(get_env(envCurrDiv)));␊ |
430 | }␉␉␉␊ |
431 | ␉␊ |
432 | ␉printf("CPU: NoCores/NoThreads: %d/%d\n", (uint32_t)(get_env(envNoCores)), (uint32_t)(get_env(envNoThreads)));␊ |
433 | ␉printf("CPU: Features: 0x%08x\n", (uint32_t)(get_env(envFeatures)));␊ |
434 | printf("CPU: ExtFeatures: 0x%08x\n", (uint32_t)(get_env(envExtFeatures)));␊ |
435 | #ifndef AMD_SUPPORT␊ |
436 | printf("CPU: MicrocodeVersion: %d\n", (uint32_t)(get_env(envMicrocodeVersion)));␊ |
437 | #endif␊ |
438 | pause();␊ |
439 | #endif␊ |
440 | } |