diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig index 28a65b61a2..aacc0982a6 100644 --- a/src/arch/x86/Kconfig +++ b/src/arch/x86/Kconfig @@ -91,6 +91,13 @@ config PC80_SYSTEM config BOOTBLOCK_NORTHBRIDGE_INIT string +config HAVE_CMOS_DEFAULT + def_bool n + +config CMOS_DEFAULT_FILE + string + depends on HAVE_CMOS_DEFAULT + config BOOTBLOCK_SOUTHBRIDGE_INIT string diff --git a/src/mainboard/getac/p470/cmos.layout b/src/mainboard/getac/p470/cmos.layout index 73ea031043..f86e479df5 100644 --- a/src/mainboard/getac/p470/cmos.layout +++ b/src/mainboard/getac/p470/cmos.layout @@ -92,7 +92,8 @@ entries # coreboot config options: bootloader 416 512 s 0 boot_devices 928 8 h 0 boot_default -#936 48 r 0 unused +936 1 e 8 cmos_defaults_loaded +#937 47 r 0 unused # coreboot config options: check sums 984 16 h 0 check_sum @@ -136,6 +137,8 @@ enumerations 7 0 Disable 7 1 Enable 7 2 Keep +8 0 No +8 1 Yes # ----------------------------------------------------------------- checksums diff --git a/src/mainboard/kontron/986lcd-m/cmos.layout b/src/mainboard/kontron/986lcd-m/cmos.layout index a61a9deabf..6f2647927e 100644 --- a/src/mainboard/kontron/986lcd-m/cmos.layout +++ b/src/mainboard/kontron/986lcd-m/cmos.layout @@ -90,7 +90,8 @@ entries # coreboot config options: bootloader 416 512 s 0 boot_devices 928 8 h 0 boot_default -#936 12 r 0 unused +936 1 e 11 cmos_defaults_loaded +#937 11 r 0 unused # coreboot config options: mainboard specific options 948 2 e 8 cpufan_cruise_control @@ -187,6 +188,8 @@ enumerations #10 13 69/156 #10 14 72/161 #10 15 75/167 +11 0 No +11 1 Yes # ----------------------------------------------------------------- checksums diff --git a/src/mainboard/roda/rk886ex/cmos.layout b/src/mainboard/roda/rk886ex/cmos.layout index 4dc9112061..475823d68e 100644 --- a/src/mainboard/roda/rk886ex/cmos.layout +++ b/src/mainboard/roda/rk886ex/cmos.layout @@ -92,7 +92,8 @@ entries # coreboot config options: bootloader 416 512 s 0 boot_devices 928 8 h 0 boot_default -#936 48 r 0 unused +936 1 e 8 cmos_defaults_loaded +#937 47 r 0 unused # coreboot config options: check sums 984 16 h 0 check_sum @@ -136,6 +137,8 @@ enumerations 7 0 Disable 7 1 Enable 7 2 Keep +8 0 No +8 1 Yes # ----------------------------------------------------------------- checksums diff --git a/src/pc80/Makefile.inc b/src/pc80/Makefile.inc index d32dfe985e..0dc78bb6d0 100644 --- a/src/pc80/Makefile.inc +++ b/src/pc80/Makefile.inc @@ -10,3 +10,8 @@ subdirs-y += vga $(obj)/pc80/mc146818rtc.ramstage.o : $(OPTION_TABLE_H) $(obj)/pc80/mc146818rtc_early.romstage.o : $(OPTION_TABLE_H) + +cbfs-files-$(CONFIG_HAVE_CMOS_DEFAULT) += $(CONFIG_CMOS_DEFAULT_FILE) +$(CONFIG_CMOS_DEFAULT_FILE)-name := cmos.default +$(CONFIG_CMOS_DEFAULT_FILE)-type := 0xaa + diff --git a/src/pc80/mc146818rtc_early.c b/src/pc80/mc146818rtc_early.c index d09d6b9df0..10de0bc54f 100644 --- a/src/pc80/mc146818rtc_early.c +++ b/src/pc80/mc146818rtc_early.c @@ -1,5 +1,6 @@ #include #include +#include #if CONFIG_USE_OPTION_TABLE #include "option_table.h" #endif @@ -11,11 +12,18 @@ #error "CONFIG_MAX_REBOOT_CNT too high" #endif +#include + +int do_printk(int msg_level, const char *fmt, ...) __attribute__((format(printf, 2, 3))); +#define printk_warning(fmt, arg...) do_printk(BIOS_WARNING ,fmt, ##arg) +#define printk_debug(fmt, arg...) do_printk(BIOS_DEBUG ,fmt, ##arg) + static int cmos_error(void) { unsigned char reg_d; /* See if the cmos error condition has been flagged */ reg_d = cmos_read(RTC_REG_D); + printk_debug("CMOS_REG_D(VRT): %x\n", reg_d & RTC_VRT); return (reg_d & RTC_VRT) == 0; } @@ -35,6 +43,7 @@ static int cmos_chksum_valid(void) old_sum = cmos_read(LB_CKS_LOC) << 8; old_sum |= cmos_read(LB_CKS_LOC+1); + printk_debug("CMOS checksum: old = %lx, new=%lx\n", old_sum, sum); return sum == old_sum; #else return 0; @@ -51,9 +60,26 @@ static inline int last_boot_normal(void) static inline int do_normal_boot(void) { + char *cmos_default = cbfs_find_file("cmos.default", 0xaa); unsigned char byte; + int i; if (cmos_error() || !cmos_chksum_valid()) { + if (cmos_default) { + printk_warning("WARNING - CMOS CORRUPTED. RESTORING DEFAULTS.\n"); + /* First 14 bytes are reserved for + RTC and ignored by nvramtool, too. + Only 128 bytes: 128+ requires cmos configuration and + contains only suspend-to-ram data, which isn't part + of the recovery procedure. */ + for (i = 14; i < 128; i++) { + cmos_write(cmos_default[i], i); + } + /* Now reboot to run with default cmos. */ + outb(0x06, 0xcf9); + for (;;) asm("hlt"); /* Wait for reset! */ + } + /* There are no impossible values, no checksums so just * trust whatever value we have in the the cmos, * but clear the fallback bit. diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h index 0d33710229..6fb9edd68c 100644 --- a/util/cbfstool/cbfs.h +++ b/util/cbfstool/cbfs.h @@ -76,6 +76,7 @@ struct cbfs_payload { #define CBFS_COMPONENT_VSA 0x51 #define CBFS_COMPONENT_MBI 0x52 #define CBFS_COMPONENT_MICROCODE 0x53 +#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa /* The deleted type is chosen to be a value * that can be written in a FLASH from all other diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c index a42585b776..0fb02004d4 100644 --- a/util/cbfstool/common.c +++ b/util/cbfstool/common.c @@ -145,6 +145,7 @@ struct filetypes_t { {CBFS_COMPONENT_VSA, "vsa"}, {CBFS_COMPONENT_MBI, "mbi"}, {CBFS_COMPONENT_MICROCODE, "microcode"}, + {CBFS_COMPONENT_CMOS_DEFAULT, "cmos default"}, {CBFS_COMPONENT_DELETED, "deleted"}, {CBFS_COMPONENT_NULL, "null"} };