-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>\r
-This software and associated documentation (if any) is furnished\r
-under a license and may only be used or copied in accordance\r
-with the terms of the license. Except as permitted by such\r
-license, no part of this software or documentation may be\r
-reproduced, stored in a retrieval system, or transmitted in any\r
-form or by any means without the express written consent of\r
-Intel Corporation.\r
-\r
-\r
-\r
-Module Name:\r
-\r
- PcRtc.c\r
-\r
-Abstract:\r
-\r
- RTC Architectural Protocol GUID as defined in DxeCis 0.96\r
-\r
---*/\r
-\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
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Address - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\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
-STATIC\r
-VOID\r
-RtcWrite (\r
- IN UINT8 Address,\r
- IN UINT8 Data\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Address - GC_TODO: add argument description\r
- Data - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\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
-EFI_STATUS\r
-PcRtcInit (\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Global - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\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
-\r
- //\r
- // Acquire RTC Lock to make access to RTC atomic\r
- //\r
- //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
- // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\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 (100000);\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
- 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
- ConvertRtcTimeToEfiTime (&Time, RegisterB);\r
-\r
- if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
- } else {\r
- Century = BcdToDecimal8 (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
- //\r
- RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B);\r
-\r
- //\r
- // Release RTC Lock.\r
- //\r
- //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
- // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Validate time fields\r
- //\r
- Status = RtcTimeFieldsValid (&Time);\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
- // Reset time value according to new RTC configuration\r
- //\r
- PcRtcSetTime (&Time, Global);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-PcRtcGetTime (\r
- OUT EFI_TIME *Time,\r
- IN EFI_TIME_CAPABILITIES *Capabilities,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
- Returns:\r
---*/\r
-// GC_TODO: Time - add argument and description to function comment\r
-// GC_TODO: Capabilities - add argument and description to function comment\r
-// GC_TODO: Global - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\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
- //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
- // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\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 (100000);\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
- 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
- ConvertRtcTimeToEfiTime (Time, RegisterB);\r
-\r
- if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
- } else {\r
- Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
- }\r
-\r
- Time->Year = (UINT16) (Century * 100 + Time->Year);\r
-\r
- //\r
- // Release RTC Lock.\r
- //\r
- //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
- // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Get the variable that containts 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 = RtcTimeFieldsValid (Time);\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) {\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
-EFI_STATUS\r
-PcRtcSetTime (\r
- IN EFI_TIME *Time,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
- Returns:\r
---*/\r
-// GC_TODO: Time - add argument and description to function comment\r
-// GC_TODO: Global - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- EFI_TIME RtcTime;\r
- RTC_REGISTER_B RegisterB;\r
- UINT8 Century;\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
- //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
- // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\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 (100000);\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
- 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
- if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80));\r
- }\r
-\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
- //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
- // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Set the variable that containts the TimeZone and Daylight fields\r
- //\r
- Global->SavedTimeZone = Time->TimeZone;\r
- Global->Daylight = Time->Daylight;\r
- return Status;\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
-Routine Description:\r
-\r
- Arguments:\r
-\r
-\r
-\r
-Returns:\r
---*/\r
-// GC_TODO: Enabled - add argument and description to function comment\r
-// GC_TODO: Pending - add argument and description to function comment\r
-// GC_TODO: Time - add argument and description to function comment\r
-// GC_TODO: Global - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- RTC_REGISTER_B RegisterB;\r
- RTC_REGISTER_C RegisterC;\r
- UINT8 Century;\r
-\r
- //\r
- // Check paramters 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
- //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
- // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\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 (100000);\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
- 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
- ConvertRtcTimeToEfiTime (Time, RegisterB);\r
-\r
- if (RtcTestCenturyRegister () == EFI_SUCCESS) {\r
- Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));\r
- } else {\r
- Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
- }\r
-\r
- Time->Year = (UINT16) (Century * 100 + Time->Year);\r
-\r
- //\r
- // Release RTC Lock.\r
- //\r
- //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
- // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- //\r
- // Make sure all field values are in correct range\r
- //\r
- Status = RtcTimeFieldsValid (Time);\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
-EFI_STATUS\r
-PcRtcSetWakeupTime (\r
- IN BOOLEAN Enable,\r
- OUT EFI_TIME *Time,\r
- IN PC_RTC_MODULE_GLOBALS *Global\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
-\r
-\r
-Returns:\r
---*/\r
-// GC_TODO: Enable - add argument and description to function comment\r
-// GC_TODO: Time - add argument and description to function comment\r
-// GC_TODO: Global - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// GC_TODO: EFI_UNSUPPORTED - add return value to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\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
- 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
- //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or\r
- // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock\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 (100000);\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
- 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
- //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or\r
- // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock\r
- if (!EfiAtRuntime ()) {\r
- EfiReleaseLock (&Global->RtcLock);\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-RtcTestCenturyRegister (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
-\r
-\r
-Returns:\r
---*/\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-{\r
- UINT8 Century;\r
- UINT8 Temp;\r
-\r
- Century = RtcRead (RTC_ADDRESS_CENTURY);\r
- //\r
- // RtcWrite (RTC_ADDRESS_CENTURY, 0x00);\r
- //\r
- Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
- RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
- if (Temp == 0x19 || Temp == 0x20) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return EFI_DEVICE_ERROR;\r
-}\r
-\r
-VOID\r
-ConvertRtcTimeToEfiTime (\r
- IN EFI_TIME *Time,\r
- IN RTC_REGISTER_B RegisterB\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
-\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
- BOOLEAN PM;\r
-\r
- if ((Time->Hour) & 0x80) {\r
- PM = TRUE;\r
- } else {\r
- PM = FALSE;\r
- }\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
- }\r
- //\r
- // If time is in 12 hour format, convert it to 24 hour format\r
- //\r
- if (RegisterB.Bits.MIL == 0) {\r
- if (PM && Time->Hour < 12) {\r
- Time->Hour = (UINT8) (Time->Hour + 12);\r
- }\r
-\r
- if (!PM && 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
-\r
-EFI_STATUS\r
-RtcWaitToUpdate (\r
- UINTN Timeout\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
-\r
-Returns:\r
---*/\r
-// GC_TODO: Timeout - add argument and description to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\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
-EFI_STATUS\r
-RtcTimeFieldsValid (\r
- IN EFI_TIME *Time\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\r
- Returns:\r
---*/\r
-// GC_TODO: Time - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- if (Time->Year < 1998 ||\r
- Time->Year > 2099 ||\r
- Time->Month < 1 ||\r
- Time->Month > 12 ||\r
- (!DayValid (Time)) ||\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)))\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-DayValid (\r
- IN EFI_TIME *Time\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Time - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\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
- 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
-BOOLEAN\r
-IsLeapYear (\r
- IN EFI_TIME *Time\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Time - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\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
-VOID\r
-ConvertEfiTimeToRtcTime (\r
- IN EFI_TIME *Time,\r
- IN RTC_REGISTER_B RegisterB,\r
- IN UINT8 *Century\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Arguments:\r
-\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
-// GC_TODO: Century - add argument and description to function comment\r
-{\r
- BOOLEAN PM;\r
-\r
- PM = TRUE;\r
- //\r
- // Adjust hour field if RTC in in 12 hour mode\r
- //\r
- if (RegisterB.Bits.MIL == 0) {\r
- if (Time->Hour < 12) {\r
- PM = 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 && PM) {\r
- Time->Hour = (UINT8) (Time->Hour | 0x80);\r
- }\r
-}\r
-\r
-STATIC\r
-INTN\r
-CompareHMS (\r
- IN EFI_TIME *From,\r
- IN EFI_TIME *To\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Compare the Hour, Minute and Second of the 'From' time and the 'To' time.\r
- Only compare H/M/S in EFI_TIME and ignore other fields here.\r
-\r
-Arguments:\r
-\r
- From - the first time\r
- To - the second time\r
-\r
-Returns:\r
-\r
- >0 : The H/M/S of the 'From' time is later than those of 'To' time\r
- ==0 : The H/M/S of the 'From' time is same as those of 'To' time\r
- <0 : The H/M/S of the 'From' time is earlier than those of 'To' time\r
-\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
-STATIC\r
-BOOLEAN\r
-IsWithinOneDay (\r
- IN EFI_TIME *From,\r
- IN EFI_TIME *To\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Judge whether two days are adjacent.\r
-\r
-Arguments:\r
-\r
- From - the first day\r
- To - the second day\r
-\r
-Returns:\r
-\r
- TRUE - The interval of two days are within one day.\r
- FALSE - The interval of two days exceed ony day or parameter error.\r
-\r
---*/\r
-{\r
- UINT8 DayOfMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};\r
- BOOLEAN Adjacent = FALSE;\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