Author: oxygene Date: Fri Jan 14 08:40:24 2011 New Revision: 6253 URL: https://tracker.coreboot.org/trac/coreboot/changeset/6253
Log: 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
Modified: trunk/src/arch/x86/Kconfig trunk/src/mainboard/getac/p470/cmos.layout trunk/src/mainboard/kontron/986lcd-m/cmos.layout trunk/src/mainboard/roda/rk886ex/cmos.layout trunk/src/pc80/Makefile.inc trunk/src/pc80/mc146818rtc_early.c trunk/util/cbfstool/cbfs.h trunk/util/cbfstool/common.c
Modified: trunk/src/arch/x86/Kconfig ============================================================================== --- trunk/src/arch/x86/Kconfig Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/src/arch/x86/Kconfig Fri Jan 14 08:40:24 2011 (r6253) @@ -91,6 +91,13 @@ 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
Modified: trunk/src/mainboard/getac/p470/cmos.layout ============================================================================== --- trunk/src/mainboard/getac/p470/cmos.layout Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/src/mainboard/getac/p470/cmos.layout Fri Jan 14 08:40:24 2011 (r6253) @@ -92,7 +92,8 @@ # 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 @@ 7 0 Disable 7 1 Enable 7 2 Keep +8 0 No +8 1 Yes
# ----------------------------------------------------------------- checksums
Modified: trunk/src/mainboard/kontron/986lcd-m/cmos.layout ============================================================================== --- trunk/src/mainboard/kontron/986lcd-m/cmos.layout Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/src/mainboard/kontron/986lcd-m/cmos.layout Fri Jan 14 08:40:24 2011 (r6253) @@ -90,7 +90,8 @@ # 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 @@ #10 13 69/156 #10 14 72/161 #10 15 75/167 +11 0 No +11 1 Yes # ----------------------------------------------------------------- checksums
Modified: trunk/src/mainboard/roda/rk886ex/cmos.layout ============================================================================== --- trunk/src/mainboard/roda/rk886ex/cmos.layout Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/src/mainboard/roda/rk886ex/cmos.layout Fri Jan 14 08:40:24 2011 (r6253) @@ -92,7 +92,8 @@ # 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 @@ 7 0 Disable 7 1 Enable 7 2 Keep +8 0 No +8 1 Yes
# ----------------------------------------------------------------- checksums
Modified: trunk/src/pc80/Makefile.inc ============================================================================== --- trunk/src/pc80/Makefile.inc Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/src/pc80/Makefile.inc Fri Jan 14 08:40:24 2011 (r6253) @@ -10,3 +10,8 @@
$(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 +
Modified: trunk/src/pc80/mc146818rtc_early.c ============================================================================== --- trunk/src/pc80/mc146818rtc_early.c Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/src/pc80/mc146818rtc_early.c Fri Jan 14 08:40:24 2011 (r6253) @@ -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 @@ 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 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.
Modified: trunk/util/cbfstool/cbfs.h ============================================================================== --- trunk/util/cbfstool/cbfs.h Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/util/cbfstool/cbfs.h Fri Jan 14 08:40:24 2011 (r6253) @@ -76,6 +76,7 @@ #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
Modified: trunk/util/cbfstool/common.c ============================================================================== --- trunk/util/cbfstool/common.c Thu Jan 13 12:40:38 2011 (r6252) +++ trunk/util/cbfstool/common.c Fri Jan 14 08:40:24 2011 (r6253) @@ -145,6 +145,7 @@ {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"} };
repository service wrote:
+++ trunk/src/pc80/mc146818rtc_early.c Fri Jan 14 08:40:24 2011 (r6253)
..
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! */
Isn't this kinda ugly to have in the rtc code? We could at least have some kind of reset/reboot function..
//Peter
* Peter Stuge peter@stuge.se [110117 03:25]:
repository service wrote:
+++ trunk/src/pc80/mc146818rtc_early.c Fri Jan 14 08:40:24 2011 (r6253)
..
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! */
Isn't this kinda ugly to have in the rtc code? We could at least have some kind of reset/reboot function..
agreed. Is this possible? Maybe romcc makes it harder ...
* Stefan Reinauer stefan.reinauer@coreboot.org [110119 07:37]:
- Peter Stuge peter@stuge.se [110117 03:25]:
repository service wrote:
+++ trunk/src/pc80/mc146818rtc_early.c Fri Jan 14 08:40:24 2011 (r6253)
..
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! */
Isn't this kinda ugly to have in the rtc code? We could at least have some kind of reset/reboot function..
agreed. Is this possible? Maybe romcc makes it harder ...
To update on this, there are many different ways to do a reset. The above is not among those implemented by (m)any mainboards I think. So to keep this reliable because it was tested, I suggest we leave it for now. It would be nice to see someone cleanup all the different reset methods, but this is not going to be a fun job. It's highly likely that we actually use the "wrong" reset in many places.
./pc80/mc146818rtc_early.c: outb(0x06, 0xcf9); ./northbridge/intel/i945/raminit.c: outb(0x00, 0xcf9); ./northbridge/intel/i945/raminit.c: outb(0x0e, 0xcf9); ./northbridge/intel/i945/raminit.c: outb(0x00, 0xcf9); ./northbridge/intel/i945/raminit.c: outb(0x0e, 0xcf9); ./northbridge/intel/i945/early_init.c: outb(0x06, 0xcf9); ./northbridge/via/cx700/reset.c: outb((1 << 2) | (1 << 1), 0xcf9); ./northbridge/via/vx800/examples/romstage.c: outb(6, 0xcf9); ./southbridge/nvidia/mcp55/reset.c: outb((0 <<3)|(0<<2)|(1<<1), 0xcf9); ./southbridge/nvidia/mcp55/reset.c: outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); ./southbridge/nvidia/ck804/reset.c: outb((0 << 3) | (0 << 2) | (1 << 1), 0xcf9); ./southbridge/nvidia/ck804/reset.c: outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9); ./southbridge/intel/sch/reset.c: outb(0x04, 0xcf9); ./southbridge/intel/sch/reset.c: outb(0x02, 0xcf9); ./southbridge/intel/sch/reset.c: outb(0x06, 0xcf9); ./southbridge/intel/i82801ex/reset.c: outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); ./southbridge/intel/i82801bx/reset.c: outb((1 << 2) | (1 << 1), 0xcf9); ./southbridge/intel/i82801cx/reset.c: outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); ./southbridge/intel/i82801gx/reset.c: outb(0x04, 0xcf9); ./southbridge/intel/i82801gx/reset.c: outb((1 << 2) | (1 << 1), 0xcf9); ./southbridge/intel/i82801gx/reset.c: outb(0x02, 0xcf9); ./southbridge/intel/i82801gx/reset.c: outb(0x06, 0xcf9); ./southbridge/intel/i82801dx/reset.c: outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9); ./southbridge/intel/i82801ax/reset.c: outb((1 << 2) | (1 << 1), 0xcf9); ./southbridge/intel/i82371eb/i82371eb.h:#define RC 0xcf9 /* Reset control register */ ./southbridge/intel/esb6300/reset.c: outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9); ./southbridge/intel/i3100/reset.c: outb(0x06, 0xcf9); ./southbridge/sis/sis966/reset.c: outb((0 <<3)|(0<<2)|(1<<1), 0xcf9); ./southbridge/sis/sis966/reset.c: outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); ./southbridge/amd/sb700/reset.c: outb((0 << 3) | (0 << 2) | (1 << 1), 0xcf9); ./southbridge/amd/sb700/reset.c: outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9); ./southbridge/amd/sb600/reset.c: outb((0 << 3) | (0 << 2) | (1 << 1), 0xcf9); ./southbridge/amd/sb600/reset.c: outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9); ./southbridge/broadcom/bcm5785/reset.c: outb((0 <<3)|(0<<2)|(1<<1), 0xcf9); ./southbridge/broadcom/bcm5785/reset.c: outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); ./mainboard/intel/eagleheights/reset.c: outb(0x04, 0xcf9); ./mainboard/intel/eagleheights/reset.c: outb(0x06, 0xcf9); ./mainboard/intel/jarrell/reset.c: outb(0x04, 0xcf9); ./mainboard/intel/jarrell/reset.c: outb(0x02, 0xcf9); ./mainboard/intel/jarrell/reset.c: outb(0x06, 0xcf9); ./mainboard/intel/jarrell/reset.c: outb(0x0e, 0xcf9); ./mainboard/via/epia-m700/romstage.c: outb(6, 0xcf9); ./mainboard/supermicro/x6dhr_ig2/reset.c: outb(0x04, 0xcf9); ./mainboard/supermicro/x6dhr_ig2/reset.c: outb(0x02, 0xcf9); ./mainboard/supermicro/x6dhr_ig2/reset.c: outb(0x06, 0xcf9); ./mainboard/supermicro/x6dhe_g/reset.c: outb(0x04, 0xcf9); ./mainboard/supermicro/x6dhe_g/reset.c: outb(0x02, 0xcf9); ./mainboard/supermicro/x6dhe_g/reset.c: outb(0x06, 0xcf9); ./mainboard/supermicro/x6dhe_g2/reset.c: outb(0x04, 0xcf9); ./mainboard/supermicro/x6dhe_g2/reset.c: outb(0x02, 0xcf9); ./mainboard/supermicro/x6dhe_g2/reset.c: outb(0x06, 0xcf9); ./mainboard/supermicro/x6dai_g/reset.c: outb(0x04, 0xcf9); ./mainboard/supermicro/x6dai_g/reset.c: outb(0x02, 0xcf9); ./mainboard/supermicro/x6dai_g/reset.c: outb(0x06, 0xcf9); ./mainboard/supermicro/x6dhr_ig/reset.c: outb(0x04, 0xcf9); ./mainboard/supermicro/x6dhr_ig/reset.c: outb(0x02, 0xcf9); ./mainboard/supermicro/x6dhr_ig/reset.c: outb(0x06, 0xcf9); ./mainboard/roda/rk886ex/romstage.c: outb(0x6, 0xcf9); ./mainboard/ibase/mb899/romstage.c: outb(0x6, 0xcf9); ./mainboard/getac/p470/romstage.c: outb(0x6, 0xcf9); ./mainboard/kontron/986lcd-m/romstage.c: outb(0x6, 0xcf9); ./mainboard/dell/s1850/romstage.c: outb(2, 0xcf9); ./mainboard/dell/s1850/romstage.c: outb(6, 0xcf9); ./mainboard/dell/s1850/reset.c: outb(0x04, 0xcf9); ./mainboard/dell/s1850/reset.c: outb(0x02, 0xcf9); ./mainboard/dell/s1850/reset.c: outb(0x06, 0xcf9);