\r
#include "PcRtc.h"\r
\r
-STATIC\r
INTN\r
CompareHMS (\r
IN EFI_TIME *From,\r
IN EFI_TIME *To\r
);\r
\r
-STATIC\r
BOOLEAN\r
IsWithinOneDay (\r
IN EFI_TIME *From,\r
IN EFI_TIME *To\r
);\r
\r
-STATIC\r
UINT8\r
RtcRead (\r
IN UINT8 Address\r
return IoRead8 (PCAT_RTC_DATA_REGISTER);\r
}\r
\r
-STATIC\r
VOID\r
RtcWrite (\r
IN UINT8 Address,\r
//\r
// Wait for up to 0.1 seconds for the RTC to be updated\r
//\r
- Status = RtcWaitToUpdate (100000);\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
if (EFI_ERROR (Status)) {\r
//BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
// provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\r
Time.Month = RtcRead (RTC_ADDRESS_MONTH);\r
Time.Year = RtcRead (RTC_ADDRESS_YEAR);\r
\r
- ConvertRtcTimeToEfiTime (&Time, RegisterB);\r
-\r
if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
+ Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
} else {\r
- Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
}\r
\r
- Time.Year = (UINT16) (Century * 100 + Time.Year);\r
-\r
//\r
// Set RTC configuration after get original time\r
// The value of bit AIE should be reserved.\r
//\r
//BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
// provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\r
+ //\r
if (!EfiAtRuntime ()) {\r
EfiReleaseLock (&Global->RtcLock);\r
}\r
+ \r
//\r
// Validate time fields\r
//\r
- Status = RtcTimeFieldsValid (&Time);\r
+ Status = ConvertRtcTimeToEfiTime (&Time, Century, RegisterB);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = RtcTimeFieldsValid (&Time);\r
+ }\r
if (EFI_ERROR (Status)) {\r
Time.Second = RTC_INIT_SECOND;\r
Time.Minute = RTC_INIT_MINUTE;\r
//\r
// Wait for up to 0.1 seconds for the RTC to be updated\r
//\r
- Status = RtcWaitToUpdate (100000);\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
if (EFI_ERROR (Status)) {\r
//BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
// provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
\r
- ConvertRtcTimeToEfiTime (Time, RegisterB);\r
-\r
if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
+ Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
} else {\r
- Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
}\r
\r
- Time->Year = (UINT16) (Century * 100 + Time->Year);\r
-\r
//\r
// Release RTC Lock.\r
//\r
//\r
// Make sure all field values are in correct range\r
//\r
- Status = RtcTimeFieldsValid (Time);\r
+ Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = RtcTimeFieldsValid (Time);\r
+ }\r
if (EFI_ERROR (Status)) {\r
return EFI_DEVICE_ERROR;\r
}\r
//\r
// Wait for up to 0.1 seconds for the RTC to be updated\r
//\r
- Status = RtcWaitToUpdate (100000);\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
if (EFI_ERROR (Status)) {\r
//BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
// provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
//\r
// Wait for up to 0.1 seconds for the RTC to be updated\r
//\r
- Status = RtcWaitToUpdate (100000);\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
if (EFI_ERROR (Status)) {\r
//BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
// provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
}\r
\r
- ConvertRtcTimeToEfiTime (Time, RegisterB);\r
-\r
if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
+ Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
} else {\r
- Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
}\r
\r
- Time->Year = (UINT16) (Century * 100 + Time->Year);\r
-\r
//\r
// Release RTC Lock.\r
//\r
//\r
// Make sure all field values are in correct range\r
//\r
- Status = RtcTimeFieldsValid (Time);\r
+ Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = RtcTimeFieldsValid (Time);\r
+ }\r
if (EFI_ERROR (Status)) {\r
return EFI_DEVICE_ERROR;\r
}\r
//\r
// Wait for up to 0.1 seconds for the RTC to be updated\r
//\r
- Status = RtcWaitToUpdate (100000);\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
if (EFI_ERROR (Status)) {\r
//BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
// provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
return EFI_DEVICE_ERROR;\r
}\r
\r
-VOID\r
-ConvertRtcTimeToEfiTime (\r
- IN EFI_TIME *Time,\r
- IN RTC_REGISTER_B RegisterB\r
+/**\r
+ Checks an 8-bit BCD value, and converts to an 8-bit value if valid.\r
+\r
+ This function checks the 8-bit BCD value specified by Value.\r
+ If valid, the function converts it to an 8-bit value and returns it.\r
+ Otherwise, return 0xff.\r
+\r
+ @param Value The 8-bit BCD value to check and convert\r
+\r
+ @return The 8-bit value converted.\r
+ 0xff if Value is invalid.\r
+\r
+**/\r
+UINT8\r
+CheckAndConvertBcd8ToDecimal8 (\r
+ IN UINT8 Value\r
)\r
-/*++\r
+{\r
+ if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {\r
+ return BcdToDecimal8 (Value);\r
+ }\r
\r
-Routine Description:\r
+ return 0xff;\r
+}\r
\r
- Arguments:\r
+/**\r
+ Converts time read from RTC to EFI_TIME format defined by UEFI spec.\r
\r
+ This function converts raw time data read from RTC to the EFI_TIME format\r
+ defined by UEFI spec.\r
+ If data mode of RTC is BCD, then converts it to decimal,\r
+ If RTC is in 12-hour format, then converts it to 24-hour format.\r
\r
+ @param Time On input, the time data read from RTC to convert\r
+ On output, the time converted to UEFI format\r
+ @param Century Value of century read from RTC.\r
+ @param RegisterB Value of Register B of RTC, indicating data mode\r
+ and hour format.\r
\r
-Returns:\r
---*/\r
-// GC_TODO: Time - add argument and description to function comment\r
-// GC_TODO: RegisterB - add argument and description to function comment\r
+**/\r
+EFI_STATUS\r
+ConvertRtcTimeToEfiTime (\r
+ IN OUT EFI_TIME *Time,\r
+ IN UINT8 Century,\r
+ IN RTC_REGISTER_B RegisterB\r
+ )\r
{\r
BOOLEAN PM;\r
\r
Time->Hour = (UINT8) (Time->Hour & 0x7f);\r
\r
if (RegisterB.Bits.DM == 0) {\r
- Time->Year = BcdToDecimal8 ((UINT8) Time->Year);\r
- Time->Month = BcdToDecimal8 (Time->Month);\r
- Time->Day = BcdToDecimal8 (Time->Day);\r
- Time->Hour = BcdToDecimal8 (Time->Hour);\r
- Time->Minute = BcdToDecimal8 (Time->Minute);\r
- Time->Second = BcdToDecimal8 (Time->Second);\r
+ Time->Year = CheckAndConvertBcd8ToDecimal8 ((UINT8) Time->Year);\r
+ Time->Month = CheckAndConvertBcd8ToDecimal8 (Time->Month);\r
+ Time->Day = CheckAndConvertBcd8ToDecimal8 (Time->Day);\r
+ Time->Hour = CheckAndConvertBcd8ToDecimal8 (Time->Hour);\r
+ Time->Minute = CheckAndConvertBcd8ToDecimal8 (Time->Minute);\r
+ Time->Second = CheckAndConvertBcd8ToDecimal8 (Time->Second);\r
+ Century = CheckAndConvertBcd8ToDecimal8 (Century);\r
+ }\r
+\r
+ if (Time->Year == 0xff || Time->Month == 0xff || Time->Day == 0xff ||\r
+ Time->Hour == 0xff || Time->Minute == 0xff || Time->Second == 0xff ||\r
+ Century == 0xff) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
+\r
+ Time->Year = (UINT16) (Century * 100 + Time->Year);\r
+\r
//\r
// If time is in 12 hour format, convert it to 24 hour format\r
//\r
Time->Nanosecond = 0;\r
Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
Time->Daylight = 0;\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS\r
}\r
}\r
\r
-STATIC\r
INTN\r
CompareHMS (\r
IN EFI_TIME *From,\r
}\r
}\r
\r
-STATIC\r
BOOLEAN\r
IsWithinOneDay (\r
IN EFI_TIME *From,\r