summaryrefslogtreecommitdiff
path: root/src/drivers/pc80
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-11-01 02:13:17 -0600
committerMartin Roth <martinroth@google.com>2015-11-03 21:55:20 +0100
commit3bfd7cc61e73439a2b1ac2d85faa7aaa988969ed (patch)
tree2efc202d627313811141f9d42bf24d80cccd41a8 /src/drivers/pc80
parent2a4f58ac1283e45d1f0cc6102a319b6d442a888d (diff)
downloadcoreboot-3bfd7cc61e73439a2b1ac2d85faa7aaa988969ed.tar.xz
drivers/pc80: Rework normal / fallback selector code
Per IRC and Gerrit discussion, the normal / fallback selector code is a rather weak spot in coreboot, and did not function correctly for certain use cases. Rework the selector to more clearly indicate proper operation, and also remove dead code. Also tentatively abandon use of RTC bit 385; a follow-up patch will remove said bit from all affected mainboards. The correct operation of the fallback code selector approximates that of a power line recloser, with a user option to attempt normal boot that can be cleared by firmware, but never set by firmware. Additionally, if cleared by user, the fallback path should always be used on the next reboot. Change-Id: I753ae9f0710c524875a85354ac2547df0c305569 Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/12289 Reviewed-by: Nico Huber <nico.h@gmx.de> Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/drivers/pc80')
-rw-r--r--src/drivers/pc80/mc146818rtc_early.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/src/drivers/pc80/mc146818rtc_early.c b/src/drivers/pc80/mc146818rtc_early.c
index 421af2f92f..268cfc2fe6 100644
--- a/src/drivers/pc80/mc146818rtc_early.c
+++ b/src/drivers/pc80/mc146818rtc_early.c
@@ -41,12 +41,24 @@ static int cmos_chksum_valid(void)
#endif
}
+static inline __attribute__((unused)) int boot_count(uint8_t rtc_byte)
+{
+ return rtc_byte >> 4;
+}
-static inline __attribute__((unused)) int last_boot_normal(void)
+static inline __attribute__((unused)) uint8_t increment_boot_count(uint8_t rtc_byte)
{
- unsigned char byte;
- byte = cmos_read(RTC_BOOT_BYTE);
- return (byte & (1 << 1));
+ return rtc_byte + (1 << 4);
+}
+
+static inline __attribute__((unused)) uint8_t boot_set_fallback(uint8_t rtc_byte)
+{
+ return rtc_byte & ~RTC_BOOT_NORMAL;
+}
+
+static inline __attribute__((unused)) int boot_use_normal(uint8_t rtc_byte)
+{
+ return rtc_byte & RTC_BOOT_NORMAL;
}
static inline __attribute__((unused)) int do_normal_boot(void)
@@ -54,42 +66,32 @@ static inline __attribute__((unused)) int do_normal_boot(void)
unsigned char byte;
if (cmos_error() || !cmos_chksum_valid()) {
- /* There are no impossible values, no checksums so just
- * trust whatever value we have in the the cmos,
- * but clear the fallback bit.
+ /* Invalid CMOS checksum detected!
+ * Force fallback boot...
*/
byte = cmos_read(RTC_BOOT_BYTE);
- byte &= 0x0c;
- byte |= CONFIG_MAX_REBOOT_CNT << 4;
+ byte &= boot_set_fallback(byte) & 0x0f;
+ byte |= 0xf << 4;
cmos_write(byte, RTC_BOOT_BYTE);
}
/* The RTC_BOOT_BYTE is now o.k. see where to go. */
byte = cmos_read(RTC_BOOT_BYTE);
- if (!IS_ENABLED(CONFIG_SKIP_MAX_REBOOT_CNT_CLEAR))
- /* Are we in normal mode? */
- if (byte & 1)
- byte &= 0x0f; /* yes, clear the boot count */
-
- /* Properly set the last boot flag */
- byte &= 0xfc;
- if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
- byte |= (1<<1);
- }
-
- /* Are we already at the max count? */
- if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
- byte += 1 << 4; /* No, add 1 to the count */
- }
- else {
- byte &= 0xfc; /* Yes, put in fallback mode */
+ /* Are we attempting to boot normally? */
+ if (boot_use_normal(byte)) {
+ /* Are we already at the max count? */
+ if (boot_count(byte) < CONFIG_MAX_REBOOT_CNT)
+ byte = increment_boot_count(byte);
+ else
+ byte = boot_set_fallback(byte);
}
/* Save the boot byte */
cmos_write(byte, RTC_BOOT_BYTE);
- return (byte & (1<<1));
+ /* Return selected code path for this boot attempt */
+ return boot_use_normal(byte);
}
unsigned read_option_lowlevel(unsigned start, unsigned size, unsigned def)