- Fix race condition in option_table.h generation by moving the include
[coreboot.git] / src / pc80 / mc146818rtc_early.c
1 #include <pc80/mc146818rtc.h>
2 #include <fallback.h>
3 #if CONFIG_USE_OPTION_TABLE
4 #include "option_table.h"
5 #endif
6
7 #ifndef CONFIG_MAX_REBOOT_CNT
8 #error "CONFIG_MAX_REBOOT_CNT not defined"
9 #endif
10 #if  CONFIG_MAX_REBOOT_CNT > 15
11 #error "CONFIG_MAX_REBOOT_CNT too high"
12 #endif
13
14 static int cmos_error(void)
15 {
16         unsigned char reg_d;
17         /* See if the cmos error condition has been flagged */
18         reg_d = cmos_read(RTC_REG_D);
19         return (reg_d & RTC_VRT) == 0;
20 }
21
22 static int cmos_chksum_valid(void)
23 {
24 #if CONFIG_USE_OPTION_TABLE
25         unsigned char addr;
26         unsigned long sum, old_sum;
27         sum = 0;
28         /* Comput the cmos checksum */
29         for(addr = LB_CKS_RANGE_START; addr <= LB_CKS_RANGE_END; addr++) {
30                 sum += cmos_read(addr);
31         }
32         sum = (sum & 0xffff) ^ 0xffff;
33
34         /* Read the stored checksum */
35         old_sum = cmos_read(LB_CKS_LOC) << 8;
36         old_sum |=  cmos_read(LB_CKS_LOC+1);
37
38         return sum == old_sum;
39 #else
40         return 0;
41 #endif
42 }
43
44
45 static inline int last_boot_normal(void)
46 {
47         unsigned char byte;
48         byte = cmos_read(RTC_BOOT_BYTE);
49         return (byte & (1 << 1));
50 }
51
52 static inline int do_normal_boot(void)
53 {
54         unsigned char byte;
55
56         if (cmos_error() || !cmos_chksum_valid()) {
57                 /* There are no impossible values, no checksums so just
58                  * trust whatever value we have in the the cmos,
59                  * but clear the fallback bit.
60                  */
61                 byte = cmos_read(RTC_BOOT_BYTE);
62                 byte &= 0x0c;
63                 byte |= CONFIG_MAX_REBOOT_CNT << 4;
64                 cmos_write(byte, RTC_BOOT_BYTE);
65         }
66
67         /* The RTC_BOOT_BYTE is now o.k. see where to go. */
68         byte = cmos_read(RTC_BOOT_BYTE);
69
70         /* Are we in normal mode? */
71         if (byte & 1) {
72                 byte &= 0x0f; /* yes, clear the boot count */
73         }
74
75         /* Properly set the last boot flag */
76         byte &= 0xfc;
77         if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
78                 byte |= (1<<1);
79         }
80
81         /* Are we already at the max count? */
82         if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
83                 byte += 1 << 4; /* No, add 1 to the count */
84         }
85         else {
86                 byte &= 0xfc;   /* Yes, put in fallback mode */
87         }
88
89         /* Save the boot byte */
90         cmos_write(byte, RTC_BOOT_BYTE);
91
92         return (byte & (1<<1));
93 }
94
95 unsigned read_option(unsigned start, unsigned size, unsigned def)
96 {
97 #if CONFIG_USE_OPTION_TABLE
98         unsigned byte;
99         byte = cmos_read(start/8);
100         return (byte >> (start & 7U)) & ((1U << size) - 1U);
101 #else
102         return def;
103 #endif
104 }