diff options
author | Patrick Georgi <patrick.georgi@secunet.com> | 2011-01-14 07:40:24 +0000 |
---|---|---|
committer | Patrick Georgi <patrick.georgi@coresystems.de> | 2011-01-14 07:40:24 +0000 |
commit | a865b17eff05fa3936494716401f6aa9a9ef6358 (patch) | |
tree | 3c0baa84f61c582638fd0c333a1020c5aa8519b0 /src/pc80 | |
parent | 4c8e269841bbdfd3325b8eb98a651a8b1df85399 (diff) |
Allow coreboot to initialize CMOS if checksum is invalid.
If a file "cmos.default", type "cmos default"(0xaa) is in CBFS,
a wrong checksum leads to coreboot rewriting the first 128 bytes
(except for clock data) with the data in cmos.default, then
reboots the system so every component of coreboot works with the
same set of values.
Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com>
Acked-by: Stefan Reinauer <stepan@coreboot.org>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6253 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/pc80')
-rw-r--r-- | src/pc80/Makefile.inc | 5 | ||||
-rw-r--r-- | src/pc80/mc146818rtc_early.c | 26 |
2 files changed, 31 insertions, 0 deletions
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 <pc80/mc146818rtc.h> #include <fallback.h> +#include <cbfs.h> #if CONFIG_USE_OPTION_TABLE #include "option_table.h" #endif @@ -11,11 +12,18 @@ #error "CONFIG_MAX_REBOOT_CNT too high" #endif +#include <console/loglevel.h> + +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. |