Denis Carikli (GNUtoo(a)no-log.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3549
-gerrit
commit 93fb53fd2340909ab49c25ae9a2a2183c2a0d7dc
Author: Denis 'GNUtoo' Carikli <GNUtoo(a)no-log.org>
Date: Fri Jun 21 23:32:19 2013 +0200
Add a new and safer bootblock implementation.
The drawback is that it requires cooperation
from something that is run after coreboot
(like the OS or the payload).
To understand how to use it, refer to the
Kconfig help of that option.
Thanks a lot to kmalkki on #coreboot Freenode IRC
channel for pointers on how to simplify the implementation.
Change-Id: I1109c49c7c84461bb056b36ee5d07391c2392176
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo(a)no-log.org>
---
src/arch/x86/Kconfig | 13 ++++++++++
src/arch/x86/init/bootblock_failboot.c | 47 ++++++++++++++++++++++++++++++++++
src/drivers/pc80/mc146818rtc_early.c | 28 ++++++++++++++++++++
3 files changed, 88 insertions(+)
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig
index 69cdc8a..721a487 100644
--- a/src/arch/x86/Kconfig
+++ b/src/arch/x86/Kconfig
@@ -54,12 +54,25 @@ config X86_BOOTBLOCK_SIMPLE
config X86_BOOTBLOCK_NORMAL
bool "Switch to normal if CMOS says so"
+config X86_BOOTBLOCK_FAILBOOT
+ bool "Switch to Fallback if it fails to boot"
+ help
+ Switch to Fallback after failing to boot.
+ Coreboot will reset boot_option to Fallback
+ as early as possible, If the user has
+ a Fallback and a Normal image in cbfs,
+ and wants to boot on the Normal image,
+ he must reset the boot_option to Normal
+ after successfully booting (like trough the OS
+ boot scripts that would run something like:
+ "nvramtool -w boot_option=Normal".
endchoice
config BOOTBLOCK_SOURCE
string
default "bootblock_simple.c" if X86_BOOTBLOCK_SIMPLE
default "bootblock_normal.c" if X86_BOOTBLOCK_NORMAL
+ default "bootblock_failboot.c" if X86_BOOTBLOCK_FAILBOOT
config UPDATE_IMAGE
bool "Update existing coreboot.rom image"
diff --git a/src/arch/x86/init/bootblock_failboot.c b/src/arch/x86/init/bootblock_failboot.c
new file mode 100644
index 0000000..96c1449
--- /dev/null
+++ b/src/arch/x86/init/bootblock_failboot.c
@@ -0,0 +1,47 @@
+#include <bootblock_common.h>
+#include <pc80/mc146818rtc.h>
+
+int boot_mode = 0;
+
+static const char *get_fallback(const char *stagelist) {
+ while (*stagelist) stagelist++;
+ return ++stagelist;
+}
+
+static void main(unsigned long bist)
+{
+ unsigned long entry;
+ const char *default_filenames = "normal/romstage\0fallback/romstage";
+
+ /* I hope that the BSP CPU is started first
+ * and reach this point first... */
+ if (boot_cpu()) {
+ bootblock_mainboard_init();
+
+#if CONFIG_USE_OPTION_TABLE
+ sanitize_cmos();
+#endif
+ boot_mode = get_and_reset_boot();
+ }
+
+ char *filenames = (char *)walkcbfs("coreboot-stages");
+ if (!filenames) {
+ filenames = default_filenames;
+ }
+ char *normal_candidate = filenames;
+
+ if (boot_mode)
+ entry = findstage(normal_candidate);
+ else
+ entry = findstage(get_fallback(normal_candidate));
+
+ if (entry) call(entry, bist);
+
+ /* run fallback if normal can't be found */
+ entry = findstage(get_fallback(normal_candidate));
+ if (entry) call(entry, bist);
+
+ /* duh. we're stuck */
+ asm volatile ("1:\n\thlt\n\tjmp 1b\n\t");
+}
+
diff --git a/src/drivers/pc80/mc146818rtc_early.c b/src/drivers/pc80/mc146818rtc_early.c
index 0652f27..019e05e 100644
--- a/src/drivers/pc80/mc146818rtc_early.c
+++ b/src/drivers/pc80/mc146818rtc_early.c
@@ -49,6 +49,34 @@ static inline int last_boot_normal(void)
return (byte & (1 << 1));
}
+#if CONFIG_X86_BOOTBLOCK_FAILBOOT
+static inline int get_and_reset_boot(void)
+{
+ unsigned char old_byte, write_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.
+ */
+ write_byte = cmos_read(RTC_BOOT_BYTE);
+ write_byte &= 0x0c;
+ cmos_write(write_byte, RTC_BOOT_BYTE);
+ }
+
+ /* The RTC_BOOT_BYTE is now o.k. see where to go. */
+ write_byte = old_byte = cmos_read(RTC_BOOT_BYTE);
+
+ /* Reset boot_option to Fallback */
+ write_byte &= ~(1<<0);
+
+ /* Save the boot byte */
+ cmos_write(write_byte, RTC_BOOT_BYTE);
+
+ return (old_byte & (1<<0));
+}
+#endif
+
static inline int do_normal_boot(void)
{
unsigned char byte;
Denis Carikli (GNUtoo(a)no-log.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3549
-gerrit
commit f0e74c9da36fca760d7355eca064c382102e34cb
Author: Denis 'GNUtoo' Carikli <GNUtoo(a)no-log.org>
Date: Fri Jun 21 23:32:19 2013 +0200
Add a new and safer bootblock implementation.
The drawback is that it requires cooperation
from something that is run after coreboot
(like the OS or the payload).
To understand how to use it, refer to the
Kconfig help of that option.
Thanks a lot to kmalkki on #coreboot Freenode IRC
channel for pointers on how to simplify the implementation.
Change-Id: I1109c49c7c84461bb056b36ee5d07391c2392176
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo(a)no-log.org>
---
src/arch/x86/Kconfig | 13 ++++++++++
src/arch/x86/init/bootblock_failboot.c | 46 ++++++++++++++++++++++++++++++++++
src/drivers/pc80/mc146818rtc_early.c | 28 +++++++++++++++++++++
3 files changed, 87 insertions(+)
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig
index 69cdc8a..721a487 100644
--- a/src/arch/x86/Kconfig
+++ b/src/arch/x86/Kconfig
@@ -54,12 +54,25 @@ config X86_BOOTBLOCK_SIMPLE
config X86_BOOTBLOCK_NORMAL
bool "Switch to normal if CMOS says so"
+config X86_BOOTBLOCK_FAILBOOT
+ bool "Switch to Fallback if it fails to boot"
+ help
+ Switch to Fallback after failing to boot.
+ Coreboot will reset boot_option to Fallback
+ as early as possible, If the user has
+ a Fallback and a Normal image in cbfs,
+ and wants to boot on the Normal image,
+ he must reset the boot_option to Normal
+ after successfully booting (like trough the OS
+ boot scripts that would run something like:
+ "nvramtool -w boot_option=Normal".
endchoice
config BOOTBLOCK_SOURCE
string
default "bootblock_simple.c" if X86_BOOTBLOCK_SIMPLE
default "bootblock_normal.c" if X86_BOOTBLOCK_NORMAL
+ default "bootblock_failboot.c" if X86_BOOTBLOCK_FAILBOOT
config UPDATE_IMAGE
bool "Update existing coreboot.rom image"
diff --git a/src/arch/x86/init/bootblock_failboot.c b/src/arch/x86/init/bootblock_failboot.c
new file mode 100644
index 0000000..85d6339
--- /dev/null
+++ b/src/arch/x86/init/bootblock_failboot.c
@@ -0,0 +1,46 @@
+#include <bootblock_common.h>
+#include <pc80/mc146818rtc.h>
+
+static const char *get_fallback(const char *stagelist) {
+ while (*stagelist) stagelist++;
+ return ++stagelist;
+}
+
+static void main(unsigned long bist)
+{
+ unsigned long entry;
+ int boot_mode = 0;
+ const char *default_filenames = "normal/romstage\0fallback/romstage";
+
+ /* I hope that the BSP CPU is started first
+ * and reach this point first... */
+ if (boot_cpu()) {
+ bootblock_mainboard_init();
+
+#if CONFIG_USE_OPTION_TABLE
+ sanitize_cmos();
+#endif
+ boot_mode = get_and_reset_boot();
+ }
+
+ char *filenames = (char *)walkcbfs("coreboot-stages");
+ if (!filenames) {
+ filenames = default_filenames;
+ }
+ char *normal_candidate = filenames;
+
+ if (boot_mode)
+ entry = findstage(normal_candidate);
+ else
+ entry = findstage(get_fallback(normal_candidate));
+
+ if (entry) call(entry, bist);
+
+ /* run fallback if normal can't be found */
+ entry = findstage(get_fallback(normal_candidate));
+ if (entry) call(entry, bist);
+
+ /* duh. we're stuck */
+ asm volatile ("1:\n\thlt\n\tjmp 1b\n\t");
+}
+
diff --git a/src/drivers/pc80/mc146818rtc_early.c b/src/drivers/pc80/mc146818rtc_early.c
index 0652f27..019e05e 100644
--- a/src/drivers/pc80/mc146818rtc_early.c
+++ b/src/drivers/pc80/mc146818rtc_early.c
@@ -49,6 +49,34 @@ static inline int last_boot_normal(void)
return (byte & (1 << 1));
}
+#if CONFIG_X86_BOOTBLOCK_FAILBOOT
+static inline int get_and_reset_boot(void)
+{
+ unsigned char old_byte, write_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.
+ */
+ write_byte = cmos_read(RTC_BOOT_BYTE);
+ write_byte &= 0x0c;
+ cmos_write(write_byte, RTC_BOOT_BYTE);
+ }
+
+ /* The RTC_BOOT_BYTE is now o.k. see where to go. */
+ write_byte = old_byte = cmos_read(RTC_BOOT_BYTE);
+
+ /* Reset boot_option to Fallback */
+ write_byte &= ~(1<<0);
+
+ /* Save the boot byte */
+ cmos_write(write_byte, RTC_BOOT_BYTE);
+
+ return (old_byte & (1<<0));
+}
+#endif
+
static inline int do_normal_boot(void)
{
unsigned char byte;