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.

Alexandru Gagniuc:
Hmm, it would be interesting to use the date the coreboot image
was built and set that as the default date. At least until time
travel is invented.

Change-Id: Ic1c7a2d60e711265686441c77bdf7891a7efb42e
Signed-off-by: Zheng Bao <zheng.bao@amd.com>
Signed-off-by: zbao <fishbaozi@gmail.com>
Reviewed-on: http://review.coreboot.org/1389
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
zbao 2012-08-02 19:02:26 +08:00 committed by Stefan Reinauer
parent d462736dfb
commit a1e6a9c25a
2 changed files with 40 additions and 8 deletions

View File

@ -77,6 +77,20 @@
# define RTC_VRT 0x80 /* valid RAM and time */ # define RTC_VRT 0x80 /* valid RAM and time */
/**********************************************************************/ /**********************************************************************/
static void rtc_update_cmos_date(u8 has_century)
{
/* Now setup a default date of Sat 1 January 2000 */
/* TODO: Set the time as building time? Is it reasonable? */
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);
if (has_century) cmos_write(0x20, RTC_CLK_ALTCENTURY);
}
#if CONFIG_USE_OPTION_TABLE #if CONFIG_USE_OPTION_TABLE
static int rtc_checksum_valid(int range_start, int range_end, int cks_loc) static int rtc_checksum_valid(int range_start, int range_end, int cks_loc)
{ {
@ -147,14 +161,7 @@ void rtc_init(int invalid)
} }
if (cmos_invalid) { if (cmos_invalid) {
/* Now setup a default date of Sat 1 January 2000 */ rtc_update_cmos_date(RTC_HAS_NO_ALTCENTURY);
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 */
} }
#endif #endif
} }
@ -338,3 +345,23 @@ int set_option(const char *name, void *value)
return 0; return 0;
} }
#endif /* CONFIG_USE_OPTION_TABLE */ #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_cmos_date(u8 has_century)
{
u8 year, century;
/* Note: We need to check if the hardware supports RTC_CLK_ALTCENTURY. */
century = has_century ? cmos_read(RTC_CLK_ALTCENTURY) : 0;
year = cmos_read(RTC_CLK_YEAR);
/* TODO: If century is 0xFF, 100% that the cmos is cleared.
* Other than that, so far rtc_year is the only entry to check if the date is valid. */
if (century > 0x99 || year > 0x99) { /* Invalid date */
rtc_update_cmos_date(has_century);
}
}

View File

@ -87,6 +87,10 @@
#define RTC_CLK_DAYOFMONTH 7 #define RTC_CLK_DAYOFMONTH 7
#define RTC_CLK_MONTH 8 #define RTC_CLK_MONTH 8
#define RTC_CLK_YEAR 9 #define RTC_CLK_YEAR 9
#define RTC_CLK_ALTCENTURY 0x32
#define RTC_HAS_ALTCENTURY 1
#define RTC_HAS_NO_ALTCENTURY 0
/* On PCs, the checksum is built only over bytes 16..45 */ /* On PCs, the checksum is built only over bytes 16..45 */
#define PC_CKS_RANGE_START 16 #define PC_CKS_RANGE_START 16
@ -136,6 +140,7 @@ static inline void cmos_write32(u8 offset, u32 value)
#if !defined(__ROMCC__) #if !defined(__ROMCC__)
void rtc_init(int invalid); void rtc_init(int invalid);
void rtc_check_update_cmos_date(u8 has_century);
#if CONFIG_USE_OPTION_TABLE #if CONFIG_USE_OPTION_TABLE
int set_option(const char *name, void *val); int set_option(const char *name, void *val);
int get_option(void *dest, const char *name); int get_option(void *dest, const char *name);