]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcRtc.c
Code Scrub for ConPlatform.
[mirror_edk2.git] / MdeModulePkg / Universal / PcatRealTimeClockRuntimeDxe / PcRtc.c
index 91e6b03f0b999ef7f655919c9e939a2bb88b7ca8..a82f5d133e34ba93187ddc19b91586f7e06bc342 100644 (file)
@@ -1,6 +1,7 @@
-/*++\r
+/** @file\r
+  RTC Architectural Protocol GUID as defined in DxeCis 0.96.\r
 \r
-Copyright (c) 2006 - 2007 Intel Corporation. <BR>\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
@@ -9,35 +10,22 @@ http://opensource.org/licenses/bsd-license.php
 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
-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
 \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
@@ -62,7 +50,6 @@ Returns:
   return IoRead8 (PCAT_RTC_DATA_REGISTER);\r
 }\r
 \r
-STATIC\r
 VOID\r
 RtcWrite (\r
   IN  UINT8   Address,\r
@@ -116,6 +103,8 @@ Returns:
   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
@@ -153,7 +142,7 @@ Returns:
   //\r
   // Wait for up to 0.1 seconds for the RTC to be updated\r
   //\r
-  Status = RtcWaitToUpdate (100000);\r
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\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
@@ -172,33 +161,35 @@ Returns:
   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
+    Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
   } else {\r
-    Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
+    Century = 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
+  // The value of bit AIE should be reserved.\r
   //\r
-  RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B);\r
+  RtcWrite (RTC_ADDRESS_REGISTER_B, (UINT8)(RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5)));\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
+  //\r
   if (!EfiAtRuntime ()) {\r
   EfiReleaseLock (&Global->RtcLock);\r
   }\r
\r
   //\r
   // Validate time fields\r
   //\r
-  Status = RtcTimeFieldsValid (&Time);\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
@@ -208,6 +199,25 @@ Returns:
     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"TimerVar",\r
+             &gEfiGenericPlatformVariableGuid,\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
@@ -258,7 +268,7 @@ Routine Description:
   //\r
   // Wait for up to 0.1 seconds for the RTC to be updated\r
   //\r
-  Status = RtcWaitToUpdate (100000);\r
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\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
@@ -282,16 +292,12 @@ Routine Description:
   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
+    Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
   } else {\r
-    Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
+    Century = RtcRead (RTC_ADDRESS_CENTURY);\r
   }\r
 \r
-  Time->Year = (UINT16) (Century * 100 + Time->Year);\r
-\r
   //\r
   // Release RTC Lock.\r
   //\r
@@ -309,7 +315,10 @@ Routine Description:
   //\r
   // Make sure all field values are in correct range\r
   //\r
-  Status = RtcTimeFieldsValid (Time);\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
@@ -352,6 +361,7 @@ Routine Description:
   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
@@ -377,7 +387,7 @@ Routine Description:
   //\r
   // Wait for up to 0.1 seconds for the RTC to be updated\r
   //\r
-  Status = RtcWaitToUpdate (100000);\r
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\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
@@ -426,7 +436,19 @@ Routine Description:
   //\r
   Global->SavedTimeZone = Time->TimeZone;\r
   Global->Daylight      = Time->Daylight;\r
-  return Status;\r
+\r
+  TimerVar = Time->Daylight;\r
+  TimerVar = (UINT32) ((TimerVar << 16) | Time->TimeZone);\r
+  Status =  EfiSetVariable (\r
+              L"TimerVar",\r
+              &gEfiGenericPlatformVariableGuid,\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
 EFI_STATUS\r
@@ -478,7 +500,7 @@ Returns:
   //\r
   // Wait for up to 0.1 seconds for the RTC to be updated\r
   //\r
-  Status = RtcWaitToUpdate (100000);\r
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\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
@@ -513,16 +535,12 @@ Returns:
     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
+    Century = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);\r
   } else {\r
-    Century = BcdToDecimal8 (RtcRead (RTC_ADDRESS_CENTURY));\r
+    Century = RtcRead (RTC_ADDRESS_CENTURY);\r
   }\r
 \r
-  Time->Year = (UINT16) (Century * 100 + Time->Year);\r
-\r
   //\r
   // Release RTC Lock.\r
   //\r
@@ -534,7 +552,10 @@ Returns:
   //\r
   // Make sure all field values are in correct range\r
   //\r
-  Status = RtcTimeFieldsValid (Time);\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
@@ -611,7 +632,7 @@ Returns:
   //\r
   // Wait for up to 0.1 seconds for the RTC to be updated\r
   //\r
-  Status = RtcWaitToUpdate (100000);\r
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));\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
@@ -693,23 +714,52 @@ Returns:
   return EFI_DEVICE_ERROR;\r
 }\r
 \r
-VOID\r
-ConvertRtcTimeToEfiTime (\r
-  IN EFI_TIME       *Time,\r
-  IN RTC_REGISTER_B RegisterB\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.\r
+          0xff if Value is invalid.\r
+\r
+**/\r
+UINT8\r
+CheckAndConvertBcd8ToDecimal8 (\r
+  IN  UINT8  Value\r
   )\r
-/*++\r
+{\r
+  if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {\r
+    return BcdToDecimal8 (Value);\r
+  }\r
 \r
-Routine Description:\r
+  return 0xff;\r
+}\r
 \r
-  Arguments:\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
-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
+EFI_STATUS\r
+ConvertRtcTimeToEfiTime (\r
+  IN OUT EFI_TIME        *Time,\r
+  IN     UINT8           Century,\r
+  IN     RTC_REGISTER_B  RegisterB\r
+  )\r
 {\r
   BOOLEAN PM;\r
 \r
@@ -722,13 +772,23 @@ Returns:
   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
+    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
+    Century       = CheckAndConvertBcd8ToDecimal8 (Century);\r
+  }\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
@@ -745,6 +805,8 @@ Returns:
   Time->Nanosecond  = 0;\r
   Time->TimeZone    = EFI_UNSPECIFIED_TIMEZONE;\r
   Time->Daylight    = 0;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 EFI_STATUS\r
@@ -968,7 +1030,6 @@ Returns:
   }\r
 }\r
 \r
-STATIC\r
 INTN\r
 CompareHMS (\r
   IN EFI_TIME   *From,\r
@@ -1005,7 +1066,6 @@ Returns:
   }\r
 }\r
 \r
-STATIC\r
 BOOLEAN\r
 IsWithinOneDay (\r
   IN EFI_TIME  *From,\r