Zheng Bao (zheng.bao@amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1389
-gerrit
commit 746a8bab1c1c108769315d794b17ae2c7f70ed75 Author: zbao fishbaozi@gmail.com Date: Thu Aug 2 16:07:40 2012 +0800
RTC: Add a routine to check if the CMOS date is valid
If the CMOS is cleared or someone writes some random date/time on purpose, the CMOS date register has a invalid date. This will hurts some OS, like Windows 7, which hangs at MS logo forever. When we detect that, we need to write a reasonable date in CMOS.
Change-Id: Ic1c7a2d60e711265686441c77bdf7891a7efb42e Signed-off-by: Zheng Bao zheng.bao@amd.com Signed-off-by: zbao fishbaozi@gmail.com --- src/drivers/pc80/mc146818rtc.c | 40 +++++++++++++++++++++++++++++++++------- src/include/pc80/mc146818rtc.h | 2 ++ 2 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c index 99d670d..af5b9e2 100644 --- a/src/drivers/pc80/mc146818rtc.c +++ b/src/drivers/pc80/mc146818rtc.c @@ -148,13 +148,13 @@ void rtc_init(int invalid)
if (cmos_invalid) { /* Now setup a default date of Sat 1 January 2000 */ - cmos_write(0, 0x00); /* seconds */ - cmos_write(0, 0x02); /* minutes */ - cmos_write(1, 0x04); /* hours */ - cmos_write(7, 0x06); /* day of week */ - cmos_write(1, 0x07); /* day of month */ - cmos_write(1, 0x08); /* month */ - cmos_write(0, 0x09); /* year */ + cmos_write(0, RTC_CLK_SECOND); + cmos_write(0, RTC_CLK_MINUTE); + cmos_write(1, RTC_CLK_HOUR); + cmos_write(7, RTC_CLK_DAYOFWEEK); + cmos_write(1, RTC_CLK_DAYOFMONTH); + cmos_write(1, RTC_CLK_MINUTE); + cmos_write(0, RTC_CLK_YEAR); } #endif } @@ -338,3 +338,29 @@ int set_option(const char *name, void *value) return 0; } #endif /* CONFIG_USE_OPTION_TABLE */ + +/* + * If the CMOS is cleared, the rtc_reg has the invalid date. That + * hurts some OSes. Even if we don't set USE_OPTION_TABLE, we need + * to make sure the date is valid. + */ +void rtc_check_update_coms_date(u8 has_century) +{ + u8 year; + + /* Note: We need to check if the hardware supports RTC_CLK_ALTCENTURY. */ + year = cmos_read(RTC_CLK_YEAR); + + /* TODO: So far rtc_year is the only entry to check if the date is valid. */ + if (year > 0x99) { /* Invalid date */ + /* Now setup a default date of Sat 1 January 2000 */ + cmos_write(0, RTC_CLK_SECOND); + cmos_write(0, RTC_CLK_MINUTE); + cmos_write(1, RTC_CLK_HOUR); + cmos_write(7, RTC_CLK_DAYOFWEEK); + cmos_write(1, RTC_CLK_DAYOFMONTH); + cmos_write(1, RTC_CLK_MINUTE); + cmos_write(0, RTC_CLK_YEAR); + has_century ? cmos_write(0x20, RTC_CLK_ALTCENTURY) : NULL; + } +} diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h index 9f18ba4..2d93b6f 100644 --- a/src/include/pc80/mc146818rtc.h +++ b/src/include/pc80/mc146818rtc.h @@ -87,6 +87,7 @@ #define RTC_CLK_DAYOFMONTH 7 #define RTC_CLK_MONTH 8 #define RTC_CLK_YEAR 9 +#define RTC_CLK_ALTCENTURY 0x32
/* On PCs, the checksum is built only over bytes 16..45 */ #define PC_CKS_RANGE_START 16 @@ -136,6 +137,7 @@ static inline void cmos_write32(u8 offset, u32 value)
#if !defined(__ROMCC__) void rtc_init(int invalid); +void rtc_check_update_coms_date(u8 has_century); #if CONFIG_USE_OPTION_TABLE int set_option(const char *name, void *val); int get_option(void *dest, const char *name);