]> git.proxmox.com Git - mirror_edk2.git/blobdiff - PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
Initialize alarm register in PcRtc module entrypoint to make UEFI SCT GetWakeupTime...
[mirror_edk2.git] / PcAtChipsetPkg / PcatRealTimeClockRuntimeDxe / PcRtc.c
index a77009a21765299e6e9160ed7993367652a21071..eb1a6567eedc85fce8e4e0a1b88ecf2f3669de2e 100644 (file)
@@ -104,6 +104,8 @@ PcRtcInit (
   EFI_TIME        Time;\r
   UINTN           DataSize;\r
   UINT32          TimerVar;\r
+  BOOLEAN         Enabled;\r
+  BOOLEAN         Pending;\r
 \r
   //\r
   // Acquire RTC Lock to make access to RTC atomic\r
@@ -226,11 +228,96 @@ PcRtcInit (
   // Reset time value according to new RTC configuration\r
   //\r
   Status = PcRtcSetTime (&Time, Global);\r
-  if(!EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  \r
+  //\r
+  // Reset wakeup time value to valid state when wakeup alarm is disabled and wakeup time is invalid.\r
+  // Global variable has already had valid SavedTimeZone and Daylight,\r
+  // so we can use them to get and set wakeup time.\r
+  //\r
+  Status = PcRtcGetWakeupTime (&Enabled, &Pending, &Time, Global);\r
+  if ((Enabled) || (!EFI_ERROR (Status))) {\r
     return EFI_SUCCESS;\r
-  } else {\r
+  }\r
+  \r
+  //\r
+  // When wakeup time is disabled and invalid, reset wakeup time register to valid state \r
+  // but keep wakeup alarm disabled.\r
+  //\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
+  Time.Nanosecond  = 0;\r
+  Time.TimeZone = Global->SavedTimeZone;\r
+  Time.Daylight = Global->Daylight;;\r
+\r
+  //\r
+  // Acquire RTC Lock to make access to RTC atomic\r
+  //\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
+    if (!EfiAtRuntime ()) {\r
+    EfiReleaseLock (&Global->RtcLock);\r
+    }\r
     return EFI_DEVICE_ERROR;\r
   }\r
+  \r
+  ConvertEfiTimeToRtcTime (&Time, RegisterB, &Century);\r
+\r
+  //\r
+  // Set the Y/M/D info to variable as it has no corresponding hw registers.\r
+  //\r
+  Status =  EfiSetVariable (\r
+              L"RTCALARM",\r
+              &gEfiCallerIdGuid,\r
+              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+              sizeof (Time),\r
+              &Time\r
+              );\r
+  if (EFI_ERROR (Status)) {\r
+    if (!EfiAtRuntime ()) {\r
+      EfiReleaseLock (&Global->RtcLock);\r
+    }\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  \r
+  //\r
+  // Inhibit updates of the RTC\r
+  //\r
+  RegisterB.Bits.Set  = 1;\r
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
\r
+  //\r
+  // Set RTC alarm time registers\r
+  //\r
+  RtcWrite (RTC_ADDRESS_SECONDS_ALARM, Time.Second);\r
+  RtcWrite (RTC_ADDRESS_MINUTES_ALARM, Time.Minute);\r
+  RtcWrite (RTC_ADDRESS_HOURS_ALARM, Time.Hour);\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
+  if (!EfiAtRuntime ()) {\r
+    EfiReleaseLock (&Global->RtcLock);\r
+  }\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r