[coreboot-gerrit] Patch set updated for coreboot: drivers/pc80: Ensure recovery mode always boots fallback image

Timothy Pearson (tpearson@raptorengineeringinc.com) gerrit at coreboot.org
Mon Nov 2 09:21:42 CET 2015


Timothy Pearson (tpearson at raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/12289

-gerrit

commit 69a98d3f1aafe61ee49b2a2c689a2fd5d2836994
Author: Timothy Pearson <tpearson at raptorengineeringinc.com>
Date:   Sun Nov 1 02:13:17 2015 -0600

    drivers/pc80: Ensure recovery mode always boots fallback image
    
    The current fallback / failed boot count checks only look at the
    value of last_boot when determining whether to execute the
    normal or fallback image.  Furthermore, the normal boot bit is
    unconditionally set if the failed boot count has not exceeded
    its threshold, thereby overriding a request from the user to
    boot into fallback mode if the user does not also set the failed
    boot count above the failure threshold.
    
    Only check the failed boot count if the normal boot bit is set
    in nvram.
    
    NOTE: The existing code did not function as intended when used
    with recovery jumpers or nvramtool.  Even when the
    user set a recovery jumper or used nvramtool to set the
    next boot attempt to Fallback, the bootblock would execute
    the normal code if the failed boot count was below threshold.
    The only way to recover from this situation was to forcibly
    power off and on the board repeatedly until the failed boot
    count rose high enough, or to directly reflash the ROM.
    
    Note that clearing the CMOS actually had the opposite effect
    from what was intended, as it reset the failed boot count and
    set the normal boot bit.
    
    Change-Id: I753ae9f0710c524875a85354ac2547df0c305569
    Signed-off-by: Timothy Pearson <tpearson at raptorengineeringinc.com>
---
 src/drivers/pc80/mc146818rtc_early.c | 53 +++++++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 16 deletions(-)

diff --git a/src/drivers/pc80/mc146818rtc_early.c b/src/drivers/pc80/mc146818rtc_early.c
index 421af2f..1a45527 100644
--- a/src/drivers/pc80/mc146818rtc_early.c
+++ b/src/drivers/pc80/mc146818rtc_early.c
@@ -12,6 +12,9 @@
 #error "CONFIG_MAX_REBOOT_CNT too high"
 #endif
 
+#define RTC_BOOT_TRY_NORMAL 0x1
+#define RTC_BOOT_LAST_WAS_NORMAL_AND_REACHED_PAYLOAD 0x2
+
 static int cmos_error(void)
 {
 	unsigned char reg_d;
@@ -46,7 +49,7 @@ static inline __attribute__((unused)) int last_boot_normal(void)
 {
 	unsigned char byte;
 	byte = cmos_read(RTC_BOOT_BYTE);
-	return (byte & (1 << 1));
+	return (byte & RTC_BOOT_LAST_WAS_NORMAL_AND_REACHED_PAYLOAD);
 }
 
 static inline __attribute__((unused)) int do_normal_boot(void)
@@ -67,29 +70,47 @@ static inline __attribute__((unused)) int do_normal_boot(void)
 	/* The RTC_BOOT_BYTE is now o.k. see where to go. */
 	byte = cmos_read(RTC_BOOT_BYTE);
 
+	/* If booting past the bootblock is all that is required
+	 * to reset the failed boot checks, then clear the boot
+	 * count.  This code must execute before any of the boot
+	 * count checks below to function correctly.
+	 */
 	if (!IS_ENABLED(CONFIG_SKIP_MAX_REBOOT_CNT_CLEAR))
-		/* Are we in normal mode? */
-		if (byte & 1)
+		/* Are we attempting to boot normally? */
+		if (byte & RTC_BOOT_TRY_NORMAL)
 			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 (byte & RTC_BOOT_TRY_NORMAL) {
+		/* Properly set the last boot flag */
+		byte &= 0xfc;
+		if ((byte >> 4) < CONFIG_MAX_REBOOT_CNT) {
+			byte |= RTC_BOOT_LAST_WAS_NORMAL_AND_REACHED_PAYLOAD;
+		}
+
+		/* 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 */
+		}
 	}
 
 	/* Save the boot byte */
 	cmos_write(byte, RTC_BOOT_BYTE);
 
-	return (byte & (1<<1));
+	/* Return selected code path for this boot attempt
+	 * If a boot path was selected and we successfully reach
+	 * the payload, the last boot state bit will indicate
+	 * which code path was taken.
+	 *
+	 * In other words, RTC_BOOT_LAST_WAS_NORMAL_AND_REACHED_PAYLOAD
+	 * has final and absolute say on which code path to take.
+	 * RTC_BOOT_TRY_NORMAL is only a request to try normal boot if
+	 * possible (i.e. the payload can be reached via normal boot).
+	 */
+	return (byte & RTC_BOOT_LAST_WAS_NORMAL_AND_REACHED_PAYLOAD);
 }
 
 unsigned read_option_lowlevel(unsigned start, unsigned size, unsigned def)



More information about the coreboot-gerrit mailing list