Angel Pons | 8a3453f | 2020-04-02 23:48:19 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Nico Huber | 5ce0fe1 | 2017-07-25 16:11:36 +0200 | [diff] [blame] | 2 | |
Nico Huber | 64ba44f | 2020-04-12 00:10:51 +0200 | [diff] [blame] | 3 | #include <console/console.h> |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 4 | #include <fallback.h> |
Elyes Haouas | 69451f1 | 2022-10-07 10:08:53 +0200 | [diff] [blame] | 5 | #include <pc80/mc146818rtc.h> |
| 6 | #include <stdint.h> |
Kyösti Mälkki | 2306330 | 2020-01-04 20:05:37 +0200 | [diff] [blame] | 7 | |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 8 | #if CONFIG_MAX_REBOOT_CNT > 15 |
| 9 | #error "CONFIG_MAX_REBOOT_CNT too high" |
| 10 | #endif |
| 11 | |
Kyösti Mälkki | 1a9b7b5 | 2020-01-04 17:38:17 +0200 | [diff] [blame] | 12 | static int boot_count(uint8_t rtc_byte) |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 13 | { |
| 14 | return rtc_byte >> 4; |
| 15 | } |
| 16 | |
Kyösti Mälkki | 1a9b7b5 | 2020-01-04 17:38:17 +0200 | [diff] [blame] | 17 | static uint8_t increment_boot_count(uint8_t rtc_byte) |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 18 | { |
| 19 | return rtc_byte + (1 << 4); |
| 20 | } |
| 21 | |
Kyösti Mälkki | 1a9b7b5 | 2020-01-04 17:38:17 +0200 | [diff] [blame] | 22 | static uint8_t boot_set_fallback(uint8_t rtc_byte) |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 23 | { |
| 24 | return rtc_byte & ~RTC_BOOT_NORMAL; |
| 25 | } |
| 26 | |
Kyösti Mälkki | 1a9b7b5 | 2020-01-04 17:38:17 +0200 | [diff] [blame] | 27 | static int boot_use_normal(uint8_t rtc_byte) |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 28 | { |
| 29 | return rtc_byte & RTC_BOOT_NORMAL; |
| 30 | } |
| 31 | |
| 32 | int do_normal_boot(void) |
| 33 | { |
| 34 | unsigned char byte; |
| 35 | |
Kyösti Mälkki | 94aaf5b | 2020-01-04 20:45:04 +0200 | [diff] [blame] | 36 | if (cmos_error() || (CONFIG(USE_OPTION_TABLE) && !cmos_lb_cks_valid())) { |
Nico Huber | 64ba44f | 2020-04-12 00:10:51 +0200 | [diff] [blame] | 37 | printk(BIOS_WARNING, |
| 38 | "Invalid CMOS checksum detected! Force fallback boot...\n"); |
Kyösti Mälkki | 836b8d2 | 2019-12-16 06:54:11 +0200 | [diff] [blame] | 39 | 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 | } |