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 | static char *gboardproduct = NULL;␊ |
24 | static char *gPlatformName = NULL;␊ |
25 | static char *gRootDevice = NULL;␊ |
26 | ␊ |
27 | void SetgRootDevice(const char * str)␊ |
28 | {␊ |
29 | gRootDevice = (char*)str;␊ |
30 | }␊ |
31 | void Setgboardproduct(const char * str)␊ |
32 | {␊ |
33 | gboardproduct = (char*)str;␊ |
34 | }␊ |
35 | void SetgPlatformName(const char * str)␊ |
36 | {␊ |
37 | gPlatformName = (char*)str;␊ |
38 | }␊ |
39 | ␊ |
40 | char * GetgPlatformName(void)␊ |
41 | {␊ |
42 | return gPlatformName ;␊ |
43 | }␊ |
44 | char * Getgboardproduct(void)␊ |
45 | {␊ |
46 | return gboardproduct;␊ |
47 | }␊ |
48 | char * GetgRootDevice(void)␊ |
49 | {␊ |
50 | return gRootDevice;␊ |
51 | }␊ |
52 | ␊ |
53 | #ifdef rootpath␊ |
54 | static char gRootPath[ROOT_PATH_LEN];␊ |
55 | void SetgRootPath(const char * str)␊ |
56 | {␊ |
57 | bzero(gRootPath,sizeof(gRootPath));␊ |
58 | memcpy(gRootPath,str, sizeof(gRootPath));␊ |
59 | }␊ |
60 | char * GetgRootPath(void)␊ |
61 | {␊ |
62 | return gRootPath ;␊ |
63 | }␊ |
64 | #endif␊ |
65 | ␊ |
66 | typedef enum envtype {␊ |
67 | kEnvPtr = 0,␊ |
68 | kEnvValue = 1␊ |
69 | } envtype;␊ |
70 | ␊ |
71 | struct env_struct {␊ |
72 | unsigned long long value; ␊ |
73 | char *name; ␊ |
74 | void * ptr;␊ |
75 | //int lock;␊ |
76 | enum envtype Type;␊ |
77 | UT_hash_handle hh; /* makes this structure hashable */␊ |
78 | };␊ |
79 | ␊ |
80 | static int CopyVarPtr (struct env_struct *var, void* ptr, size_t size);␊ |
81 | static struct env_struct *find_env(const char *name);␊ |
82 | static void _re_set_env_copy(struct env_struct *var , void* ptr,size_t size);␊ |
83 | struct env_struct *platform_env = NULL;␊ |
84 | ␊ |
85 | ␊ |
86 | static int CopyVarPtr (struct env_struct *var, void* ptr, size_t size)␊ |
87 | {␊ |
88 | var->ptr = malloc(size);␊ |
89 | if (!var->ptr) {␊ |
90 | return 0;␊ |
91 | }␊ |
92 | memcpy(var->ptr, ptr, size);␊ |
93 | return 1;␊ |
94 | }␊ |
95 | ␊ |
96 | static struct env_struct *find_env(const char *name) {␊ |
97 | struct env_struct *var;␊ |
98 | ␊ |
99 | ␉if (setjmp(h_buf_error) == -1) {␊ |
100 | #if DEBUG_PLATFORM␊ |
101 | ␉␉printf("find_env: Unable to find environement variable\n"); ␊ |
102 | getc();␊ |
103 | #endif␊ |
104 | ␉␉return NULL;␊ |
105 | ␉} else {␊ |
106 | ␉␉HASH_FIND_STR( platform_env, name, var ); ␊ |
107 | ␉}␊ |
108 | return var;␊ |
109 | }␊ |
110 | ␊ |
111 | static void _re_set_env_copy(struct env_struct *var , void* ptr,size_t size) {␊ |
112 | ␊ |
113 | ␉if (var->Type == kEnvPtr) {␊ |
114 | ␉␉return ;␊ |
115 | ␉} ␊ |
116 | ␊ |
117 | if (var->ptr) {␊ |
118 | free(var->ptr);␊ |
119 | var->ptr = NULL;␊ |
120 | }␊ |
121 | ␊ |
122 | CopyVarPtr(var, ptr, size);␊ |
123 | ␉␊ |
124 | ␉return; ␊ |
125 | }␊ |
126 | ␊ |
127 | void re_set_env_copy(const char *name , void* ptr,size_t size) {␊ |
128 | ␉struct env_struct *var;␊ |
129 | ␊ |
130 | ␉var = find_env(name);␊ |
131 | ␉if (!var|| (var->Type == kEnvPtr)) {␊ |
132 | ␉␉printf("re_set_env_copy: Unable to find environement variable %s\n",name);␊ |
133 | #if DEBUG_PLATFORM␊ |
134 | getc();␊ |
135 | #endif␊ |
136 | ␉␉return ;␊ |
137 | ␉} ␊ |
138 | ␊ |
139 | _re_set_env_copy(var , ptr, size);␊ |
140 | ␉␊ |
141 | ␉return; ␊ |
142 | }␊ |
143 | ␊ |
144 | static void _set_env(const char *name, unsigned long long value, enum envtype Type, void* ptr, size_t size ) {␊ |
145 | struct env_struct *var;␊ |
146 | ␊ |
147 | var = (struct env_struct*)malloc(sizeof(struct env_struct));␊ |
148 | if (!var) {␊ |
149 | return;␊ |
150 | }␊ |
151 | if (Type == kEnvPtr) {␊ |
152 | if (!CopyVarPtr( var, ptr, size)) return;␊ |
153 | } ␊ |
154 | else if (Type == kEnvValue) ␊ |
155 | var->value = value;␊ |
156 | else␊ |
157 | return;␊ |
158 | ␊ |
159 | var->Type = Type; ␊ |
160 | ␊ |
161 | var->name = newString(name);␊ |
162 | if (!var->name) { ␊ |
163 | free(var);␊ |
164 | return;␊ |
165 | }␊ |
166 | ␉␊ |
167 | ␉if (setjmp(h_buf_error) == -1) {␊ |
168 | ␉␉printf("_set_env: Unable to set environement variable"); // don't try to acces to the string 'name', ␊ |
169 | ␉␉//'cause we just returned from the longjump, stack as already changed state.␊ |
170 | #if DEBUG_PLATFORM␊ |
171 | ␉␉getc();␊ |
172 | #endif␊ |
173 | ␉␉return;␊ |
174 | ␉} else {␊ |
175 | HASH_ADD_KEYPTR( hh, platform_env, name, strlen(var->name), var );␊ |
176 | ␉}␊ |
177 | }␊ |
178 | ␊ |
179 | /* Warning: set_env will create a new variable each time it will be called, ␊ |
180 | * if you want to set again an existing variable, please use safe_set_env or re_set_env .␊ |
181 | * NOTE: If you set several times the "same variable" by using this function,␊ |
182 | * the HASH_COUNT will grow up, ␊ |
183 | * but hopefully find_env will return the last variable that you have set with the same name␊ |
184 | * ex: set_env("test",10);␊ |
185 | * set_env("test",20);␊ |
186 | *␊ |
187 | * HASH_COUNT will be equal to 2, get_env("test") will return 20␊ |
188 | *␊ |
189 | * safe_set_env("test",10);␊ |
190 | * safe_set_env("test",20);␊ |
191 | * ␊ |
192 | * HASH_COUNT will be equal to 1, get_env("test") will return 20␊ |
193 | *␊ |
194 | * set_env("test",10);␊ |
195 | * re_set_env("test",20);␊ |
196 | *␊ |
197 | * HASH_COUNT will be equal to 1, get_env("test") will return 20␊ |
198 | *␊ |
199 | */␊ |
200 | void set_env(const char *name, unsigned long long value ) {␊ |
201 | _set_env(name, value, kEnvValue,0,0);␊ |
202 | }␊ |
203 | ␊ |
204 | void set_env_copy(const char *name, void * ptr, size_t size ) {␊ |
205 | _set_env(name, 0, kEnvPtr,ptr,size);␊ |
206 | }␊ |
207 | ␊ |
208 | unsigned long long get_env_var(const char *name) {␊ |
209 | ␉struct env_struct *var;␊ |
210 | ␊ |
211 | ␉var = find_env(name);␊ |
212 | ␉if (!var) {␊ |
213 | #if DEBUG_PLATFORM␊ |
214 | ␉␉printf("get_env_var: Unable to find environement variable %s\n",name);␊ |
215 | getc();␊ |
216 | #endif␊ |
217 | ␉␉return 0;␊ |
218 | ␉}␊ |
219 | ␊ |
220 | if (var->Type != kEnvValue) {␊ |
221 | printf("get_env_var: Variable %s is not a value\n",name);␊ |
222 | #if DEBUG_PLATFORM␊ |
223 | getc();␊ |
224 | #endif␊ |
225 | return 0;␊ |
226 | }␊ |
227 | ␉␊ |
228 | ␉return var->value;␊ |
229 | ␊ |
230 | }␊ |
231 | ␊ |
232 | unsigned long long get_env(const char *name) {␉␊ |
233 | ␉␊ |
234 | ␉return get_env_var(name);;␊ |
235 | ␊ |
236 | }␊ |
237 | ␊ |
238 | void * get_env_ptr(const char *name) {␊ |
239 | ␉struct env_struct *var;␊ |
240 | ␊ |
241 | ␉var = find_env(name);␊ |
242 | ␉if (!var) {␊ |
243 | #if DEBUG_PLATFORM␊ |
244 | ␉␉printf("get_env_ptr: Unable to get environement ptr variable %s\n",name);␊ |
245 | getc();␊ |
246 | #endif␊ |
247 | ␉␉return 0;␊ |
248 | ␉}␊ |
249 | ␊ |
250 | if (var->Type != kEnvPtr) {␊ |
251 | printf("get_env_ptr: Variable %s is not a ptr\n",name);␊ |
252 | #if DEBUG_PLATFORM␊ |
253 | getc();␊ |
254 | #endif␊ |
255 | return 0;␊ |
256 | }␊ |
257 | ␉␊ |
258 | ␉return var->ptr;␊ |
259 | ␊ |
260 | }␊ |
261 | ␊ |
262 | /* If no specified variable exist, safe_set_env will create one, else it only modify the value */␊ |
263 | static void _safe_set_env(const char *name, unsigned long long value, enum envtype Type, void* ptr, size_t size )␊ |
264 | {␊ |
265 | ␉struct env_struct *var;␊ |
266 | ␊ |
267 | ␉var = find_env(name);␊ |
268 | ␊ |
269 | if (!var) {␊ |
270 | if (Type == kEnvPtr) {␊ |
271 | _set_env(name, 0, kEnvPtr,ptr,size);␊ |
272 | } ␊ |
273 | else if (Type == kEnvValue) {␊ |
274 | _set_env(name, value, kEnvValue,0,0);␊ |
275 | }␊ |
276 | } ␊ |
277 | else if (var->Type != Type) {␊ |
278 | return; ␊ |
279 | ␉} ␊ |
280 | else {␊ |
281 | if (Type == kEnvValue) ␊ |
282 | var->value = value;␊ |
283 | else if (Type == kEnvPtr)␊ |
284 | _re_set_env_copy(var,ptr,size); ␊ |
285 | }␊ |
286 | ␉␊ |
287 | ␉return; ␊ |
288 | }␊ |
289 | ␊ |
290 | void safe_set_env_copy(const char *name , void * ptr, size_t size ) {␊ |
291 | ␊ |
292 | _safe_set_env(name, 0, kEnvPtr,ptr,size);␊ |
293 | ␉␊ |
294 | ␉return; ␊ |
295 | }␊ |
296 | ␊ |
297 | void safe_set_env(const char *name , unsigned long long value) {␊ |
298 | ␊ |
299 | _safe_set_env(name, value, kEnvValue,0,0);␊ |
300 | ␉␊ |
301 | ␉return; ␊ |
302 | }␊ |
303 | ␊ |
304 | void re_set_env(const char *name , unsigned long long value) {␊ |
305 | ␉struct env_struct *var;␊ |
306 | ␊ |
307 | ␉var = find_env(name);␊ |
308 | ␉if (!var || (var->Type == kEnvValue)) {␊ |
309 | ␉␉printf("re_set_env: Unable to reset environement value variable %s\n",name);␊ |
310 | #if DEBUG_PLATFORM␊ |
311 | getc();␊ |
312 | #endif␊ |
313 | ␉␉return ;␊ |
314 | ␉} ␊ |
315 | ␊ |
316 | var->value = value;␊ |
317 | ␉␊ |
318 | ␉return; ␊ |
319 | }␊ |
320 | ␊ |
321 | static void delete_env(struct env_struct *var) {␊ |
322 | ␉␊ |
323 | ␉if (setjmp(h_buf_error) == -1) {␊ |
324 | ␉␉printf("delete_env: Unable to delete environement variable\n");␊ |
325 | #if DEBUG_PLATFORM␊ |
326 | getc();␉␊ |
327 | #endif␊ |
328 | ␉␉return;␊ |
329 | ␉} else {␊ |
330 | ␉␉HASH_DEL( platform_env, var);␊ |
331 | if (var->name) free(var->name); ␊ |
332 | free(var);␊ |
333 | ␊ |
334 | ␉}␊ |
335 | }␊ |
336 | ␊ |
337 | void unset_env(const char *name) {␊ |
338 | struct env_struct *var;␊ |
339 | ␊ |
340 | if ((var = find_env(name))) {␊ |
341 | delete_env(var);␊ |
342 | } ␊ |
343 | }␊ |
344 | ␊ |
345 | void free_platform_env(void) {␊ |
346 | struct env_struct *current_var, *tmp; ␊ |
347 | ␊ |
348 | ␉if (setjmp(h_buf_error) == -1) {␊ |
349 | ␉␉printf("free_platform_env: Unable to delete all environement variables\n"); ␊ |
350 | #if DEBUG_PLATFORM␊ |
351 | ␉␉getc();␊ |
352 | #endif␊ |
353 | ␉␉return;␊ |
354 | ␉} else {␊ |
355 | ␉␉HASH_ITER(hh, platform_env, current_var, tmp) { ␊ |
356 | ␉␉␉HASH_DEL(platform_env,current_var);␊ |
357 | if (current_var->name) free(current_var->name);␊ |
358 | ␉␉␉free(current_var); ␊ |
359 | ␉␉}␊ |
360 | ␉} ␊ |
361 | }␊ |
362 | ␊ |
363 | #if DEBUG_PLATFORM␊ |
364 | void debug_platform_env(void)␊ |
365 | {␊ |
366 | struct env_struct *current_var = platform_env;␊ |
367 | for(current_var=platform_env;current_var;current_var=(struct env_struct*)(current_var->hh.next)) ␊ |
368 | {␊ |
369 | #if DEBUG_PLATFORM >= 2␊ |
370 | if (current_var->Type == kEnvValue)␊ |
371 | printf(" Name = %s | Type = VALUE | Value = 0x%04x\n",current_var->name,(uint32_t)current_var->value);␊ |
372 | else if (current_var->Type == kEnvPtr )␊ |
373 | printf(" Name = %s | Type = PTR(Copy) | Value = 0x%x\n",current_var->name,(uint32_t)current_var->ptr);␊ |
374 | #else␊ |
375 | ␊ |
376 | if (current_var->Type == kEnvValue)␊ |
377 | printf("%s: 0x%04x\n",current_var->name,(uint32_t)current_var->value);␊ |
378 | else if (current_var->Type == kEnvPtr )␊ |
379 | printf("%s(ptr): 0x%x\n",current_var->name,(uint32_t)current_var->ptr);␊ |
380 | #endif␊ |
381 | ␊ |
382 | }␊ |
383 | getc();␊ |
384 | }␊ |
385 | #endif␊ |
386 | ␊ |
387 | /** ␊ |
388 | Scan platform hardware information, called by the main entry point (common_boot() ) ␊ |
389 | _before_ bootConfig xml parsing settings are loaded␊ |
390 | */␊ |
391 | void scan_platform(void)␊ |
392 | {␉␊ |
393 | ␉//memset(&Platform, 0, sizeof(PlatformInfo_t));␊ |
394 | ␉build_pci_dt();␊ |
395 | ␉scan_cpu();␊ |
396 | ␊ |
397 | #if DEBUG_PLATFORM␊ |
398 | DBG("CPU: %s\n", (char*)get_env_ptr(envBrandString));␊ |
399 | if (get_env(envVendor) == CPUID_VENDOR_AMD)␊ |
400 | DBG("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));␊ |
401 | ␉DBG("CPU: Family/ExtFamily: 0x%x/0x%x\n", (uint32_t)get_env(envFamily), (uint32_t)get_env(envExtFamily));␊ |
402 | if (get_env(envVendor) == CPUID_VENDOR_AMD) {␊ |
403 | DBG("CPU (AMD): TSCFreq: %dMHz\n", (uint32_t)(get_env(envTSCFreq) / 1000000));␊ |
404 | DBG("CPU (AMD): FSBFreq: %dMHz\n", (uint32_t)(get_env(envFSBFreq) / 1000000));␊ |
405 | DBG("CPU (AMD): CPUFreq: %dMHz\n", (uint32_t)(get_env(envCPUFreq) / 1000000));␊ |
406 | DBG("CPU (AMD): MaxCoef/CurrCoef: 0x%x/0x%x\n", (uint32_t)get_env(envMaxCoef), (uint32_t)get_env(envCurrCoef));␊ |
407 | DBG("CPU (AMD): MaxDiv/CurrDiv: 0x%x/0x%x\n", (uint32_t)get_env(envMaxDiv), (uint32_t)get_env(envCurrDiv));␊ |
408 | } else if (get_env(envVendor) == CPUID_VENDOR_INTEL){␊ |
409 | DBG("CPU: TSCFreq: %dMHz\n", (uint32_t)(get_env(envTSCFreq) / 1000000));␊ |
410 | DBG("CPU: FSBFreq: %dMHz\n", (uint32_t)(get_env(envFSBFreq) / 1000000));␊ |
411 | DBG("CPU: CPUFreq: %dMHz\n", (uint32_t)(get_env(envCPUFreq) / 1000000));␊ |
412 | DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", (uint32_t)(get_env(envMaxCoef)), (uint32_t)(get_env(envCurrCoef)));␊ |
413 | DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", (uint32_t)(get_env(envMaxDiv)), (uint32_t)(get_env(envCurrDiv)));␊ |
414 | }␉␉␉␊ |
415 | ␉␊ |
416 | ␉DBG("CPU: NoCores/NoThreads: %d/%d\n", (uint32_t)(get_env(envNoCores)), (uint32_t)(get_env(envNoThreads)));␊ |
417 | ␉DBG("CPU: Features: 0x%08x\n", (uint32_t)(get_env(envFeatures)));␊ |
418 | DBG("CPU: ExtFeatures: 0x%08x\n", (uint32_t)(get_env(envExtFeatures)));␊ |
419 | #ifndef AMD_SUPPORT␊ |
420 | DBG("CPU: MicrocodeVersion: %d\n", (uint32_t)(get_env(envMicrocodeVersion)));␊ |
421 | #endif␊ |
422 | pause();␊ |
423 | #endif␊ |
424 | }␊ |
425 | ␊ |
426 | #ifdef ShowCurrentDate␊ |
427 | ␊ |
428 | // shamefully ripped to http://wiki.osdev.org/CMOS␊ |
429 | ␊ |
430 | /*␊ |
431 | * http://wiki.osdev.org/OSDev_Wiki:General_disclaimer␊ |
432 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR␊ |
433 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,␊ |
434 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE␊ |
435 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER␊ |
436 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,␊ |
437 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN␊ |
438 | * THE SOFTWARE.␊ |
439 | */␊ |
440 | ␊ |
441 | #define CURRENT_YEAR 2012 // Change this each year!␊ |
442 | ␊ |
443 | static int century_register = 0x00; // Set by ACPI table parsing code if possible(... in FADT table)␊ |
444 | ␊ |
445 | enum {␊ |
446 | cmos_address = 0x70,␊ |
447 | cmos_data = 0x71␊ |
448 | };␊ |
449 | ␊ |
450 | ␊ |
451 | static int get_update_in_progress_flag() {␊ |
452 | outb(cmos_address, 0x0A);␊ |
453 | return (inb(cmos_data) & 0x80);␊ |
454 | }␊ |
455 | ␊ |
456 | ␊ |
457 | static unsigned char get_RTC_register(int reg) {␊ |
458 | outb(cmos_address, reg);␊ |
459 | return inb(cmos_data);␊ |
460 | }␊ |
461 | ␊ |
462 | static void read_rtc(EFI_TIME *time) {␊ |
463 | unsigned char century;␊ |
464 | unsigned char last_second;␊ |
465 | unsigned char last_minute;␊ |
466 | unsigned char last_hour;␊ |
467 | unsigned char last_day;␊ |
468 | unsigned char last_month;␊ |
469 | unsigned char last_year;␊ |
470 | unsigned char last_century;␊ |
471 | unsigned char registerB;␊ |
472 | ␊ |
473 | unsigned char second;␊ |
474 | unsigned char minute;␊ |
475 | unsigned char hour;␊ |
476 | unsigned char day;␊ |
477 | unsigned char month;␊ |
478 | unsigned int year;␊ |
479 | // Note: This uses the "read registers until you get the same values twice in a row" technique␊ |
480 | // to avoid getting dodgy/inconsistent values due to RTC updates␊ |
481 | ␊ |
482 | while (get_update_in_progress_flag()); // Make sure an update isn't in progress␊ |
483 | second = get_RTC_register(0x00);␊ |
484 | minute = get_RTC_register(0x02);␊ |
485 | hour = get_RTC_register(0x04);␊ |
486 | day = get_RTC_register(0x07);␊ |
487 | month = get_RTC_register(0x08);␊ |
488 | year = get_RTC_register(0x09);␊ |
489 | if(century_register != 0) {␊ |
490 | century = get_RTC_register(century_register);␊ |
491 | }␊ |
492 | ␊ |
493 | do {␊ |
494 | last_second = second;␊ |
495 | last_minute = minute;␊ |
496 | last_hour = hour;␊ |
497 | last_day = day;␊ |
498 | last_month = month;␊ |
499 | last_year = year;␊ |
500 | last_century = century;␊ |
501 | ␊ |
502 | while (get_update_in_progress_flag()); // Make sure an update isn't in progress␊ |
503 | second = get_RTC_register(0x00);␊ |
504 | minute = get_RTC_register(0x02);␊ |
505 | hour = get_RTC_register(0x04);␊ |
506 | day = get_RTC_register(0x07);␊ |
507 | month = get_RTC_register(0x08);␊ |
508 | year = get_RTC_register(0x09);␊ |
509 | if(century_register != 0) {␊ |
510 | century = get_RTC_register(century_register);␊ |
511 | }␊ |
512 | } while( (last_second == second) && (last_minute == minute) && (last_hour == hour) &&␊ |
513 | (last_day == day) && (last_month == month) && (last_year == year) &&␊ |
514 | (last_century == century) );␊ |
515 | ␊ |
516 | registerB = get_RTC_register(0x0B);␊ |
517 | ␊ |
518 | // Convert BCD to binary values if necessary␊ |
519 | ␊ |
520 | if (!(registerB & 0x04)) {␊ |
521 | second = (second & 0x0F) + ((second / 16) * 10);␊ |
522 | minute = (minute & 0x0F) + ((minute / 16) * 10);␊ |
523 | hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80);␊ |
524 | day = (day & 0x0F) + ((day / 16) * 10);␊ |
525 | month = (month & 0x0F) + ((month / 16) * 10);␊ |
526 | year = (year & 0x0F) + ((year / 16) * 10);␊ |
527 | if(century_register != 0) {␊ |
528 | century = (century & 0x0F) + ((century / 16) * 10);␊ |
529 | }␊ |
530 | } ␊ |
531 | ␊ |
532 | // Calculate the full (4-digit) year␊ |
533 | ␊ |
534 | if(century_register != 0) {␊ |
535 | year += century * 100;␊ |
536 | } else {␊ |
537 | //year += (CURRENT_YEAR / 100) * 100;␊ |
538 | //if(year < CURRENT_YEAR) year += 100; ␊ |
539 | ␊ |
540 | if ((year += 1900) < 1970)␊ |
541 | year += 100;␊ |
542 | }␊ |
543 | ␊ |
544 | time->Second = second;␊ |
545 | time->Minute = minute;␊ |
546 | time->Hour = hour;␊ |
547 | time->Day = day;␊ |
548 | time->Month = month;␊ |
549 | time->Year = year;␊ |
550 | }␊ |
551 | ␊ |
552 | void rtc_time(EFI_TIME *time) {␊ |
553 | ␊ |
554 | read_rtc(time);␊ |
555 | ␊ |
556 | time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;␊ |
557 | ␊ |
558 | return ;␊ |
559 | }␊ |
560 | ␊ |
561 | char * Date(void)␊ |
562 | {␊ |
563 | EFI_TIME rtctime; ␊ |
564 | rtc_time(&rtctime);␊ |
565 | ␊ |
566 | return newStringWithFormat("%02d/%02d/%04d %02d:%02d:%02d",rtctime.Month,rtctime.Day,rtctime.Year,␊ |
567 | rtctime.Hour,rtctime.Minute,rtctime.Second);␊ |
568 | }␊ |
569 | #endif |