blob: 6780c3a7ab083dfc2ae66c4aea1376a7e1119098 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Nico Huber5ce0fe12017-07-25 16:11:36 +02002
Nico Huber64ba44f2020-04-12 00:10:51 +02003#include <console/console.h>
Kyösti Mälkki836b8d22019-12-16 06:54:11 +02004#include <fallback.h>
Elyes Haouas69451f12022-10-07 10:08:53 +02005#include <pc80/mc146818rtc.h>
6#include <stdint.h>
Kyösti Mälkki23063302020-01-04 20:05:37 +02007
Kyösti Mälkki836b8d22019-12-16 06:54:11 +02008#if CONFIG_MAX_REBOOT_CNT > 15
9#error "CONFIG_MAX_REBOOT_CNT too high"
10#endif
11
Kyösti Mälkki1a9b7b52020-01-04 17:38:17 +020012static int boot_count(uint8_t rtc_byte)
Kyösti Mälkki836b8d22019-12-16 06:54:11 +020013{
14 return rtc_byte >> 4;
15}
16
Kyösti Mälkki1a9b7b52020-01-04 17:38:17 +020017static uint8_t increment_boot_count(uint8_t rtc_byte)
Kyösti Mälkki836b8d22019-12-16 06:54:11 +020018{
19 return rtc_byte + (1 << 4);
20}
21
Kyösti Mälkki1a9b7b52020-01-04 17:38:17 +020022static uint8_t boot_set_fallback(uint8_t rtc_byte)
Kyösti Mälkki836b8d22019-12-16 06:54:11 +020023{
24 return rtc_byte & ~RTC_BOOT_NORMAL;
25}
26
Kyösti Mälkki1a9b7b52020-01-04 17:38:17 +020027static int boot_use_normal(uint8_t rtc_byte)
Kyösti Mälkki836b8d22019-12-16 06:54:11 +020028{
29 return rtc_byte & RTC_BOOT_NORMAL;
30}
31
32int do_normal_boot(void)
33{
34 unsigned char byte;
35
Kyösti Mälkki94aaf5b2020-01-04 20:45:04 +020036 if (cmos_error() || (CONFIG(USE_OPTION_TABLE) && !cmos_lb_cks_valid())) {
Nico Huber64ba44f2020-04-12 00:10:51 +020037 printk(BIOS_WARNING,
38 "Invalid CMOS checksum detected! Force fallback boot...\n");
Kyösti Mälkki836b8d22019-12-16 06:54:11 +020039 byte = cmos_read(RTC_BOOT_BYTE);
40 byte &= boot_set_fallback(byte) & 0x0f;
41 byte |= 0xf << 4;
42 cmos_write(byte, RTC_BOOT_BYTE);
43 }
44
45 /* The RTC_BOOT_BYTE is now o.k. see where to go. */
46 byte = cmos_read(RTC_BOOT_BYTE);
47
48 /* Are we attempting to boot normally? */
49 if (boot_use_normal(byte)) {
50 /* Are we already at the max count? */
51 if (boot_count(byte) < CONFIG_MAX_REBOOT_CNT)
52 byte = increment_boot_count(byte);
53 else
54 byte = boot_set_fallback(byte);
55 }
56
57 /* Save the boot byte */
58 cmos_write(byte, RTC_BOOT_BYTE);
59
60 /* Return selected code path for this boot attempt */
61 return boot_use_normal(byte);
62}