+++ /dev/null
-/** @file\r
- RTC Architectural Protocol GUID as defined in DxeCis 0.96.\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "PcRtc.h"\r
-\r
-/**\r
- Compare the Hour, Minute and Second of the From time and the To time.\r
- \r
- Only compare H/M/S in EFI_TIME and ignore other fields here.\r
-\r
- @param From the first time\r
- @param To the second time\r
-\r
- @return >0 The H/M/S of the From time is later than those of To time\r
- @return ==0 The H/M/S of the From time is same as those of To time\r
- @return <0 The H/M/S of the From time is earlier than those of To time\r
-**/\r
-INTN\r
-CompareHMS (\r
- IN EFI_TIME *From,\r
- IN EFI_TIME *To\r
- );\r
-\r
-/**\r
- To check if second date is later than first date within 24 hours.\r
-\r
- @param From the first date\r
- @param To the second date\r
-\r
- @retval TRUE From is previous to To within 24 hours.\r
- @retval FALSE From is later, or it is previous to To more than 24 hours.\r
-**/\r
-BOOLEAN\r
-IsWithinOneDay (\r
- IN EFI_TIME *From,\r
- IN EFI_TIME *To\r
- );\r
-\r
-/**\r
- Read RTC content through its registers.\r
-\r
- @param Address Address offset of RTC. It is recommended to use macros such as\r
- RTC_ADDRESS_SECONDS.\r
-\r
- @return The data of UINT8 type read from RTC.\r
-**/\r
-UINT8\r
-RtcRead (\r
- IN UINT8 Address\r
- )\r
-{\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
- return IoRead8 (PCAT_RTC_DATA_REGISTER);\r
-}\r
-\r
-/**\r
- Write RTC through its registers.\r
-\r
- @param Address Address offset of RTC. It is recommended to use macros such as\r
- RTC_ADDRESS_SECONDS.\r
- @param Data The content you want to write into RTC.\r
-\r
-**/\r
-VOID\r
-RtcWrite (\r
- IN UINT8 Address,\r
- IN UINT8 Data\r
- )\r
-{\r
- IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
- IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);\r
-}\r
-\r
-/**\r
- Initialize RTC.\r
-\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_DEVICE_ERROR Initialization failed due to device error.\r
- @retval EFI_SUCCESS Initialization successful.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcInit (\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-{\r
- EFI_STATUS Status;\r
- RTC_REGISTER_A RegisterA;\r
- RTC_REGISTER_B RegisterB;\r
- RTC_REGISTER_D RegisterD;\r
- UINT8 Century;\r
- EFI_TIME Time;\r
- UINTN DataSize;\r
- UINT32 TimerVar;\r
-\r
- //\r
- // Acquire RTC Lock to make access to RTC atomic\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiAcquireLock (&Global->RtcLock);\r
- }\r
- //\r
- // Initialize RTC Register\r
- //\r
- // Make sure Division Chain is properly configured,\r
- // or RTC clock won't "tick" -- time won't increment\r
- //\r
- RegisterA.Data = RTC_INIT_REGISTER_A;\r
- RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);\r
-\r
- //\r
- // Read Register B\r
- //\r
- RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
-\r
- //\r
- // Clear RTC flag register\r
- //\r
- RtcRead (RTC_ADDRESS_REGISTER_C);\r
-\r
- //\r
- // Clear RTC register D\r
- //\r
- RegisterD.Data = RTC_INIT_REGISTER_D;\r
- RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);\r
-\r
- //\r
- // Wait for up to 0.1 seconds for the RTC to be updated\r
- //\r
- Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
- if (EFI_ERROR (Status)) {\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Get the Time/Date/Daylight Savings values.\r
- //\r
- Time.Second = RtcRead (RTC_ADDRESS_SECONDS);\r
- Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
- Time.Hour = RtcRead (RTC_ADDRESS_HOURS);\r
- Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
- Time.Month = RtcRead (RTC_ADDRESS_MONTH);\r
- Time.Year = RtcRead (RTC_ADDRESS_YEAR);\r
-\r
- Century = RtcRead (RTC_ADDRESS_CENTURY);\r
- \r
- //\r
- // Set RTC configuration after get original time\r
- // The value of bit AIE should be reserved.\r
- //\r
- RtcWrite (RTC_ADDRESS_REGISTER_B, (UINT8)(RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5)));\r
-\r
- //\r
- // Release RTC Lock.\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- \r
- //\r
- // Validate time fields\r
- //\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
- Time.Hour = RTC_INIT_HOUR;\r
- Time.Day = RTC_INIT_DAY;\r
- Time.Month = RTC_INIT_MONTH;\r
- Time.Year = RTC_INIT_YEAR;\r
- }\r
- //\r
- // Get the data of Daylight saving and time zone, if they have been\r
- // stored in NV variable during previous boot.\r
- //\r
- DataSize = sizeof (UINT32);\r
- Status = EfiGetVariable (\r
- L"RTC",\r
- &gEfiCallerIdGuid,\r
- NULL,\r
- &DataSize,\r
- (VOID *) &TimerVar\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Global->SavedTimeZone = (INT16) TimerVar;\r
- Global->Daylight = (UINT8) (TimerVar >> 16);\r
-\r
- Time.TimeZone = Global->SavedTimeZone;\r
- Time.Daylight = Global->Daylight;\r
- }\r
- //\r
- // Reset time value according to new RTC configuration\r
- //\r
- PcRtcSetTime (&Time, Global);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Returns the current time and date information, and the time-keeping capabilities\r
- of the hardware platform.\r
-\r
- @param Time A pointer to storage to receive a snapshot of the current time.\r
- @param Capabilities An optional pointer to a buffer to receive the real time clock\r
- device's capabilities.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcGetTime (\r
- OUT EFI_TIME *Time,\r
- OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-{\r
- EFI_STATUS Status;\r
- RTC_REGISTER_B RegisterB;\r
- UINT8 Century;\r
-\r
- //\r
- // Check parameters for null pointer\r
- //\r
- if (Time == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
-\r
- }\r
- //\r
- // Acquire RTC Lock to make access to RTC atomic\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiAcquireLock (&Global->RtcLock);\r
- }\r
- //\r
- // Wait for up to 0.1 seconds for the RTC to be updated\r
- //\r
- Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
- if (EFI_ERROR (Status)) {\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return Status;\r
- }\r
- //\r
- // Read Register B\r
- //\r
- RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
-\r
- //\r
- // Get the Time/Date/Daylight Savings values.\r
- //\r
- Time->Second = RtcRead (RTC_ADDRESS_SECONDS);\r
- Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
- Time->Hour = RtcRead (RTC_ADDRESS_HOURS);\r
- Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
- Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
- Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
-\r
- Century = RtcRead (RTC_ADDRESS_CENTURY);\r
- \r
- //\r
- // Release RTC Lock.\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Get the variable that contains the TimeZone and Daylight fields\r
- //\r
- Time->TimeZone = Global->SavedTimeZone;\r
- Time->Daylight = Global->Daylight;\r
-\r
- //\r
- // Make sure all field values are in correct range\r
- //\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
- // Fill in Capabilities if it was passed in\r
- //\r
- if (Capabilities != NULL) {\r
- Capabilities->Resolution = 1;\r
- //\r
- // 1 hertz\r
- //\r
- Capabilities->Accuracy = 50000000;\r
- //\r
- // 50 ppm\r
- //\r
- Capabilities->SetsToZero = FALSE;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Sets the current local time and date information.\r
-\r
- @param Time A pointer to the current time.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER A time field is out of range.\r
- @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcSetTime (\r
- IN EFI_TIME *Time,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TIME RtcTime;\r
- RTC_REGISTER_B RegisterB;\r
- UINT8 Century;\r
- UINT32 TimerVar;\r
-\r
- if (Time == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Make sure that the time fields are valid\r
- //\r
- Status = RtcTimeFieldsValid (Time);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
-\r
- //\r
- // Acquire RTC Lock to make access to RTC atomic\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiAcquireLock (&Global->RtcLock);\r
- }\r
- //\r
- // Wait for up to 0.1 seconds for the RTC to be updated\r
- //\r
- Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
- if (EFI_ERROR (Status)) {\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return Status;\r
- }\r
- //\r
- // Read Register B, and inhibit updates of the RTC\r
- //\r
- RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
- RegisterB.Bits.SET = 1;\r
- RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
-\r
- ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
-\r
- RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);\r
- RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);\r
- RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);\r
- RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);\r
- RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);\r
- RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);\r
- RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
-\r
- //\r
- // Allow updates of the RTC registers\r
- //\r
- RegisterB.Bits.SET = 0;\r
- RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
-\r
- //\r
- // Release RTC Lock.\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Set the variable that contains the TimeZone and Daylight fields\r
- //\r
- Global->SavedTimeZone = Time->TimeZone;\r
- Global->Daylight = Time->Daylight;\r
-\r
- TimerVar = Time->Daylight;\r
- TimerVar = (UINT32) ((TimerVar << 16) | Time->TimeZone);\r
- Status = EfiSetVariable (\r
- L"RTC",\r
- &gEfiCallerIdGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- sizeof (TimerVar),\r
- &TimerVar\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Returns the current wakeup alarm clock setting.\r
-\r
- @param Enabled Indicates if the alarm is currently enabled or disabled.\r
- @param Pending Indicates if the alarm signal is pending and requires acknowledgment.\r
- @param Time The current alarm setting.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS The alarm settings were returned.\r
- @retval EFI_INVALID_PARAMETER Enabled is NULL.\r
- @retval EFI_INVALID_PARAMETER Pending is NULL.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.\r
- @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcGetWakeupTime (\r
- OUT BOOLEAN *Enabled,\r
- OUT BOOLEAN *Pending,\r
- OUT EFI_TIME *Time,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-{\r
- EFI_STATUS Status;\r
- RTC_REGISTER_B RegisterB;\r
- RTC_REGISTER_C RegisterC;\r
- UINT8 Century;\r
-\r
- //\r
- // Check parameters for null pointers\r
- //\r
- if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
-\r
- }\r
- //\r
- // Acquire RTC Lock to make access to RTC atomic\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiAcquireLock (&Global->RtcLock);\r
- }\r
- //\r
- // Wait for up to 0.1 seconds for the RTC to be updated\r
- //\r
- Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
- if (EFI_ERROR (Status)) {\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Read Register B and Register C\r
- //\r
- RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
- RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);\r
-\r
- //\r
- // Get the Time/Date/Daylight Savings values.\r
- //\r
- *Enabled = RegisterB.Bits.AIE;\r
- if (*Enabled) {\r
- Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);\r
- Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);\r
- Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);\r
- Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
- Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
- Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
- } else {\r
- Time->Second = 0;\r
- Time->Minute = 0;\r
- Time->Hour = 0;\r
- Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
- Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
- Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
- }\r
-\r
- Century = RtcRead (RTC_ADDRESS_CENTURY);\r
- \r
- //\r
- // Release RTC Lock.\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Make sure all field values are in correct range\r
- //\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
- *Pending = RegisterC.Bits.AF;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Sets the system wakeup alarm clock time.\r
-\r
- @param Enabled Enable or disable the wakeup alarm.\r
- @param Time If Enable is TRUE, the time to set the wakeup alarm for.\r
- If Enable is FALSE, then this parameter is optional, and may be NULL.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.\r
- If Enable is FALSE, then the wakeup alarm was disabled.\r
- @retval EFI_INVALID_PARAMETER A time field is out of range.\r
- @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.\r
- @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcSetWakeupTime (\r
- IN BOOLEAN Enable,\r
- IN EFI_TIME *Time, OPTIONAL\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TIME RtcTime;\r
- RTC_REGISTER_B RegisterB;\r
- UINT8 Century;\r
- EFI_TIME_CAPABILITIES Capabilities;\r
-\r
- if (Enable) {\r
-\r
- if (Time == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Make sure that the time fields are valid\r
- //\r
- Status = RtcTimeFieldsValid (Time);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Just support set alarm time within 24 hours\r
- //\r
- PcRtcGetTime (&RtcTime, &Capabilities, Global);\r
- Status = RtcTimeFieldsValid (&RtcTime);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- if (!IsWithinOneDay (&RtcTime, Time)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- //\r
- // Make a local copy of the time and date\r
- //\r
- CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
-\r
- }\r
- //\r
- // Acquire RTC Lock to make access to RTC atomic\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiAcquireLock (&Global->RtcLock);\r
- }\r
- //\r
- // Wait for up to 0.1 seconds for the RTC to be updated\r
- //\r
- Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
- if (EFI_ERROR (Status)) {\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Read Register B, and inhibit updates of the RTC\r
- //\r
- RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
-\r
- RegisterB.Bits.SET = 1;\r
- RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
-\r
- if (Enable) {\r
- ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
-\r
- //\r
- // Set RTC alarm time\r
- //\r
- RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);\r
- RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);\r
- RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);\r
-\r
- RegisterB.Bits.AIE = 1;\r
-\r
- } else {\r
- RegisterB.Bits.AIE = 0;\r
- }\r
- //\r
- // Allow updates of the RTC registers\r
- //\r
- RegisterB.Bits.SET = 0;\r
- RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
-\r
- //\r
- // Release RTC Lock.\r
- //\r
- //Code here doesn't consider the runtime environment.\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\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. Or 0xff if Value is invalid.\r
-\r
-**/\r
-UINT8\r
-CheckAndConvertBcd8ToDecimal8 (\r
- IN UINT8 Value\r
- )\r
-{\r
- if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {\r
- return BcdToDecimal8 (Value);\r
- }\r
-\r
- return 0xff;\r
-}\r
-\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
- @retval EFI_INVALID_PARAMETER Parameters passed in are invalid.\r
- @retval EFI_SUCCESS Convert RTC time to EFI time successfully.\r
-\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 IsPM;\r
-\r
- if ((Time->Hour & 0x80) != 0) {\r
- IsPM = TRUE;\r
- } else {\r
- IsPM = FALSE;\r
- }\r
-\r
- Time->Hour = (UINT8) (Time->Hour & 0x7f);\r
-\r
- if (RegisterB.Bits.DM == 0) {\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
- }\r
- Century = CheckAndConvertBcd8ToDecimal8 (Century);\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
- if (RegisterB.Bits.MIL == 0) {\r
- if (IsPM && Time->Hour < 12) {\r
- Time->Hour = (UINT8) (Time->Hour + 12);\r
- }\r
-\r
- if (!IsPM && Time->Hour == 12) {\r
- Time->Hour = 0;\r
- }\r
- }\r
-\r
- Time->Nanosecond = 0;\r
- Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
- Time->Daylight = 0;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Wait for a period for the RTC to be ready.\r
-\r
- @param Timeout Tell how long it should take to wait.\r
-\r
- @retval EFI_DEVICE_ERROR RTC device error.\r
- @retval EFI_SUCCESS RTC is updated and ready. \r
-**/\r
-EFI_STATUS\r
-RtcWaitToUpdate (\r
- UINTN Timeout\r
- )\r
-{\r
- RTC_REGISTER_A RegisterA;\r
- RTC_REGISTER_D RegisterD;\r
-\r
- //\r
- // See if the RTC is functioning correctly\r
- //\r
- RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
-\r
- if (RegisterD.Bits.VRT == 0) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Wait for up to 0.1 seconds for the RTC to be ready.\r
- //\r
- Timeout = (Timeout / 10) + 1;\r
- RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
- while (RegisterA.Bits.UIP == 1 && Timeout > 0) {\r
- MicroSecondDelay (10);\r
- RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
- Timeout--;\r
- }\r
-\r
- RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
- if (Timeout == 0 || RegisterD.Bits.VRT == 0) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- See if all fields of a variable of EFI_TIME type is correct.\r
-\r
- @param Time The time to be checked.\r
-\r
- @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.\r
- @retval EFI_SUCCESS Time is a valid EFI_TIME variable.\r
-\r
-**/\r
-EFI_STATUS\r
-RtcTimeFieldsValid (\r
- IN EFI_TIME *Time\r
- )\r
-{\r
- if (Time->Year < 1998 ||\r
- Time->Year > 2099 ||\r
- Time->Month < 1 ||\r
- Time->Month > 12 ||\r
- Time->Hour > 23 ||\r
- Time->Minute > 59 ||\r
- Time->Second > 59 ||\r
- Time->Nanosecond > 999999999 ||\r
- (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||\r
- ((Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) != 0)\r
- ) {\r
- if (!DayValid (Time)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- See if field Day of an EFI_TIME is correct.\r
-\r
- @param Time Its Day field is to be checked.\r
-\r
- @retval TRUE Day field of Time is correct.\r
- @retval FALSE Day field of Time is NOT correct.\r
-**/\r
-BOOLEAN\r
-DayValid (\r
- IN EFI_TIME *Time\r
- )\r
-{\r
- INTN DayOfMonth[12];\r
-\r
- DayOfMonth[0] = 31;\r
- DayOfMonth[1] = 29;\r
- DayOfMonth[2] = 31;\r
- DayOfMonth[3] = 30;\r
- DayOfMonth[4] = 31;\r
- DayOfMonth[5] = 30;\r
- DayOfMonth[6] = 31;\r
- DayOfMonth[7] = 31;\r
- DayOfMonth[8] = 30;\r
- DayOfMonth[9] = 31;\r
- DayOfMonth[10] = 30;\r
- DayOfMonth[11] = 31;\r
-\r
- //\r
- // The validity of Time->Month field should be checked before\r
- //\r
- ASSERT (Time->Month >=1);\r
- ASSERT (Time->Month <=12);\r
- if (Time->Day < 1 ||\r
- Time->Day > DayOfMonth[Time->Month - 1] ||\r
- (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
- ) {\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/**\r
- Check if it is a leap year.\r
-\r
- @param Time The time to be checked.\r
-\r
- @retval TRUE It is a leap year.\r
- @retval FALSE It is NOT a leap year.\r
-**/\r
-BOOLEAN\r
-IsLeapYear (\r
- IN EFI_TIME *Time\r
- )\r
-{\r
- if (Time->Year % 4 == 0) {\r
- if (Time->Year % 100 == 0) {\r
- if (Time->Year % 400 == 0) {\r
- return TRUE;\r
- } else {\r
- return FALSE;\r
- }\r
- } else {\r
- return TRUE;\r
- }\r
- } else {\r
- return FALSE;\r
- }\r
-}\r
-\r
-/**\r
- Converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
-\r
- This function converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
- If data mode of RTC is BCD, then converts EFI_TIME to it.\r
- If RTC is in 12-hour format, then converts EFI_TIME to it.\r
-\r
- @param Time On input, the time data read from UEFI to convert\r
- On output, the time converted to RTC format\r
- @param RegisterB Value of Register B of RTC, indicating data mode\r
- @param Century It is set according to EFI_TIME Time.\r
-\r
-**/\r
-VOID\r
-ConvertEfiTimeToRtcTime (\r
- IN OUT EFI_TIME *Time,\r
- IN RTC_REGISTER_B RegisterB,\r
- OUT UINT8 *Century\r
- )\r
-{\r
- BOOLEAN IsPM;\r
-\r
- IsPM = TRUE;\r
- //\r
- // Adjust hour field if RTC is in 12 hour mode\r
- //\r
- if (RegisterB.Bits.MIL == 0) {\r
- if (Time->Hour < 12) {\r
- IsPM = FALSE;\r
- }\r
-\r
- if (Time->Hour >= 13) {\r
- Time->Hour = (UINT8) (Time->Hour - 12);\r
- } else if (Time->Hour == 0) {\r
- Time->Hour = 12;\r
- }\r
- }\r
- //\r
- // Set the Time/Date/Daylight Savings values.\r
- //\r
- *Century = DecimalToBcd8 ((UINT8) (Time->Year / 100));\r
-\r
- Time->Year = (UINT16) (Time->Year % 100);\r
-\r
- if (RegisterB.Bits.DM == 0) {\r
- Time->Year = DecimalToBcd8 ((UINT8) Time->Year);\r
- Time->Month = DecimalToBcd8 (Time->Month);\r
- Time->Day = DecimalToBcd8 (Time->Day);\r
- Time->Hour = DecimalToBcd8 (Time->Hour);\r
- Time->Minute = DecimalToBcd8 (Time->Minute);\r
- Time->Second = DecimalToBcd8 (Time->Second);\r
- }\r
- //\r
- // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.\r
- //\r
- if (RegisterB.Bits.MIL == 0 && IsPM) {\r
- Time->Hour = (UINT8) (Time->Hour | 0x80);\r
- }\r
-}\r
-\r
-/**\r
- Compare the Hour, Minute and Second of the From time and the To time.\r
- \r
- Only compare H/M/S in EFI_TIME and ignore other fields here.\r
-\r
- @param From the first time\r
- @param To the second time\r
-\r
- @return >0 The H/M/S of the From time is later than those of To time\r
- @return ==0 The H/M/S of the From time is same as those of To time\r
- @return <0 The H/M/S of the From time is earlier than those of To time\r
-**/\r
-INTN\r
-CompareHMS (\r
- IN EFI_TIME *From,\r
- IN EFI_TIME *To\r
- )\r
-{\r
- if ((From->Hour > To->Hour) ||\r
- ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||\r
- ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second))) {\r
- return 1;\r
- } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {\r
- return 0;\r
- } else {\r
- return -1;\r
- }\r
-}\r
-\r
-/**\r
- To check if second date is later than first date within 24 hours.\r
-\r
- @param From the first date\r
- @param To the second date\r
-\r
- @retval TRUE From is previous to To within 24 hours.\r
- @retval FALSE From is later, or it is previous to To more than 24 hours.\r
-**/\r
-BOOLEAN\r
-IsWithinOneDay (\r
- IN EFI_TIME *From,\r
- IN EFI_TIME *To\r
- )\r
-{\r
- UINT8 DayOfMonth[12];\r
- BOOLEAN Adjacent;\r
-\r
- DayOfMonth[0] = 31;\r
- DayOfMonth[1] = 29;\r
- DayOfMonth[2] = 31;\r
- DayOfMonth[3] = 30;\r
- DayOfMonth[4] = 31;\r
- DayOfMonth[5] = 30;\r
- DayOfMonth[6] = 31;\r
- DayOfMonth[7] = 31;\r
- DayOfMonth[8] = 30;\r
- DayOfMonth[9] = 31;\r
- DayOfMonth[10] = 30;\r
- DayOfMonth[11] = 31;\r
-\r
- Adjacent = FALSE;\r
-\r
- //\r
- // The validity of From->Month field should be checked before\r
- //\r
- ASSERT (From->Month >=1);\r
- ASSERT (From->Month <=12);\r
- \r
- if (From->Year == To->Year) {\r
- if (From->Month == To->Month) {\r
- if ((From->Day + 1) == To->Day) {\r
- if ((CompareHMS(From, To) >= 0)) {\r
- Adjacent = TRUE;\r
- }\r
- } else if (From->Day == To->Day) {\r
- if ((CompareHMS(From, To) <= 0)) {\r
- Adjacent = TRUE;\r
- }\r
- }\r
- } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {\r
- if ((From->Month == 2) && !IsLeapYear(From)) {\r
- if (From->Day == 28) {\r
- if ((CompareHMS(From, To) >= 0)) {\r
- Adjacent = TRUE;\r
- }\r
- }\r
- } else if (From->Day == DayOfMonth[From->Month - 1]) {\r
- if ((CompareHMS(From, To) >= 0)) {\r
- Adjacent = TRUE;\r
- }\r
- }\r
- }\r
- } else if (((From->Year + 1) == To->Year) &&\r
- (From->Month == 12) &&\r
- (From->Day == 31) &&\r
- (To->Month == 1) &&\r
- (To->Day == 1)) {\r
- if ((CompareHMS(From, To) >= 0)) {\r
- Adjacent = TRUE;\r
- }\r
- }\r
-\r
- return Adjacent;\r
-}\r
-\r
+++ /dev/null
-/** @file\r
- Header file for real time clock driver.\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#ifndef _RTC_H_\r
-#define _RTC_H_\r
-\r
-\r
-#include <Uefi.h>\r
-\r
-#include <Protocol/RealTimeClock.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/TimerLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/PcdLib.h>\r
-\r
-\r
-typedef struct {\r
- EFI_LOCK RtcLock;\r
- INT16 SavedTimeZone;\r
- UINT8 Daylight;\r
-} PC_RTC_MODULE_GLOBALS;\r
-\r
-#define PCAT_RTC_ADDRESS_REGISTER 0x70\r
-#define PCAT_RTC_DATA_REGISTER 0x71\r
-\r
-//\r
-// Dallas DS12C887 Real Time Clock\r
-//\r
-#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59\r
-#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59\r
-#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59\r
-#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59\r
-#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
-#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
-#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7\r
-#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31\r
-#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12\r
-#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99\r
-#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]\r
-#define RTC_ADDRESS_REGISTER_B 11 // R/W\r
-#define RTC_ADDRESS_REGISTER_C 12 // RO\r
-#define RTC_ADDRESS_REGISTER_D 13 // RO\r
-#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W\r
-//\r
-// Date and time initial values.\r
-// They are used if the RTC values are invalid during driver initialization\r
-//\r
-#define RTC_INIT_SECOND 0\r
-#define RTC_INIT_MINUTE 0\r
-#define RTC_INIT_HOUR 0\r
-#define RTC_INIT_DAY 1\r
-#define RTC_INIT_MONTH 1\r
-#define RTC_INIT_YEAR 2001\r
-\r
-//\r
-// Register initial values\r
-//\r
-#define RTC_INIT_REGISTER_A 0x26\r
-#define RTC_INIT_REGISTER_B 0x02\r
-#define RTC_INIT_REGISTER_D 0x0\r
-\r
-#pragma pack(1)\r
-//\r
-// Register A\r
-//\r
-typedef struct {\r
- UINT8 RS : 4; // Rate Selection Bits\r
- UINT8 DV : 3; // Divisor\r
- UINT8 UIP : 1; // Update in progress\r
-} RTC_REGISTER_A_BITS;\r
-\r
-typedef union {\r
- RTC_REGISTER_A_BITS Bits;\r
- UINT8 Data;\r
-} RTC_REGISTER_A;\r
-\r
-//\r
-// Register B\r
-//\r
-typedef struct {\r
- UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled\r
- UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode\r
- UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format\r
- UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output\r
- UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled\r
- UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled\r
- UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled\r
- UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited\r
-} RTC_REGISTER_B_BITS;\r
-\r
-typedef union {\r
- RTC_REGISTER_B_BITS Bits;\r
- UINT8 Data;\r
-} RTC_REGISTER_B;\r
-\r
-//\r
-// Register C\r
-//\r
-typedef struct {\r
- UINT8 Reserved : 4; // Read as zero. Can not be written.\r
- UINT8 UF : 1; // Update End Interrupt Flag\r
- UINT8 AF : 1; // Alarm Interrupt Flag\r
- UINT8 PF : 1; // Periodic Interrupt Flag\r
- UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE\r
-} RTC_REGISTER_C_BITS;\r
-\r
-typedef union {\r
- RTC_REGISTER_C_BITS Bits;\r
- UINT8 Data;\r
-} RTC_REGISTER_C;\r
-\r
-//\r
-// Register D\r
-//\r
-typedef struct {\r
- UINT8 Reserved : 7; // Read as zero. Can not be written.\r
- UINT8 VRT : 1; // Valid RAM and Time\r
-} RTC_REGISTER_D_BITS;\r
-\r
-typedef union {\r
- RTC_REGISTER_D_BITS Bits;\r
- UINT8 Data;\r
-} RTC_REGISTER_D;\r
-\r
-#pragma pack()\r
-\r
-/**\r
- Initialize RTC.\r
-\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_DEVICE_ERROR Initialization failed due to device error.\r
- @retval EFI_SUCCESS Initialization successful.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcInit (\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- );\r
-\r
-/**\r
- Sets the current local time and date information.\r
-\r
- @param Time A pointer to the current time.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER A time field is out of range.\r
- @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcSetTime (\r
- IN EFI_TIME *Time,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- );\r
-\r
-/**\r
- Returns the current time and date information, and the time-keeping capabilities\r
- of the hardware platform.\r
-\r
- @param Time A pointer to storage to receive a snapshot of the current time.\r
- @param Capabilities An optional pointer to a buffer to receive the real time clock\r
- device's capabilities.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcGetTime (\r
- OUT EFI_TIME *Time,\r
- OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- );\r
-\r
-/**\r
- Sets the system wakeup alarm clock time.\r
-\r
- @param Enabled Enable or disable the wakeup alarm.\r
- @param Time If Enable is TRUE, the time to set the wakeup alarm for.\r
- If Enable is FALSE, then this parameter is optional, and may be NULL.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.\r
- If Enable is FALSE, then the wakeup alarm was disabled.\r
- @retval EFI_INVALID_PARAMETER A time field is out of range.\r
- @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.\r
- @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcSetWakeupTime (\r
- IN BOOLEAN Enable,\r
- IN EFI_TIME *Time, OPTIONAL\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- );\r
-\r
-/**\r
- Returns the current wakeup alarm clock setting.\r
-\r
- @param Enabled Indicates if the alarm is currently enabled or disabled.\r
- @param Pending Indicates if the alarm signal is pending and requires acknowledgement.\r
- @param Time The current alarm setting.\r
- @param Global For global use inside this module.\r
-\r
- @retval EFI_SUCCESS The alarm settings were returned.\r
- @retval EFI_INVALID_PARAMETER Enabled is NULL.\r
- @retval EFI_INVALID_PARAMETER Pending is NULL.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.\r
- @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
-\r
-**/\r
-EFI_STATUS\r
-PcRtcGetWakeupTime (\r
- OUT BOOLEAN *Enabled,\r
- OUT BOOLEAN *Pending,\r
- OUT EFI_TIME *Time,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- );\r
-\r
-/**\r
- The user Entry Point for PcRTC module.\r
-\r
- This is the entrhy point for PcRTC module. It installs the UEFI runtime service\r
- including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().\r
-\r
- @param ImageHandle The firmware allocated handle for the EFI image.\r
- @param SystemTable A pointer to the EFI System Table.\r
-\r
- @retval EFI_SUCCESS The entry point is executed successfully.\r
- @retval Others Some error occurs when executing this entry point.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializePcRtc (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- );\r
-\r
-/**\r
- See if all fields of a variable of EFI_TIME type is correct.\r
-\r
- @param Time The time to be checked.\r
-\r
- @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.\r
- @retval EFI_SUCCESS Time is a valid EFI_TIME variable.\r
-\r
-**/\r
-EFI_STATUS\r
-RtcTimeFieldsValid (\r
- IN EFI_TIME *Time\r
- );\r
-\r
-/**\r
- Converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
-\r
- This function converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
- If data mode of RTC is BCD, then converts EFI_TIME to it.\r
- If RTC is in 12-hour format, then converts EFI_TIME to it.\r
-\r
- @param Time On input, the time data read from UEFI to convert\r
- On output, the time converted to RTC format\r
- @param RegisterB Value of Register B of RTC, indicating data mode\r
- @param Century It is set according to EFI_TIME Time.\r
-\r
-**/\r
-VOID\r
-ConvertEfiTimeToRtcTime (\r
- IN OUT EFI_TIME *Time,\r
- IN RTC_REGISTER_B RegisterB,\r
- OUT UINT8 *Century\r
- );\r
-\r
-\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
- @retval EFI_INVALID_PARAMETER Parameters passed in are invalid.\r
- @retval EFI_SUCCESS Convert RTC time to EFI time successfully.\r
-\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
-/**\r
- Wait for a period for the RTC to be ready.\r
-\r
- @param Timeout Tell how long it should take to wait.\r
-\r
- @retval EFI_DEVICE_ERROR RTC device error.\r
- @retval EFI_SUCCESS RTC is updated and ready. \r
-**/\r
-EFI_STATUS\r
-RtcWaitToUpdate (\r
- UINTN Timeout\r
- );\r
-\r
-/**\r
- See if field Day of an EFI_TIME is correct.\r
-\r
- @param Time Its Day field is to be checked.\r
-\r
- @retval TRUE Day field of Time is correct.\r
- @retval FALSE Day field of Time is NOT correct.\r
-**/\r
-BOOLEAN\r
-DayValid (\r
- IN EFI_TIME *Time\r
- );\r
-\r
-/**\r
- Check if it is a leapyear.\r
-\r
- @param Time The time to be checked.\r
-\r
- @retval TRUE It is a leapyear.\r
- @retval FALSE It is NOT a leapyear.\r
-**/\r
-BOOLEAN\r
-IsLeapYear (\r
- IN EFI_TIME *Time\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- Provides Set/Get time operations.\r
-\r
-Copyright (c) 2006 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "PcRtc.h"\r
-\r
-PC_RTC_MODULE_GLOBALS mModuleGlobal;\r
-\r
-EFI_HANDLE mHandle = NULL;\r
-\r
-\r
-/**\r
- Returns the current time and date information, and the time-keeping capabilities\r
- of the hardware platform.\r
-\r
- @param Time A pointer to storage to receive a snapshot of the current time.\r
- @param Capabilities An optional pointer to a buffer to receive the real time\r
- clock device's capabilities.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PcRtcEfiGetTime (\r
- OUT EFI_TIME *Time,\r
- OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL\r
- )\r
-{\r
- return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);\r
-}\r
-\r
-/**\r
- Sets the current local time and date information.\r
-\r
- @param Time A pointer to the current time.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER A time field is out of range.\r
- @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PcRtcEfiSetTime (\r
- IN EFI_TIME *Time\r
- )\r
-{\r
- return PcRtcSetTime (Time, &mModuleGlobal);\r
-}\r
-\r
-/**\r
- Returns the current wakeup alarm clock setting.\r
-\r
- @param Enabled Indicates if the alarm is currently enabled or disabled.\r
- @param Pending Indicates if the alarm signal is pending and requires acknowledgement.\r
- @param Time The current alarm setting.\r
-\r
- @retval EFI_SUCCESS The alarm settings were returned.\r
- @retval EFI_INVALID_PARAMETER Enabled is NULL.\r
- @retval EFI_INVALID_PARAMETER Pending is NULL.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.\r
- @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PcRtcEfiGetWakeupTime (\r
- OUT BOOLEAN *Enabled,\r
- OUT BOOLEAN *Pending,\r
- OUT EFI_TIME *Time\r
- )\r
-{\r
- return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);\r
-}\r
-\r
-\r
-/**\r
- Sets the system wakeup alarm clock time.\r
-\r
- @param Enabled Enable or disable the wakeup alarm.\r
- @param Time If Enable is TRUE, the time to set the wakeup alarm for.\r
- If Enable is FALSE, then this parameter is optional, and may be NULL.\r
-\r
- @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.\r
- If Enable is FALSE, then the wakeup alarm was disabled.\r
- @retval EFI_INVALID_PARAMETER A time field is out of range.\r
- @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.\r
- @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PcRtcEfiSetWakeupTime (\r
- IN BOOLEAN Enabled,\r
- IN EFI_TIME *Time OPTIONAL\r
- )\r
-{\r
- return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);\r
-}\r
-\r
-/**\r
- The user Entry Point for PcRTC module.\r
-\r
- This is the entrhy point for PcRTC module. It installs the UEFI runtime service\r
- including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().\r
-\r
- @param ImageHandle The firmware allocated handle for the EFI image.\r
- @param SystemTable A pointer to the EFI System Table.\r
-\r
- @retval EFI_SUCCESS The entry point is executed successfully.\r
- @retval Others Some error occurs when executing this entry point.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializePcRtc (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);\r
-\r
- Status = PcRtcInit (&mModuleGlobal);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- gRT->GetTime = PcRtcEfiGetTime;\r
- gRT->SetTime = PcRtcEfiSetTime;\r
- gRT->GetWakeupTime = PcRtcEfiGetWakeupTime;\r
- gRT->SetWakeupTime = PcRtcEfiSetWakeupTime;\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mHandle,\r
- &gEfiRealTimeClockArchProtocolGuid,\r
- NULL,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-#/** @file\r
-#\r
-# PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL.\r
-#\r
-# This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.\r
-# It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.\r
-#\r
-# Copyright (c) 2006 - 2008 Intel Corporation. <BR>\r
-# All rights reserved. This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#**/\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = PcRtc\r
- FILE_GUID = 378D7B65-8DA9-4773-B6E4-A47826A833E1\r
- MODULE_TYPE = DXE_RUNTIME_DRIVER\r
- VERSION_STRING = 1.0\r
- ENTRY_POINT = InitializePcRtc\r
-\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-# VALID_ARCHITECTURES = IA32 X64 EBC\r
-#\r
-\r
-[Sources.common]\r
- PcRtcEntry.c\r
- PcRtc.c\r
- PcRtc.h\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
-\r
-[LibraryClasses]\r
- UefiRuntimeServicesTableLib\r
- UefiRuntimeLib\r
- UefiBootServicesTableLib\r
- UefiDriverEntryPoint\r
- TimerLib\r
- IoLib\r
- BaseMemoryLib\r
- UefiLib\r
- DebugLib\r
- BaseLib\r
- PcdLib\r
-\r
-[Protocols]\r
- gEfiRealTimeClockArchProtocolGuid ## PRODUCES\r
-\r
-[Depex]\r
- gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid\r
- \r
-[Pcd]\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout ## CONSUMES
\ No newline at end of file
--- /dev/null
+/** @file\r
+ RTC Architectural Protocol GUID as defined in DxeCis 0.96.\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PcRtc.h"\r
+\r
+/**\r
+ Compare the Hour, Minute and Second of the From time and the To time.\r
+ \r
+ Only compare H/M/S in EFI_TIME and ignore other fields here.\r
+\r
+ @param From the first time\r
+ @param To the second time\r
+\r
+ @return >0 The H/M/S of the From time is later than those of To time\r
+ @return ==0 The H/M/S of the From time is same as those of To time\r
+ @return <0 The H/M/S of the From time is earlier than those of To time\r
+**/\r
+INTN\r
+CompareHMS (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ );\r
+\r
+/**\r
+ To check if second date is later than first date within 24 hours.\r
+\r
+ @param From the first date\r
+ @param To the second date\r
+\r
+ @retval TRUE From is previous to To within 24 hours.\r
+ @retval FALSE From is later, or it is previous to To more than 24 hours.\r
+**/\r
+BOOLEAN\r
+IsWithinOneDay (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ );\r
+\r
+/**\r
+ Read RTC content through its registers.\r
+\r
+ @param Address Address offset of RTC. It is recommended to use macros such as\r
+ RTC_ADDRESS_SECONDS.\r
+\r
+ @return The data of UINT8 type read from RTC.\r
+**/\r
+UINT8\r
+RtcRead (\r
+ IN UINT8 Address\r
+ )\r
+{\r
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
+ return IoRead8 (PCAT_RTC_DATA_REGISTER);\r
+}\r
+\r
+/**\r
+ Write RTC through its registers.\r
+\r
+ @param Address Address offset of RTC. It is recommended to use macros such as\r
+ RTC_ADDRESS_SECONDS.\r
+ @param Data The content you want to write into RTC.\r
+\r
+**/\r
+VOID\r
+RtcWrite (\r
+ IN UINT8 Address,\r
+ IN UINT8 Data\r
+ )\r
+{\r
+ IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));\r
+ IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);\r
+}\r
+\r
+/**\r
+ Initialize RTC.\r
+\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_DEVICE_ERROR Initialization failed due to device error.\r
+ @retval EFI_SUCCESS Initialization successful.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcInit (\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ RTC_REGISTER_A RegisterA;\r
+ RTC_REGISTER_B RegisterB;\r
+ RTC_REGISTER_D RegisterD;\r
+ UINT8 Century;\r
+ EFI_TIME Time;\r
+ UINTN DataSize;\r
+ UINT32 TimerVar;\r
+\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiAcquireLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Initialize RTC Register\r
+ //\r
+ // Make sure Division Chain is properly configured,\r
+ // or RTC clock won't "tick" -- time won't increment\r
+ //\r
+ RegisterA.Data = RTC_INIT_REGISTER_A;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);\r
+\r
+ //\r
+ // Read Register B\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+\r
+ //\r
+ // Clear RTC flag register\r
+ //\r
+ RtcRead (RTC_ADDRESS_REGISTER_C);\r
+\r
+ //\r
+ // Clear RTC register D\r
+ //\r
+ RegisterD.Data = RTC_INIT_REGISTER_D;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);\r
+\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
+ if (EFI_ERROR (Status)) {\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Get the Time/Date/Daylight Savings values.\r
+ //\r
+ Time.Second = RtcRead (RTC_ADDRESS_SECONDS);\r
+ Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
+ Time.Hour = RtcRead (RTC_ADDRESS_HOURS);\r
+ Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time.Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time.Year = RtcRead (RTC_ADDRESS_YEAR);\r
+\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
+ \r
+ //\r
+ // Set RTC configuration after get original time\r
+ // The value of bit AIE should be reserved.\r
+ //\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, (UINT8)(RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5)));\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ \r
+ //\r
+ // Validate time fields\r
+ //\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
+ Time.Hour = RTC_INIT_HOUR;\r
+ Time.Day = RTC_INIT_DAY;\r
+ Time.Month = RTC_INIT_MONTH;\r
+ Time.Year = RTC_INIT_YEAR;\r
+ }\r
+ //\r
+ // Get the data of Daylight saving and time zone, if they have been\r
+ // stored in NV variable during previous boot.\r
+ //\r
+ DataSize = sizeof (UINT32);\r
+ Status = EfiGetVariable (\r
+ L"RTC",\r
+ &gEfiCallerIdGuid,\r
+ NULL,\r
+ &DataSize,\r
+ (VOID *) &TimerVar\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Global->SavedTimeZone = (INT16) TimerVar;\r
+ Global->Daylight = (UINT8) (TimerVar >> 16);\r
+\r
+ Time.TimeZone = Global->SavedTimeZone;\r
+ Time.Daylight = Global->Daylight;\r
+ }\r
+ //\r
+ // Reset time value according to new RTC configuration\r
+ //\r
+ PcRtcSetTime (&Time, Global);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Returns the current time and date information, and the time-keeping capabilities\r
+ of the hardware platform.\r
+\r
+ @param Time A pointer to storage to receive a snapshot of the current time.\r
+ @param Capabilities An optional pointer to a buffer to receive the real time clock\r
+ device's capabilities.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcGetTime (\r
+ OUT EFI_TIME *Time,\r
+ OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ RTC_REGISTER_B RegisterB;\r
+ UINT8 Century;\r
+\r
+ //\r
+ // Check parameters for null pointer\r
+ //\r
+ if (Time == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+\r
+ }\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiAcquireLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
+ if (EFI_ERROR (Status)) {\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ return Status;\r
+ }\r
+ //\r
+ // Read Register B\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+\r
+ //\r
+ // Get the Time/Date/Daylight Savings values.\r
+ //\r
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS);\r
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);\r
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS);\r
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
+\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
+ \r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Get the variable that contains the TimeZone and Daylight fields\r
+ //\r
+ Time->TimeZone = Global->SavedTimeZone;\r
+ Time->Daylight = Global->Daylight;\r
+\r
+ //\r
+ // Make sure all field values are in correct range\r
+ //\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
+ // Fill in Capabilities if it was passed in\r
+ //\r
+ if (Capabilities != NULL) {\r
+ Capabilities->Resolution = 1;\r
+ //\r
+ // 1 hertz\r
+ //\r
+ Capabilities->Accuracy = 50000000;\r
+ //\r
+ // 50 ppm\r
+ //\r
+ Capabilities->SetsToZero = FALSE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Sets the current local time and date information.\r
+\r
+ @param Time A pointer to the current time.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER A time field is out of range.\r
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcSetTime (\r
+ IN EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TIME RtcTime;\r
+ RTC_REGISTER_B RegisterB;\r
+ UINT8 Century;\r
+ UINT32 TimerVar;\r
+\r
+ if (Time == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Make sure that the time fields are valid\r
+ //\r
+ Status = RtcTimeFieldsValid (Time);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
+\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiAcquireLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
+ if (EFI_ERROR (Status)) {\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ return Status;\r
+ }\r
+ //\r
+ // Read Register B, and inhibit updates of the RTC\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+ RegisterB.Bits.SET = 1;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
+\r
+ RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);\r
+ RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);\r
+ RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);\r
+ RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);\r
+ RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);\r
+ RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);\r
+ RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
+\r
+ //\r
+ // Allow updates of the RTC registers\r
+ //\r
+ RegisterB.Bits.SET = 0;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Set the variable that contains the TimeZone and Daylight fields\r
+ //\r
+ Global->SavedTimeZone = Time->TimeZone;\r
+ Global->Daylight = Time->Daylight;\r
+\r
+ TimerVar = Time->Daylight;\r
+ TimerVar = (UINT32) ((TimerVar << 16) | Time->TimeZone);\r
+ Status = EfiSetVariable (\r
+ L"RTC",\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (TimerVar),\r
+ &TimerVar\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Returns the current wakeup alarm clock setting.\r
+\r
+ @param Enabled Indicates if the alarm is currently enabled or disabled.\r
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgment.\r
+ @param Time The current alarm setting.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS The alarm settings were returned.\r
+ @retval EFI_INVALID_PARAMETER Enabled is NULL.\r
+ @retval EFI_INVALID_PARAMETER Pending is NULL.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.\r
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ RTC_REGISTER_B RegisterB;\r
+ RTC_REGISTER_C RegisterC;\r
+ UINT8 Century;\r
+\r
+ //\r
+ // Check parameters for null pointers\r
+ //\r
+ if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+\r
+ }\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiAcquireLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
+ if (EFI_ERROR (Status)) {\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Read Register B and Register C\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+ RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);\r
+\r
+ //\r
+ // Get the Time/Date/Daylight Savings values.\r
+ //\r
+ *Enabled = RegisterB.Bits.AIE;\r
+ if (*Enabled) {\r
+ Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);\r
+ Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);\r
+ Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);\r
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
+ } else {\r
+ Time->Second = 0;\r
+ Time->Minute = 0;\r
+ Time->Hour = 0;\r
+ Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);\r
+ Time->Month = RtcRead (RTC_ADDRESS_MONTH);\r
+ Time->Year = RtcRead (RTC_ADDRESS_YEAR);\r
+ }\r
+\r
+ Century = RtcRead (RTC_ADDRESS_CENTURY);\r
+ \r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Make sure all field values are in correct range\r
+ //\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
+ *Pending = RegisterC.Bits.AF;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Sets the system wakeup alarm clock time.\r
+\r
+ @param Enabled Enable or disable the wakeup alarm.\r
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.\r
+ If Enable is FALSE, then this parameter is optional, and may be NULL.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.\r
+ If Enable is FALSE, then the wakeup alarm was disabled.\r
+ @retval EFI_INVALID_PARAMETER A time field is out of range.\r
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.\r
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcSetWakeupTime (\r
+ IN BOOLEAN Enable,\r
+ IN EFI_TIME *Time, OPTIONAL\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TIME RtcTime;\r
+ RTC_REGISTER_B RegisterB;\r
+ UINT8 Century;\r
+ EFI_TIME_CAPABILITIES Capabilities;\r
+\r
+ if (Enable) {\r
+\r
+ if (Time == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Make sure that the time fields are valid\r
+ //\r
+ Status = RtcTimeFieldsValid (Time);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Just support set alarm time within 24 hours\r
+ //\r
+ PcRtcGetTime (&RtcTime, &Capabilities, Global);\r
+ Status = RtcTimeFieldsValid (&RtcTime);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ if (!IsWithinOneDay (&RtcTime, Time)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Make a local copy of the time and date\r
+ //\r
+ CopyMem (&RtcTime, Time, sizeof (EFI_TIME));\r
+\r
+ }\r
+ //\r
+ // Acquire RTC Lock to make access to RTC atomic\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiAcquireLock (&Global->RtcLock);\r
+ }\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be updated\r
+ //\r
+ Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\r
+ if (EFI_ERROR (Status)) {\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Read Register B, and inhibit updates of the RTC\r
+ //\r
+ RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
+\r
+ RegisterB.Bits.SET = 1;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ if (Enable) {\r
+ ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
+\r
+ //\r
+ // Set RTC alarm time\r
+ //\r
+ RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);\r
+ RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);\r
+ RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);\r
+\r
+ RegisterB.Bits.AIE = 1;\r
+\r
+ } else {\r
+ RegisterB.Bits.AIE = 0;\r
+ }\r
+ //\r
+ // Allow updates of the RTC registers\r
+ //\r
+ RegisterB.Bits.SET = 0;\r
+ RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
+\r
+ //\r
+ // Release RTC Lock.\r
+ //\r
+ //Code here doesn't consider the runtime environment.\r
+ if (!EfiAtRuntime ()) {\r
+ EfiReleaseLock (&Global->RtcLock);\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\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. Or 0xff if Value is invalid.\r
+\r
+**/\r
+UINT8\r
+CheckAndConvertBcd8ToDecimal8 (\r
+ IN UINT8 Value\r
+ )\r
+{\r
+ if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {\r
+ return BcdToDecimal8 (Value);\r
+ }\r
+\r
+ return 0xff;\r
+}\r
+\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
+ @retval EFI_INVALID_PARAMETER Parameters passed in are invalid.\r
+ @retval EFI_SUCCESS Convert RTC time to EFI time successfully.\r
+\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 IsPM;\r
+\r
+ if ((Time->Hour & 0x80) != 0) {\r
+ IsPM = TRUE;\r
+ } else {\r
+ IsPM = FALSE;\r
+ }\r
+\r
+ Time->Hour = (UINT8) (Time->Hour & 0x7f);\r
+\r
+ if (RegisterB.Bits.DM == 0) {\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
+ }\r
+ Century = CheckAndConvertBcd8ToDecimal8 (Century);\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
+ if (RegisterB.Bits.MIL == 0) {\r
+ if (IsPM && Time->Hour < 12) {\r
+ Time->Hour = (UINT8) (Time->Hour + 12);\r
+ }\r
+\r
+ if (!IsPM && Time->Hour == 12) {\r
+ Time->Hour = 0;\r
+ }\r
+ }\r
+\r
+ Time->Nanosecond = 0;\r
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
+ Time->Daylight = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Wait for a period for the RTC to be ready.\r
+\r
+ @param Timeout Tell how long it should take to wait.\r
+\r
+ @retval EFI_DEVICE_ERROR RTC device error.\r
+ @retval EFI_SUCCESS RTC is updated and ready. \r
+**/\r
+EFI_STATUS\r
+RtcWaitToUpdate (\r
+ UINTN Timeout\r
+ )\r
+{\r
+ RTC_REGISTER_A RegisterA;\r
+ RTC_REGISTER_D RegisterD;\r
+\r
+ //\r
+ // See if the RTC is functioning correctly\r
+ //\r
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
+\r
+ if (RegisterD.Bits.VRT == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Wait for up to 0.1 seconds for the RTC to be ready.\r
+ //\r
+ Timeout = (Timeout / 10) + 1;\r
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
+ while (RegisterA.Bits.UIP == 1 && Timeout > 0) {\r
+ MicroSecondDelay (10);\r
+ RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);\r
+ Timeout--;\r
+ }\r
+\r
+ RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);\r
+ if (Timeout == 0 || RegisterD.Bits.VRT == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ See if all fields of a variable of EFI_TIME type is correct.\r
+\r
+ @param Time The time to be checked.\r
+\r
+ @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.\r
+ @retval EFI_SUCCESS Time is a valid EFI_TIME variable.\r
+\r
+**/\r
+EFI_STATUS\r
+RtcTimeFieldsValid (\r
+ IN EFI_TIME *Time\r
+ )\r
+{\r
+ if (Time->Year < 1998 ||\r
+ Time->Year > 2099 ||\r
+ Time->Month < 1 ||\r
+ Time->Month > 12 ||\r
+ Time->Hour > 23 ||\r
+ Time->Minute > 59 ||\r
+ Time->Second > 59 ||\r
+ Time->Nanosecond > 999999999 ||\r
+ (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||\r
+ ((Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) != 0)\r
+ ) {\r
+ if (!DayValid (Time)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ See if field Day of an EFI_TIME is correct.\r
+\r
+ @param Time Its Day field is to be checked.\r
+\r
+ @retval TRUE Day field of Time is correct.\r
+ @retval FALSE Day field of Time is NOT correct.\r
+**/\r
+BOOLEAN\r
+DayValid (\r
+ IN EFI_TIME *Time\r
+ )\r
+{\r
+ INTN DayOfMonth[12];\r
+\r
+ DayOfMonth[0] = 31;\r
+ DayOfMonth[1] = 29;\r
+ DayOfMonth[2] = 31;\r
+ DayOfMonth[3] = 30;\r
+ DayOfMonth[4] = 31;\r
+ DayOfMonth[5] = 30;\r
+ DayOfMonth[6] = 31;\r
+ DayOfMonth[7] = 31;\r
+ DayOfMonth[8] = 30;\r
+ DayOfMonth[9] = 31;\r
+ DayOfMonth[10] = 30;\r
+ DayOfMonth[11] = 31;\r
+\r
+ //\r
+ // The validity of Time->Month field should be checked before\r
+ //\r
+ ASSERT (Time->Month >=1);\r
+ ASSERT (Time->Month <=12);\r
+ if (Time->Day < 1 ||\r
+ Time->Day > DayOfMonth[Time->Month - 1] ||\r
+ (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
+ ) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Check if it is a leap year.\r
+\r
+ @param Time The time to be checked.\r
+\r
+ @retval TRUE It is a leap year.\r
+ @retval FALSE It is NOT a leap year.\r
+**/\r
+BOOLEAN\r
+IsLeapYear (\r
+ IN EFI_TIME *Time\r
+ )\r
+{\r
+ if (Time->Year % 4 == 0) {\r
+ if (Time->Year % 100 == 0) {\r
+ if (Time->Year % 400 == 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+ } else {\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
+\r
+ This function converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
+ If data mode of RTC is BCD, then converts EFI_TIME to it.\r
+ If RTC is in 12-hour format, then converts EFI_TIME to it.\r
+\r
+ @param Time On input, the time data read from UEFI to convert\r
+ On output, the time converted to RTC format\r
+ @param RegisterB Value of Register B of RTC, indicating data mode\r
+ @param Century It is set according to EFI_TIME Time.\r
+\r
+**/\r
+VOID\r
+ConvertEfiTimeToRtcTime (\r
+ IN OUT EFI_TIME *Time,\r
+ IN RTC_REGISTER_B RegisterB,\r
+ OUT UINT8 *Century\r
+ )\r
+{\r
+ BOOLEAN IsPM;\r
+\r
+ IsPM = TRUE;\r
+ //\r
+ // Adjust hour field if RTC is in 12 hour mode\r
+ //\r
+ if (RegisterB.Bits.MIL == 0) {\r
+ if (Time->Hour < 12) {\r
+ IsPM = FALSE;\r
+ }\r
+\r
+ if (Time->Hour >= 13) {\r
+ Time->Hour = (UINT8) (Time->Hour - 12);\r
+ } else if (Time->Hour == 0) {\r
+ Time->Hour = 12;\r
+ }\r
+ }\r
+ //\r
+ // Set the Time/Date/Daylight Savings values.\r
+ //\r
+ *Century = DecimalToBcd8 ((UINT8) (Time->Year / 100));\r
+\r
+ Time->Year = (UINT16) (Time->Year % 100);\r
+\r
+ if (RegisterB.Bits.DM == 0) {\r
+ Time->Year = DecimalToBcd8 ((UINT8) Time->Year);\r
+ Time->Month = DecimalToBcd8 (Time->Month);\r
+ Time->Day = DecimalToBcd8 (Time->Day);\r
+ Time->Hour = DecimalToBcd8 (Time->Hour);\r
+ Time->Minute = DecimalToBcd8 (Time->Minute);\r
+ Time->Second = DecimalToBcd8 (Time->Second);\r
+ }\r
+ //\r
+ // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.\r
+ //\r
+ if (RegisterB.Bits.MIL == 0 && IsPM) {\r
+ Time->Hour = (UINT8) (Time->Hour | 0x80);\r
+ }\r
+}\r
+\r
+/**\r
+ Compare the Hour, Minute and Second of the From time and the To time.\r
+ \r
+ Only compare H/M/S in EFI_TIME and ignore other fields here.\r
+\r
+ @param From the first time\r
+ @param To the second time\r
+\r
+ @return >0 The H/M/S of the From time is later than those of To time\r
+ @return ==0 The H/M/S of the From time is same as those of To time\r
+ @return <0 The H/M/S of the From time is earlier than those of To time\r
+**/\r
+INTN\r
+CompareHMS (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ )\r
+{\r
+ if ((From->Hour > To->Hour) ||\r
+ ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||\r
+ ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second))) {\r
+ return 1;\r
+ } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {\r
+ return 0;\r
+ } else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+/**\r
+ To check if second date is later than first date within 24 hours.\r
+\r
+ @param From the first date\r
+ @param To the second date\r
+\r
+ @retval TRUE From is previous to To within 24 hours.\r
+ @retval FALSE From is later, or it is previous to To more than 24 hours.\r
+**/\r
+BOOLEAN\r
+IsWithinOneDay (\r
+ IN EFI_TIME *From,\r
+ IN EFI_TIME *To\r
+ )\r
+{\r
+ UINT8 DayOfMonth[12];\r
+ BOOLEAN Adjacent;\r
+\r
+ DayOfMonth[0] = 31;\r
+ DayOfMonth[1] = 29;\r
+ DayOfMonth[2] = 31;\r
+ DayOfMonth[3] = 30;\r
+ DayOfMonth[4] = 31;\r
+ DayOfMonth[5] = 30;\r
+ DayOfMonth[6] = 31;\r
+ DayOfMonth[7] = 31;\r
+ DayOfMonth[8] = 30;\r
+ DayOfMonth[9] = 31;\r
+ DayOfMonth[10] = 30;\r
+ DayOfMonth[11] = 31;\r
+\r
+ Adjacent = FALSE;\r
+\r
+ //\r
+ // The validity of From->Month field should be checked before\r
+ //\r
+ ASSERT (From->Month >=1);\r
+ ASSERT (From->Month <=12);\r
+ \r
+ if (From->Year == To->Year) {\r
+ if (From->Month == To->Month) {\r
+ if ((From->Day + 1) == To->Day) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ } else if (From->Day == To->Day) {\r
+ if ((CompareHMS(From, To) <= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+ } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {\r
+ if ((From->Month == 2) && !IsLeapYear(From)) {\r
+ if (From->Day == 28) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+ } else if (From->Day == DayOfMonth[From->Month - 1]) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+ }\r
+ } else if (((From->Year + 1) == To->Year) &&\r
+ (From->Month == 12) &&\r
+ (From->Day == 31) &&\r
+ (To->Month == 1) &&\r
+ (To->Day == 1)) {\r
+ if ((CompareHMS(From, To) >= 0)) {\r
+ Adjacent = TRUE;\r
+ }\r
+ }\r
+\r
+ return Adjacent;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Header file for real time clock driver.\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#ifndef _RTC_H_\r
+#define _RTC_H_\r
+\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/RealTimeClock.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+\r
+typedef struct {\r
+ EFI_LOCK RtcLock;\r
+ INT16 SavedTimeZone;\r
+ UINT8 Daylight;\r
+} PC_RTC_MODULE_GLOBALS;\r
+\r
+#define PCAT_RTC_ADDRESS_REGISTER 0x70\r
+#define PCAT_RTC_DATA_REGISTER 0x71\r
+\r
+//\r
+// Dallas DS12C887 Real Time Clock\r
+//\r
+#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59\r
+#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59\r
+#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59\r
+#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59\r
+#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
+#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM\r
+#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7\r
+#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31\r
+#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12\r
+#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99\r
+#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]\r
+#define RTC_ADDRESS_REGISTER_B 11 // R/W\r
+#define RTC_ADDRESS_REGISTER_C 12 // RO\r
+#define RTC_ADDRESS_REGISTER_D 13 // RO\r
+#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W\r
+//\r
+// Date and time initial values.\r
+// They are used if the RTC values are invalid during driver initialization\r
+//\r
+#define RTC_INIT_SECOND 0\r
+#define RTC_INIT_MINUTE 0\r
+#define RTC_INIT_HOUR 0\r
+#define RTC_INIT_DAY 1\r
+#define RTC_INIT_MONTH 1\r
+#define RTC_INIT_YEAR 2001\r
+\r
+//\r
+// Register initial values\r
+//\r
+#define RTC_INIT_REGISTER_A 0x26\r
+#define RTC_INIT_REGISTER_B 0x02\r
+#define RTC_INIT_REGISTER_D 0x0\r
+\r
+#pragma pack(1)\r
+//\r
+// Register A\r
+//\r
+typedef struct {\r
+ UINT8 RS : 4; // Rate Selection Bits\r
+ UINT8 DV : 3; // Divisor\r
+ UINT8 UIP : 1; // Update in progress\r
+} RTC_REGISTER_A_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_A_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_A;\r
+\r
+//\r
+// Register B\r
+//\r
+typedef struct {\r
+ UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled\r
+ UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode\r
+ UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format\r
+ UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output\r
+ UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled\r
+ UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled\r
+ UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled\r
+ UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited\r
+} RTC_REGISTER_B_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_B_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_B;\r
+\r
+//\r
+// Register C\r
+//\r
+typedef struct {\r
+ UINT8 Reserved : 4; // Read as zero. Can not be written.\r
+ UINT8 UF : 1; // Update End Interrupt Flag\r
+ UINT8 AF : 1; // Alarm Interrupt Flag\r
+ UINT8 PF : 1; // Periodic Interrupt Flag\r
+ UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE\r
+} RTC_REGISTER_C_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_C_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_C;\r
+\r
+//\r
+// Register D\r
+//\r
+typedef struct {\r
+ UINT8 Reserved : 7; // Read as zero. Can not be written.\r
+ UINT8 VRT : 1; // Valid RAM and Time\r
+} RTC_REGISTER_D_BITS;\r
+\r
+typedef union {\r
+ RTC_REGISTER_D_BITS Bits;\r
+ UINT8 Data;\r
+} RTC_REGISTER_D;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+ Initialize RTC.\r
+\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_DEVICE_ERROR Initialization failed due to device error.\r
+ @retval EFI_SUCCESS Initialization successful.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcInit (\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ );\r
+\r
+/**\r
+ Sets the current local time and date information.\r
+\r
+ @param Time A pointer to the current time.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER A time field is out of range.\r
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcSetTime (\r
+ IN EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ );\r
+\r
+/**\r
+ Returns the current time and date information, and the time-keeping capabilities\r
+ of the hardware platform.\r
+\r
+ @param Time A pointer to storage to receive a snapshot of the current time.\r
+ @param Capabilities An optional pointer to a buffer to receive the real time clock\r
+ device's capabilities.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcGetTime (\r
+ OUT EFI_TIME *Time,\r
+ OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ );\r
+\r
+/**\r
+ Sets the system wakeup alarm clock time.\r
+\r
+ @param Enabled Enable or disable the wakeup alarm.\r
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.\r
+ If Enable is FALSE, then this parameter is optional, and may be NULL.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.\r
+ If Enable is FALSE, then the wakeup alarm was disabled.\r
+ @retval EFI_INVALID_PARAMETER A time field is out of range.\r
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.\r
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcSetWakeupTime (\r
+ IN BOOLEAN Enable,\r
+ IN EFI_TIME *Time, OPTIONAL\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ );\r
+\r
+/**\r
+ Returns the current wakeup alarm clock setting.\r
+\r
+ @param Enabled Indicates if the alarm is currently enabled or disabled.\r
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.\r
+ @param Time The current alarm setting.\r
+ @param Global For global use inside this module.\r
+\r
+ @retval EFI_SUCCESS The alarm settings were returned.\r
+ @retval EFI_INVALID_PARAMETER Enabled is NULL.\r
+ @retval EFI_INVALID_PARAMETER Pending is NULL.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.\r
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+PcRtcGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time,\r
+ IN PC_RTC_MODULE_GLOBALS *Global\r
+ );\r
+\r
+/**\r
+ The user Entry Point for PcRTC module.\r
+\r
+ This is the entrhy point for PcRTC module. It installs the UEFI runtime service\r
+ including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval Others Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePcRtc (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+/**\r
+ See if all fields of a variable of EFI_TIME type is correct.\r
+\r
+ @param Time The time to be checked.\r
+\r
+ @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.\r
+ @retval EFI_SUCCESS Time is a valid EFI_TIME variable.\r
+\r
+**/\r
+EFI_STATUS\r
+RtcTimeFieldsValid (\r
+ IN EFI_TIME *Time\r
+ );\r
+\r
+/**\r
+ Converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
+\r
+ This function converts time from EFI_TIME format defined by UEFI spec to RTC's.\r
+ If data mode of RTC is BCD, then converts EFI_TIME to it.\r
+ If RTC is in 12-hour format, then converts EFI_TIME to it.\r
+\r
+ @param Time On input, the time data read from UEFI to convert\r
+ On output, the time converted to RTC format\r
+ @param RegisterB Value of Register B of RTC, indicating data mode\r
+ @param Century It is set according to EFI_TIME Time.\r
+\r
+**/\r
+VOID\r
+ConvertEfiTimeToRtcTime (\r
+ IN OUT EFI_TIME *Time,\r
+ IN RTC_REGISTER_B RegisterB,\r
+ OUT UINT8 *Century\r
+ );\r
+\r
+\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
+ @retval EFI_INVALID_PARAMETER Parameters passed in are invalid.\r
+ @retval EFI_SUCCESS Convert RTC time to EFI time successfully.\r
+\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
+/**\r
+ Wait for a period for the RTC to be ready.\r
+\r
+ @param Timeout Tell how long it should take to wait.\r
+\r
+ @retval EFI_DEVICE_ERROR RTC device error.\r
+ @retval EFI_SUCCESS RTC is updated and ready. \r
+**/\r
+EFI_STATUS\r
+RtcWaitToUpdate (\r
+ UINTN Timeout\r
+ );\r
+\r
+/**\r
+ See if field Day of an EFI_TIME is correct.\r
+\r
+ @param Time Its Day field is to be checked.\r
+\r
+ @retval TRUE Day field of Time is correct.\r
+ @retval FALSE Day field of Time is NOT correct.\r
+**/\r
+BOOLEAN\r
+DayValid (\r
+ IN EFI_TIME *Time\r
+ );\r
+\r
+/**\r
+ Check if it is a leapyear.\r
+\r
+ @param Time The time to be checked.\r
+\r
+ @retval TRUE It is a leapyear.\r
+ @retval FALSE It is NOT a leapyear.\r
+**/\r
+BOOLEAN\r
+IsLeapYear (\r
+ IN EFI_TIME *Time\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Provides Set/Get time operations.\r
+\r
+Copyright (c) 2006 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PcRtc.h"\r
+\r
+PC_RTC_MODULE_GLOBALS mModuleGlobal;\r
+\r
+EFI_HANDLE mHandle = NULL;\r
+\r
+\r
+/**\r
+ Returns the current time and date information, and the time-keeping capabilities\r
+ of the hardware platform.\r
+\r
+ @param Time A pointer to storage to receive a snapshot of the current time.\r
+ @param Capabilities An optional pointer to a buffer to receive the real time\r
+ clock device's capabilities.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiGetTime (\r
+ OUT EFI_TIME *Time,\r
+ OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL\r
+ )\r
+{\r
+ return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);\r
+}\r
+\r
+/**\r
+ Sets the current local time and date information.\r
+\r
+ @param Time A pointer to the current time.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER A time field is out of range.\r
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiSetTime (\r
+ IN EFI_TIME *Time\r
+ )\r
+{\r
+ return PcRtcSetTime (Time, &mModuleGlobal);\r
+}\r
+\r
+/**\r
+ Returns the current wakeup alarm clock setting.\r
+\r
+ @param Enabled Indicates if the alarm is currently enabled or disabled.\r
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.\r
+ @param Time The current alarm setting.\r
+\r
+ @retval EFI_SUCCESS The alarm settings were returned.\r
+ @retval EFI_INVALID_PARAMETER Enabled is NULL.\r
+ @retval EFI_INVALID_PARAMETER Pending is NULL.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.\r
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiGetWakeupTime (\r
+ OUT BOOLEAN *Enabled,\r
+ OUT BOOLEAN *Pending,\r
+ OUT EFI_TIME *Time\r
+ )\r
+{\r
+ return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);\r
+}\r
+\r
+\r
+/**\r
+ Sets the system wakeup alarm clock time.\r
+\r
+ @param Enabled Enable or disable the wakeup alarm.\r
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.\r
+ If Enable is FALSE, then this parameter is optional, and may be NULL.\r
+\r
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.\r
+ If Enable is FALSE, then the wakeup alarm was disabled.\r
+ @retval EFI_INVALID_PARAMETER A time field is out of range.\r
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.\r
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PcRtcEfiSetWakeupTime (\r
+ IN BOOLEAN Enabled,\r
+ IN EFI_TIME *Time OPTIONAL\r
+ )\r
+{\r
+ return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);\r
+}\r
+\r
+/**\r
+ The user Entry Point for PcRTC module.\r
+\r
+ This is the entrhy point for PcRTC module. It installs the UEFI runtime service\r
+ including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval Others Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePcRtc (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);\r
+\r
+ Status = PcRtcInit (&mModuleGlobal);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gRT->GetTime = PcRtcEfiGetTime;\r
+ gRT->SetTime = PcRtcEfiSetTime;\r
+ gRT->GetWakeupTime = PcRtcEfiGetWakeupTime;\r
+ gRT->SetWakeupTime = PcRtcEfiSetWakeupTime;\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mHandle,\r
+ &gEfiRealTimeClockArchProtocolGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+#/** @file\r
+#\r
+# PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL.\r
+#\r
+# This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.\r
+# It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.\r
+#\r
+# Copyright (c) 2006 - 2008 Intel Corporation. <BR>\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = PcRtc\r
+ FILE_GUID = 378D7B65-8DA9-4773-B6E4-A47826A833E1\r
+ MODULE_TYPE = DXE_RUNTIME_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = InitializePcRtc\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 EBC\r
+#\r
+\r
+[Sources.common]\r
+ PcRtcEntry.c\r
+ PcRtc.c\r
+ PcRtc.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiRuntimeServicesTableLib\r
+ UefiRuntimeLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ TimerLib\r
+ IoLib\r
+ BaseMemoryLib\r
+ UefiLib\r
+ DebugLib\r
+ BaseLib\r
+ PcdLib\r
+\r
+[Protocols]\r
+ gEfiRealTimeClockArchProtocolGuid ## PRODUCES\r
+\r
+[Depex]\r
+ gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid\r
+ \r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout ## CONSUMES
\ No newline at end of file