Denis Carikli (GNUtoo@no-log.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3549
-gerrit
commit 232ff06c084858ce33e170905e1f7c1bacb1c669 Author: Denis 'GNUtoo' Carikli GNUtoo@no-log.org Date: Fri Jun 21 23:32:19 2013 +0200
Add an alternative bootblock implementation.
Change-Id: I1109c49c7c84461bb056b36ee5d07391c2392176 Signed-off-by: Denis 'GNUtoo' Carikli GNUtoo@no-log.org --- src/arch/x86/Kconfig | 13 ++++++ src/arch/x86/include/arch/cbfs.h | 8 ++++ src/arch/x86/init/bootblock_failboot.c | 53 ++++++++++++++++++++++ src/cpu/amd/agesa/cache_as_ram.inc | 9 +++- src/cpu/amd/car/cache_as_ram.inc | 9 +++- src/cpu/amd/geode_gx2/cache_as_ram.inc | 11 +++++ src/cpu/amd/geode_lx/cache_as_ram.inc | 11 +++++ src/cpu/intel/car/cache_as_ram.inc | 9 ++++ src/cpu/intel/car/cache_as_ram_ht.inc | 12 +++++ src/cpu/intel/haswell/cache_as_ram.inc | 11 +++++ src/cpu/intel/model_2065x/cache_as_ram.inc | 9 ++++ src/cpu/intel/model_206ax/cache_as_ram.inc | 9 ++++ src/cpu/intel/model_6ex/cache_as_ram.inc | 9 ++++ src/cpu/via/car/cache_as_ram.inc | 8 ++++ src/cpu/x86/16bit/entry16.inc | 8 ++++ src/cpu/x86/32bit/entry32.inc | 10 +++- src/cpu/x86/fpu_enable.inc | 9 +++- src/cpu/x86/sse_enable.inc | 9 +++- src/drivers/pc80/mc146818rtc_early.c | 11 +++++ .../emulation/qemu-i440fx/cache_as_ram.inc | 10 ++++ src/northbridge/intel/i5000/halt_second_bsp.S | 9 ++++ 21 files changed, 241 insertions(+), 6 deletions(-)
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/include/arch/cbfs.h b/src/arch/x86/include/arch/cbfs.h index 8a61d6e..b6df10b 100644 --- a/src/arch/x86/include/arch/cbfs.h +++ b/src/arch/x86/include/arch/cbfs.h @@ -45,4 +45,12 @@ static inline void call(unsigned long addr, unsigned long bist) { asm volatile ("jmp *%0\n\t" : : "r" (addr), "a" (bist)); } + +#if CONFIG_X86_BOOTBLOCK_FAILBOOT +static inline void call_cmos_stage(unsigned long addr, unsigned long bist, int normal) +{ + asm volatile ("jmp *%0\n\t" : : "r" (addr), "a" (bist),"b" (normal)); +} +#endif + #endif diff --git a/src/arch/x86/init/bootblock_failboot.c b/src/arch/x86/init/bootblock_failboot.c new file mode 100644 index 0000000..17e5ee3 --- /dev/null +++ b/src/arch/x86/init/bootblock_failboot.c @@ -0,0 +1,53 @@ +#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; + const char *default_filenames = "normal/romstage\0fallback/romstage"; + + if (boot_cpu()) { + bootblock_mainboard_init(); + +#if CONFIG_USE_OPTION_TABLE + sanitize_cmos(); +#endif + boot_mode = last_boot_normal(); + } else { + + /* Questionable single byte read from CMOS. + * Do not add any other CMOS access in the + * bootblock for AP CPUs. + */ + boot_mode = last_boot_normal(); + } + + 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)); + + /* reset nvram to fallback */ + set_boot_fallback(); + + if (entry) call_cmos_stage(entry, bist, boot_mode); + + /* run fallback if normal can't be found */ + entry = findstage(get_fallback(normal_candidate)); + if (entry) call_cmos_stage(entry, bist, boot_mode); + + /* duh. we're stuck */ + asm volatile ("1:\n\thlt\n\tjmp 1b\n\t"); +} diff --git a/src/cpu/amd/agesa/cache_as_ram.inc b/src/cpu/amd/agesa/cache_as_ram.inc index c645a1e..780add6 100755 --- a/src/cpu/amd/agesa/cache_as_ram.inc +++ b/src/cpu/amd/agesa/cache_as_ram.inc @@ -57,7 +57,10 @@ cache_as_ram_setup:
/* Save the BIST result */ cvtsi2sd %ebp, %xmm0 - +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Not implemented for AGESA" +#endif /* for normal part %ebx already contain cpu_init_detected from fallback call */
/* Save the cpu_init_detected */ @@ -70,6 +73,10 @@ cache_as_ram_setup:
/* Restore the BIST result */ cvtsd2si %xmm0, %edx +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Not implemented for AGESA" +#endif
/* Restore the cpu_init_detected */ cvtsd2si %xmm1, %ebx diff --git a/src/cpu/amd/car/cache_as_ram.inc b/src/cpu/amd/car/cache_as_ram.inc index 7070cf9..c8d6177 100644 --- a/src/cpu/amd/car/cache_as_ram.inc +++ b/src/cpu/amd/car/cache_as_ram.inc @@ -45,6 +45,10 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %esp +#endif
/* * For normal part %ebx already contain cpu_init_detected @@ -408,7 +412,10 @@ CAR_FAM10_ap_out:
/* Restore the BIST result. */ movl %ebp, %eax - +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif /* We need to set EBP? No need. */ movl %esp, %ebp pushl %ebx /* Init detected. */ diff --git a/src/cpu/amd/geode_gx2/cache_as_ram.inc b/src/cpu/amd/geode_gx2/cache_as_ram.inc index 6a107fe..28c3f16 100644 --- a/src/cpu/amd/geode_gx2/cache_as_ram.inc +++ b/src/cpu/amd/geode_gx2/cache_as_ram.inc @@ -38,6 +38,11 @@ /** /***************************************************************************/ DCacheSetup: +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers for Geode GX2" + //movl %ebx, ??? +#endif /* Save the BIST result */ movl %eax, %ebx
@@ -154,6 +159,12 @@ DCacheSetupGood:
/* Restore the BIST result */ movl %ebx, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers for Geode GX2" + //movl ??? , %ebx ??? +#endif + movl %esp, %ebp pushl %eax
diff --git a/src/cpu/amd/geode_lx/cache_as_ram.inc b/src/cpu/amd/geode_lx/cache_as_ram.inc index 45fd166..16a19e0 100644 --- a/src/cpu/amd/geode_lx/cache_as_ram.inc +++ b/src/cpu/amd/geode_lx/cache_as_ram.inc @@ -35,6 +35,11 @@ /** /***************************************************************************/ DCacheSetup: +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers available for Geode LX" + //movl %ebx, %??? +#endif /* Save the BIST result */ movl %eax, %ebx
@@ -180,6 +185,12 @@ DCacheSetupGood:
/* Restore the BIST result */ movl %ebx, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers available for Geode LX" + //movl ??? , %ebx ??? +#endif + movl %esp, %ebp pushl %eax
diff --git a/src/cpu/intel/car/cache_as_ram.inc b/src/cpu/intel/car/cache_as_ram.inc index 1ea50b8..a3a9c29 100644 --- a/src/cpu/intel/car/cache_as_ram.inc +++ b/src/cpu/intel/car/cache_as_ram.inc @@ -32,6 +32,10 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %ebp +#endif
CacheAsRam: /* Check whether the processor has HT capability. */ @@ -319,10 +323,15 @@ clear_fixed_var_mtrr_out: lout: /* Restore the BIST result. */ movl %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif
/* We need to set EBP? No need. */ movl %esp, %ebp pushl %eax /* BIST */ + // pushl %ebx /* nvram's boot_option */ ??? No ebp used after that... call main
/* We don't need CAR from now on. */ diff --git a/src/cpu/intel/car/cache_as_ram_ht.inc b/src/cpu/intel/car/cache_as_ram_ht.inc index 8a845e9..954114f 100644 --- a/src/cpu/intel/car/cache_as_ram_ht.inc +++ b/src/cpu/intel/car/cache_as_ram_ht.inc @@ -35,6 +35,12 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers available in src/cpu/intel/car/cache_as_ram_ht.inc" + //movl %ebx, %??? /* %esp and %ebx are used later... */ +#endif +
cache_as_ram: post_code(0x20) @@ -343,6 +349,12 @@ no_msr_11e:
/* Restore the BIST result. */ movl %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers for Geode src/cpu/intel/car/cache_as_ram_ht.inc" + //movl ??? , %ebx ??? +#endif + movl %esp, %ebp pushl %eax
diff --git a/src/cpu/intel/haswell/cache_as_ram.inc b/src/cpu/intel/haswell/cache_as_ram.inc index 8601f46..7688a50 100644 --- a/src/cpu/intel/haswell/cache_as_ram.inc +++ b/src/cpu/intel/haswell/cache_as_ram.inc @@ -43,6 +43,11 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers available for haswell" + //movl %ebx, ??? /* %esp and %ebx are used later... */ +#endif
cache_as_ram: post_code(0x20) @@ -170,6 +175,12 @@ clear_mtrrs: andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax movl %eax, %cr0
+#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + #error "CONFIG_X86_BOOTBLOCK_FAILBOOT Fixme: Not enough registers available for haswell" + //movl ??? , %ebx ??? +#endif + /* Setup the stack. */ movl $(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE), %eax movl %eax, %esp diff --git a/src/cpu/intel/model_2065x/cache_as_ram.inc b/src/cpu/intel/model_2065x/cache_as_ram.inc index db0eaae..2893ea7 100644 --- a/src/cpu/intel/model_2065x/cache_as_ram.inc +++ b/src/cpu/intel/model_2065x/cache_as_ram.inc @@ -38,6 +38,11 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + /* Nothing to do, since %esp is used and %ebx not */ + /* Do not clobber %ebx */ +#endif
cache_as_ram: post_code(0x20) @@ -174,6 +179,10 @@ clear_mtrrs: movl %ebp, %eax movl %esp, %ebp pushl %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + /* should I push %ebx in the stack? */ +#endif
before_romstage: post_code(0x29) diff --git a/src/cpu/intel/model_206ax/cache_as_ram.inc b/src/cpu/intel/model_206ax/cache_as_ram.inc index 2652cb7..d9fb482 100644 --- a/src/cpu/intel/model_206ax/cache_as_ram.inc +++ b/src/cpu/intel/model_206ax/cache_as_ram.inc @@ -38,6 +38,11 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + /* Nothing to do, since %esp is used and %ebx not */ + /* Do not clobber %ebx */ +#endif
cache_as_ram: post_code(0x20) @@ -174,6 +179,10 @@ clear_mtrrs: movl %ebp, %eax movl %esp, %ebp pushl %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + /* should I push %ebx in the stack? */ +#endif
before_romstage: post_code(0x29) diff --git a/src/cpu/intel/model_6ex/cache_as_ram.inc b/src/cpu/intel/model_6ex/cache_as_ram.inc index 50fab35..ed25ef8 100644 --- a/src/cpu/intel/model_6ex/cache_as_ram.inc +++ b/src/cpu/intel/model_6ex/cache_as_ram.inc @@ -30,6 +30,11 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + /* Nothing to do, since %esp is used and %ebx not */ + /* Do not clobber %ebx */ +#endif
cache_as_ram: post_code(0x20) @@ -138,6 +143,10 @@ clear_mtrrs: movl %ebp, %eax movl %esp, %ebp pushl %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + /* should I push %ebx in the stack? */ +#endif
post_code(0x23)
diff --git a/src/cpu/via/car/cache_as_ram.inc b/src/cpu/via/car/cache_as_ram.inc index 17b4b83..eea0b93 100644 --- a/src/cpu/via/car/cache_as_ram.inc +++ b/src/cpu/via/car/cache_as_ram.inc @@ -35,6 +35,10 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %esp +#endif
CacheAsRam:
@@ -204,6 +208,10 @@ testok:
/* Restore the BIST result. */ movl %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif
/* We need to set EBP? No need. */ movl %esp, %ebp diff --git a/src/cpu/x86/16bit/entry16.inc b/src/cpu/x86/16bit/entry16.inc index e4613bf..b7f90c2 100644 --- a/src/cpu/x86/16bit/entry16.inc +++ b/src/cpu/x86/16bit/entry16.inc @@ -36,6 +36,10 @@ _start: cli /* Save the BIST result */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %esp +#endif
post_code(POST_RESET_VECTOR_CORRECT)
@@ -114,6 +118,10 @@ _start:
/* Restore BIST to %eax */ movl %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif
/* Now that we are in protected mode jump to a 32 bit code segment. */ data32 ljmp $ROM_CODE_SEG, $__protected_start diff --git a/src/cpu/x86/32bit/entry32.inc b/src/cpu/x86/32bit/entry32.inc index f74e1b8..9299316 100644 --- a/src/cpu/x86/32bit/entry32.inc +++ b/src/cpu/x86/32bit/entry32.inc @@ -51,7 +51,10 @@ protected_start: __protected_start: /* Save the BIST value */ movl %eax, %ebp - +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %esp +#endif post_code(POST_ENTER_PROTECTED_MODE)
movw $ROM_DATA_SEG, %ax @@ -63,4 +66,7 @@ __protected_start:
/* Restore the BIST value to %eax */ movl %ebp, %eax - +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif diff --git a/src/cpu/x86/fpu_enable.inc b/src/cpu/x86/fpu_enable.inc index c08e8a0..2d43b34 100644 --- a/src/cpu/x86/fpu_enable.inc +++ b/src/cpu/x86/fpu_enable.inc @@ -20,7 +20,10 @@ __fpu_start: /* Preserve BIST. */ movl %eax, %ebp - +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %esp +#endif /* * Clear the CR0[2] bit (the "Emulation" flag, EM). * @@ -37,3 +40,7 @@ __fpu_start:
/* Restore BIST. */ movl %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif diff --git a/src/cpu/x86/sse_enable.inc b/src/cpu/x86/sse_enable.inc index 09dea02..1e1ed49 100644 --- a/src/cpu/x86/sse_enable.inc +++ b/src/cpu/x86/sse_enable.inc @@ -19,6 +19,10 @@
/* Preserve BIST. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + movl %ebx, %esp +#endif
/* Enable SSE instructions. */ movl %cr4, %eax @@ -27,4 +31,7 @@
/* Restore BIST. */ movl %ebp, %eax - +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + movl %esp, %ebx +#endif diff --git a/src/drivers/pc80/mc146818rtc_early.c b/src/drivers/pc80/mc146818rtc_early.c index 0652f27..df8215a 100644 --- a/src/drivers/pc80/mc146818rtc_early.c +++ b/src/drivers/pc80/mc146818rtc_early.c @@ -49,6 +49,17 @@ static inline int last_boot_normal(void) return (byte & (1 << 1)); }
+#if CONFIG_X86_BOOTBLOCK_FAILBOOT +static inline void set_boot_fallback(void) +{ + unsigned char byte; + byte = cmos_read(RTC_BOOT_BYTE); + /* set it back to Fallback */ + byte &= ~(1<<0); + cmos_write(byte, RTC_BOOT_BYTE); +} +#endif + static inline int do_normal_boot(void) { unsigned char byte; diff --git a/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc b/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc index 11ac91d..deb7b65 100644 --- a/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc +++ b/src/mainboard/emulation/qemu-i440fx/cache_as_ram.inc @@ -31,6 +31,11 @@
/* Save the BIST result. */ movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #warning "CONFIG_X86_BOOTBLOCK_FAILBOOT is used, the build may fail" + movl %ebx, %esp +#endif
cache_as_ram: post_code(0x20) @@ -49,6 +54,11 @@ cache_as_ram:
/* Restore the BIST result. */ movl %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + #warning "CONFIG_X86_BOOTBLOCK_FAILBOOT is used, the build may fail" + movl %esp, %ebx +#endif movl %esp, %ebp pushl %eax
diff --git a/src/northbridge/intel/i5000/halt_second_bsp.S b/src/northbridge/intel/i5000/halt_second_bsp.S index 041807e..f21e23d 100644 --- a/src/northbridge/intel/i5000/halt_second_bsp.S +++ b/src/northbridge/intel/i5000/halt_second_bsp.S @@ -1,6 +1,11 @@ /* Save BIST result */
movl %eax, %ebp +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Preserve the nvram's boot_option parameter */ + /* Nothing to do, since %ebx is not used */ + /* Do not clobber %ebx */ +#endif
/* check if SPAD0 is cleared. If yes, it means this was a hard reset */ movl $0x800080d0, %eax @@ -56,3 +61,7 @@ loop: hlt
/* Restore BIST */ mov %ebp, %eax +#if CONFIG_X86_BOOTBLOCK_FAILBOOT + /* Restore nvram's saved boot_option parameter */ + /* Nothing to do, since %ebx is not used */ +#endif