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:
		| @@ -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); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user