Kyösti Mälkki (kyosti.malkki@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/304
-gerrit
commit 586d9a5f5480080210a40b15b8833bf992e9d6e6 Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Thu Oct 27 17:04:39 2011 +0300
Add bootstrap to select loaded romstage
Just before loading romstage, read the console serial port pin (DCD). The level determines whether normal or fallback boots.
Change-Id: Ib8b6984ddd886cd21638880c6f43dd90d078c844 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- src/arch/x86/init/bootblock_normal.c | 9 ++++++- src/arch/x86/init/bootblock_simple.c | 16 +++++++++++- src/arch/x86/init/bootstrap_dcd.h | 41 ++++++++++++++++++++++++++++++++++ src/console/Kconfig | 9 +++++++ 4 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/src/arch/x86/init/bootblock_normal.c b/src/arch/x86/init/bootblock_normal.c index db9d0f9..f3f4e50 100644 --- a/src/arch/x86/init/bootblock_normal.c +++ b/src/arch/x86/init/bootblock_normal.c @@ -1,5 +1,6 @@ #include <bootblock_common.h> #include <pc80/mc146818rtc.h> +#include "bootstrap_dcd.h"
static void main(unsigned long bist) { @@ -14,7 +15,13 @@ static void main(unsigned long bist) #endif
unsigned long entry; - if (do_normal_boot()) + int boot_mode = do_normal_boot(); + +#if CONFIG_TTYS0_DCD_HOOK + /* high DCD overrides to fallback */ + boot_mode &= !early_dcd_hook(); +#endif + if (boot_mode) entry = findstage("normal/romstage"); else entry = findstage("fallback/romstage"); diff --git a/src/arch/x86/init/bootblock_simple.c b/src/arch/x86/init/bootblock_simple.c index 5d7c611..f5f3158 100644 --- a/src/arch/x86/init/bootblock_simple.c +++ b/src/arch/x86/init/bootblock_simple.c @@ -1,4 +1,5 @@ #include <bootblock_common.h> +#include "bootstrap_dcd.h"
static void main(unsigned long bist) { @@ -12,10 +13,21 @@ static void main(unsigned long bist) sanitize_cmos(); #endif
- const char* target1 = "fallback/romstage"; unsigned long entry; - entry = findstage(target1); + int boot_mode = 0; + +#if CONFIG_TTYS0_DCD_HOOK + /* DCD high selects normal */ + boot_mode = early_dcd_hook(); +#endif + if (boot_mode) + entry = findstage("normal/romstage"); + else + entry = findstage("fallback/romstage"); + if (entry) call(entry, bist); + + /* duh. we're stuck */ asm volatile ("1:\n\thlt\n\tjmp 1b\n\t"); }
diff --git a/src/arch/x86/init/bootstrap_dcd.h b/src/arch/x86/init/bootstrap_dcd.h new file mode 100644 index 0000000..956b116 --- /dev/null +++ b/src/arch/x86/init/bootstrap_dcd.h @@ -0,0 +1,41 @@ +#include <arch/io.h> +#include <device/pnp_def.h> +#include <arch/romcc_io.h> +#include <uart8250.h> + +/* grab from devicetree.cb ? */ +#define EARLY_SERIAL_DEV PNP_DEV(0x2e, 0x04) +#define EARLY_TTYS0_BASE 0x3f8 + +#if CONFIG_TTYS0_DCD_HOOK +static int early_dcd_hook(void) +{ + device_t dev = EARLY_SERIAL_DEV; + u16 port = dev >> 8; + u16 base; + u8 dcd, i; + + /* power-up uart, set base if not already set */ + outb(0x55, port); + pnp_set_logical_device(dev); + pnp_set_enable(dev, 0); + base = pnp_read_iobase(dev, PNP_IDX_IO0); + if (!base) { + base = EARLY_TTYS0_BASE; + pnp_set_iobase(dev, PNP_IDX_IO0, base); + } + pnp_set_enable(dev, 1); + outb(0xaa, port); + + /* assert DTR, so you can jump-wire DCD high */ + outb(UART_MCR_DTR, base + UART_MCR); + + /* just powered up.. better not to trust the first value */ + i = 0; + do { + dcd = !!(inb(base + UART_MSR) & UART_MSR_DCD); + } while (++i<10); + return dcd; +} +#endif + diff --git a/src/console/Kconfig b/src/console/Kconfig index 8382695..b1b2fc8 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -91,6 +91,15 @@ config TTYS0_LCS default 3 depends on CONSOLE_SERIAL8250 || CONSOLE_SERIAL8250MEM
+config TTYS0_DCD_HOOK + bool "DCD line is bootstrap to select romstage" + default n + depends on CONSOLE_SERIAL8250 + help + Status of DCD line on the selected serial debug console + port is read at boot-time, and is used to choose from + the two romstage prefixes. + # Use "select HAVE_USBDEBUG" on southbridges which have Debug Port code. config HAVE_USBDEBUG def_bool n