From d431bf6e56bac6e8b457a6531932dec13f03933a Mon Sep 17 00:00:00 2001 From: Elvin Li Date: Tue, 25 Nov 2014 03:38:20 +0000 Subject: Initialize alarm register in PcRtc module entrypoint to make UEFI SCT GetWakeupTime pass. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Elvin Li Reviewed-by: Feng Tian Reviewed-by: Eric Jin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16425 6f19259b-4bc3-4df7-8a09-765794883524 --- PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c | 91 +++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c index a77009a217..eb1a6567ee 100644 --- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c +++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c @@ -104,6 +104,8 @@ PcRtcInit ( EFI_TIME Time; UINTN DataSize; UINT32 TimerVar; + BOOLEAN Enabled; + BOOLEAN Pending; // // Acquire RTC Lock to make access to RTC atomic @@ -226,11 +228,96 @@ PcRtcInit ( // Reset time value according to new RTC configuration // Status = PcRtcSetTime (&Time, Global); - if(!EFI_ERROR (Status)) { + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Reset wakeup time value to valid state when wakeup alarm is disabled and wakeup time is invalid. + // Global variable has already had valid SavedTimeZone and Daylight, + // so we can use them to get and set wakeup time. + // + Status = PcRtcGetWakeupTime (&Enabled, &Pending, &Time, Global); + if ((Enabled) || (!EFI_ERROR (Status))) { return EFI_SUCCESS; - } else { + } + + // + // When wakeup time is disabled and invalid, reset wakeup time register to valid state + // but keep wakeup alarm disabled. + // + Time.Second = RTC_INIT_SECOND; + Time.Minute = RTC_INIT_MINUTE; + Time.Hour = RTC_INIT_HOUR; + Time.Day = RTC_INIT_DAY; + Time.Month = RTC_INIT_MONTH; + Time.Year = RTC_INIT_YEAR; + Time.Nanosecond = 0; + Time.TimeZone = Global->SavedTimeZone; + Time.Daylight = Global->Daylight;; + + // + // Acquire RTC Lock to make access to RTC atomic + // + if (!EfiAtRuntime ()) { + EfiAcquireLock (&Global->RtcLock); + } + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout)); + if (EFI_ERROR (Status)) { + if (!EfiAtRuntime ()) { + EfiReleaseLock (&Global->RtcLock); + } return EFI_DEVICE_ERROR; } + + ConvertEfiTimeToRtcTime (&Time, RegisterB, &Century); + + // + // Set the Y/M/D info to variable as it has no corresponding hw registers. + // + Status = EfiSetVariable ( + L"RTCALARM", + &gEfiCallerIdGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (Time), + &Time + ); + if (EFI_ERROR (Status)) { + if (!EfiAtRuntime ()) { + EfiReleaseLock (&Global->RtcLock); + } + return EFI_DEVICE_ERROR; + } + + // + // Inhibit updates of the RTC + // + RegisterB.Bits.Set = 1; + RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); + + // + // Set RTC alarm time registers + // + RtcWrite (RTC_ADDRESS_SECONDS_ALARM, Time.Second); + RtcWrite (RTC_ADDRESS_MINUTES_ALARM, Time.Minute); + RtcWrite (RTC_ADDRESS_HOURS_ALARM, Time.Hour); + + // + // Allow updates of the RTC registers + // + RegisterB.Bits.Set = 0; + RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data); + + // + // Release RTC Lock. + // + if (!EfiAtRuntime ()) { + EfiReleaseLock (&Global->RtcLock); + } + return EFI_SUCCESS; } /** -- cgit v1.2.3