X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FPcatRealTimeClockRuntimeDxe%2FPcRtc.c;h=a82f5d133e34ba93187ddc19b91586f7e06bc342;hp=91e6b03f0b999ef7f655919c9e939a2bb88b7ca8;hb=c5ed97f62898afc846af1751ac10ae874f93e24c;hpb=1f4cf7b1ba400fa6b4ee29f9367312ac977ffe2d diff --git a/MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcRtc.c b/MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcRtc.c index 91e6b03f0b..a82f5d133e 100644 --- a/MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcRtc.c +++ b/MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcRtc.c @@ -1,6 +1,7 @@ -/*++ +/** @file + RTC Architectural Protocol GUID as defined in DxeCis 0.96. -Copyright (c) 2006 - 2007 Intel Corporation.
+Copyright (c) 2006 - 2007, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -9,35 +10,22 @@ http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - -Module Name: - - PcRtc.c - -Abstract: - - RTC Architectural Protocol GUID as defined in DxeCis 0.96 - ---*/ +**/ #include "PcRtc.h" -STATIC INTN CompareHMS ( IN EFI_TIME *From, IN EFI_TIME *To ); -STATIC BOOLEAN IsWithinOneDay ( IN EFI_TIME *From, IN EFI_TIME *To ); -STATIC UINT8 RtcRead ( IN UINT8 Address @@ -62,7 +50,6 @@ Returns: return IoRead8 (PCAT_RTC_DATA_REGISTER); } -STATIC VOID RtcWrite ( IN UINT8 Address, @@ -116,6 +103,8 @@ Returns: RTC_REGISTER_D RegisterD; UINT8 Century; EFI_TIME Time; + UINTN DataSize; + UINT32 TimerVar; // // Acquire RTC Lock to make access to RTC atomic @@ -153,7 +142,7 @@ Returns: // // Wait for up to 0.1 seconds for the RTC to be updated // - Status = RtcWaitToUpdate (100000); + Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout)); if (EFI_ERROR (Status)) { //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock @@ -172,33 +161,35 @@ Returns: Time.Month = RtcRead (RTC_ADDRESS_MONTH); Time.Year = RtcRead (RTC_ADDRESS_YEAR); - ConvertRtcTimeToEfiTime (&Time, RegisterB); - if (RtcTestCenturyRegister () == EFI_SUCCESS) { - Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); + Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f); } else { - Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY)); + Century = RtcRead (RTC_ADDRESS_CENTURY); } - Time.Year = (UINT16) (Century * 100 + Time.Year); - // // Set RTC configuration after get original time + // The value of bit AIE should be reserved. // - RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B); + RtcWrite (RTC_ADDRESS_REGISTER_B, (UINT8)(RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5))); // // Release RTC Lock. // //BugBug: the EfiAtRuntime should be encapsulated in EfiAcquireLock or // provide a new instance for EfiAcquireLock, say, RtEfiAcquireLock + // if (!EfiAtRuntime ()) { EfiReleaseLock (&Global->RtcLock); } + // // Validate time fields // - Status = RtcTimeFieldsValid (&Time); + Status = ConvertRtcTimeToEfiTime (&Time, Century, RegisterB); + if (!EFI_ERROR (Status)) { + Status = RtcTimeFieldsValid (&Time); + } if (EFI_ERROR (Status)) { Time.Second = RTC_INIT_SECOND; Time.Minute = RTC_INIT_MINUTE; @@ -208,6 +199,25 @@ Returns: Time.Year = RTC_INIT_YEAR; } // + // Get the data of Daylight saving and time zone, if they have been + // stored in NV variable during previous boot. + // + DataSize = sizeof (UINT32); + Status = EfiGetVariable ( + L"TimerVar", + &gEfiGenericPlatformVariableGuid, + NULL, + &DataSize, + (VOID *) &TimerVar + ); + if (!EFI_ERROR (Status)) { + Global->SavedTimeZone = (INT16) TimerVar; + Global->Daylight = (UINT8) (TimerVar >> 16); + + Time.TimeZone = Global->SavedTimeZone; + Time.Daylight = Global->Daylight; + } + // // Reset time value according to new RTC configuration // PcRtcSetTime (&Time, Global); @@ -258,7 +268,7 @@ Routine Description: // // Wait for up to 0.1 seconds for the RTC to be updated // - Status = RtcWaitToUpdate (100000); + Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout)); if (EFI_ERROR (Status)) { //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock @@ -282,16 +292,12 @@ Routine Description: Time->Month = RtcRead (RTC_ADDRESS_MONTH); Time->Year = RtcRead (RTC_ADDRESS_YEAR); - ConvertRtcTimeToEfiTime (Time, RegisterB); - if (RtcTestCenturyRegister () == EFI_SUCCESS) { - Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); + Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f); } else { - Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY)); + Century = RtcRead (RTC_ADDRESS_CENTURY); } - Time->Year = (UINT16) (Century * 100 + Time->Year); - // // Release RTC Lock. // @@ -309,7 +315,10 @@ Routine Description: // // Make sure all field values are in correct range // - Status = RtcTimeFieldsValid (Time); + Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB); + if (!EFI_ERROR (Status)) { + Status = RtcTimeFieldsValid (Time); + } if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -352,6 +361,7 @@ Routine Description: EFI_TIME RtcTime; RTC_REGISTER_B RegisterB; UINT8 Century; + UINT32 TimerVar; if (Time == NULL) { return EFI_INVALID_PARAMETER; @@ -377,7 +387,7 @@ Routine Description: // // Wait for up to 0.1 seconds for the RTC to be updated // - Status = RtcWaitToUpdate (100000); + Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout)); if (EFI_ERROR (Status)) { //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock @@ -426,7 +436,19 @@ Routine Description: // Global->SavedTimeZone = Time->TimeZone; Global->Daylight = Time->Daylight; - return Status; + + TimerVar = Time->Daylight; + TimerVar = (UINT32) ((TimerVar << 16) | Time->TimeZone); + Status = EfiSetVariable ( + L"TimerVar", + &gEfiGenericPlatformVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (TimerVar), + &TimerVar + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; } EFI_STATUS @@ -478,7 +500,7 @@ Returns: // // Wait for up to 0.1 seconds for the RTC to be updated // - Status = RtcWaitToUpdate (100000); + Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout)); if (EFI_ERROR (Status)) { //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock @@ -513,16 +535,12 @@ Returns: Time->Year = RtcRead (RTC_ADDRESS_YEAR); } - ConvertRtcTimeToEfiTime (Time, RegisterB); - if (RtcTestCenturyRegister () == EFI_SUCCESS) { - Century = BcdToDecimal8 ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f)); + Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f); } else { - Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY)); + Century = RtcRead (RTC_ADDRESS_CENTURY); } - Time->Year = (UINT16) (Century * 100 + Time->Year); - // // Release RTC Lock. // @@ -534,7 +552,10 @@ Returns: // // Make sure all field values are in correct range // - Status = RtcTimeFieldsValid (Time); + Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB); + if (!EFI_ERROR (Status)) { + Status = RtcTimeFieldsValid (Time); + } if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -611,7 +632,7 @@ Returns: // // Wait for up to 0.1 seconds for the RTC to be updated // - Status = RtcWaitToUpdate (100000); + Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout)); if (EFI_ERROR (Status)) { //BugBug: the EfiAtRuntime should be encapsulated in EfiReleaseLock or // provide a new instance for EfiReleaseLock, say, RtEfiReleaseLock @@ -693,23 +714,52 @@ Returns: return EFI_DEVICE_ERROR; } -VOID -ConvertRtcTimeToEfiTime ( - IN EFI_TIME *Time, - IN RTC_REGISTER_B RegisterB +/** + Checks an 8-bit BCD value, and converts to an 8-bit value if valid. + + This function checks the 8-bit BCD value specified by Value. + If valid, the function converts it to an 8-bit value and returns it. + Otherwise, return 0xff. + + @param Value The 8-bit BCD value to check and convert + + @return The 8-bit value converted. + 0xff if Value is invalid. + +**/ +UINT8 +CheckAndConvertBcd8ToDecimal8 ( + IN UINT8 Value ) -/*++ +{ + if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) { + return BcdToDecimal8 (Value); + } -Routine Description: + return 0xff; +} - Arguments: +/** + Converts time read from RTC to EFI_TIME format defined by UEFI spec. + This function converts raw time data read from RTC to the EFI_TIME format + defined by UEFI spec. + If data mode of RTC is BCD, then converts it to decimal, + If RTC is in 12-hour format, then converts it to 24-hour format. + @param Time On input, the time data read from RTC to convert + On output, the time converted to UEFI format + @param Century Value of century read from RTC. + @param RegisterB Value of Register B of RTC, indicating data mode + and hour format. -Returns: ---*/ -// GC_TODO: Time - add argument and description to function comment -// GC_TODO: RegisterB - add argument and description to function comment +**/ +EFI_STATUS +ConvertRtcTimeToEfiTime ( + IN OUT EFI_TIME *Time, + IN UINT8 Century, + IN RTC_REGISTER_B RegisterB + ) { BOOLEAN PM; @@ -722,13 +772,23 @@ Returns: Time->Hour = (UINT8) (Time->Hour & 0x7f); if (RegisterB.Bits.DM == 0) { - Time->Year = BcdToDecimal8 ((UINT8) Time->Year); - Time->Month = BcdToDecimal8 (Time->Month); - Time->Day = BcdToDecimal8 (Time->Day); - Time->Hour = BcdToDecimal8 (Time->Hour); - Time->Minute = BcdToDecimal8 (Time->Minute); - Time->Second = BcdToDecimal8 (Time->Second); + Time->Year = CheckAndConvertBcd8ToDecimal8 ((UINT8) Time->Year); + Time->Month = CheckAndConvertBcd8ToDecimal8 (Time->Month); + Time->Day = CheckAndConvertBcd8ToDecimal8 (Time->Day); + Time->Hour = CheckAndConvertBcd8ToDecimal8 (Time->Hour); + Time->Minute = CheckAndConvertBcd8ToDecimal8 (Time->Minute); + Time->Second = CheckAndConvertBcd8ToDecimal8 (Time->Second); + Century = CheckAndConvertBcd8ToDecimal8 (Century); + } + + if (Time->Year == 0xff || Time->Month == 0xff || Time->Day == 0xff || + Time->Hour == 0xff || Time->Minute == 0xff || Time->Second == 0xff || + Century == 0xff) { + return EFI_INVALID_PARAMETER; } + + Time->Year = (UINT16) (Century * 100 + Time->Year); + // // If time is in 12 hour format, convert it to 24 hour format // @@ -745,6 +805,8 @@ Returns: Time->Nanosecond = 0; Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; Time->Daylight = 0; + + return EFI_SUCCESS; } EFI_STATUS @@ -968,7 +1030,6 @@ Returns: } } -STATIC INTN CompareHMS ( IN EFI_TIME *From, @@ -1005,7 +1066,6 @@ Returns: } } -STATIC BOOLEAN IsWithinOneDay ( IN EFI_TIME *From,