]> 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 a58aee5f8a53d793fdaf72c6d391e78b6f032456..a82f5d133e34ba93187ddc19b91586f7e06bc342 100644 (file)
@@ -1,43 +1,31 @@
-/*++\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
+/** @file\r
+  RTC Architectural Protocol GUID as defined in DxeCis 0.96.\r
 \r
-  PcRtc.c\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
+http://opensource.org/licenses/bsd-license.php\r
 \r
-Abstract:\r
+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
-  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
@@ -1029,8 +1089,23 @@ Returns:
 \r
 --*/\r
 {\r
-  UINT8   DayOfMonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};\r
-  BOOLEAN Adjacent = FALSE;\r
+  UINT8   DayOfMonth[12];\r
+  BOOLEAN Adjacent;\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
+  Adjacent = FALSE;\r
 \r
   if (From->Year == To->Year) {\r
     if (From->Month == To->Month) {\r