]> git.proxmox.com Git - mirror_edk2.git/blobdiff - PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
IntelFsp2WrapperPkg: Update gFspWrapperTokenSpaceGuid to gIntelFsp2WrapperTokenSpaceGuid.
[mirror_edk2.git] / PcAtChipsetPkg / PcatRealTimeClockRuntimeDxe / PcRtc.c
index 9ec309c6b997d90983a179fc07292ad8a9294481..5143575e311f9e4d11d222e83e8c45f96afee4cf 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   RTC Architectural Protocol GUID as defined in DxeCis 0.96.\r
 \r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
 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
@@ -14,6 +14,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "PcRtc.h"\r
 \r
+//\r
+// Days of month.\r
+//\r
+UINTN mDayOfMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+\r
+//\r
+// The name of NV variable to store the timezone and daylight saving information.\r
+//\r
+CHAR16 mTimeZoneVariableName[] = L"RTC";\r
+\r
 /**\r
   Compare the Hour, Minute and Second of the From time and the To time.\r
   \r
@@ -166,7 +176,8 @@ PcRtcInit (
   // Set RTC configuration after get original time\r
   // The value of bit AIE should be reserved.\r
   //\r
-  RtcWrite (RTC_ADDRESS_REGISTER_B, (UINT8)(RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5)));\r
+  RegisterB.Data = RTC_INIT_REGISTER_B | (RegisterB.Data & BIT5);\r
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
 \r
   //\r
   // Release RTC Lock.\r
@@ -181,11 +192,11 @@ PcRtcInit (
   //\r
   DataSize = sizeof (UINT32);\r
   Status = EfiGetVariable (\r
-             L"RTC",\r
+             mTimeZoneVariableName,\r
              &gEfiCallerIdGuid,\r
              NULL,\r
              &DataSize,\r
-             (VOID *) &TimerVar\r
+             &TimerVar\r
              );\r
   if (!EFI_ERROR (Status)) {\r
     Time.TimeZone = (INT16) TimerVar;\r
@@ -476,15 +487,29 @@ PcRtcSetTime (
   //\r
   // Write timezone and daylight to RTC variable\r
   //\r
-  TimerVar = Time->Daylight;\r
-  TimerVar = (UINT32) ((TimerVar << 16) | (UINT16)(Time->TimeZone));\r
-  Status =  EfiSetVariable (\r
-              L"RTC",\r
-              &gEfiCallerIdGuid,\r
-              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-              sizeof (TimerVar),\r
-              &TimerVar\r
-              );\r
+  if ((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Time->Daylight == 0)) {\r
+    Status = EfiSetVariable (\r
+               mTimeZoneVariableName,\r
+               &gEfiCallerIdGuid,\r
+               0,\r
+               0,\r
+               NULL\r
+               );\r
+    if (Status == EFI_NOT_FOUND) {\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  } else {\r
+    TimerVar = Time->Daylight;\r
+    TimerVar = (UINT32) ((TimerVar << 16) | (UINT16)(Time->TimeZone));\r
+    Status = EfiSetVariable (\r
+               mTimeZoneVariableName,\r
+               &gEfiCallerIdGuid,\r
+               EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+               sizeof (TimerVar),\r
+               &TimerVar\r
+               );\r
+  }\r
+\r
   if (EFI_ERROR (Status)) {\r
     if (!EfiAtRuntime ()) {\r
       EfiReleaseLock (&Global->RtcLock);\r
@@ -499,6 +524,13 @@ PcRtcSetTime (
   RegisterB.Bits.Set  = 1;\r
   RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
 \r
+  //\r
+  // Store the century value to RTC before converting to BCD format.\r
+  //\r
+  if (Global->CenturyRtcAddress != 0) {\r
+    RtcWrite (Global->CenturyRtcAddress, DecimalToBcd8 ((UINT8) (RtcTime.Year / 100)));\r
+  }\r
+\r
   ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);\r
 \r
   RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);\r
@@ -979,28 +1011,13 @@ DayValid (
   IN  EFI_TIME  *Time\r
   )\r
 {\r
-  INTN  DayOfMonth[12];\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
   //\r
   // The validity of Time->Month field should be checked before\r
   //\r
   ASSERT (Time->Month >=1);\r
   ASSERT (Time->Month <=12);\r
   if (Time->Day < 1 ||\r
-      Time->Day > DayOfMonth[Time->Month - 1] ||\r
+      Time->Day > mDayOfMonth[Time->Month - 1] ||\r
       (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
       ) {\r
     return FALSE;\r
@@ -1136,22 +1153,8 @@ IsWithinOneDay (
   IN EFI_TIME  *To\r
   )\r
 {\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
   //\r
@@ -1178,7 +1181,7 @@ IsWithinOneDay (
             Adjacent = TRUE;\r
           }\r
         }\r
-      } else if (From->Day == DayOfMonth[From->Month - 1]) {\r
+      } else if (From->Day == mDayOfMonth[From->Month - 1]) {\r
         if ((CompareHMS(From, To) >= 0)) {\r
            Adjacent = TRUE;\r
         }\r
@@ -1197,3 +1200,108 @@ IsWithinOneDay (
   return Adjacent;\r
 }\r
 \r
+/**\r
+  This function find ACPI table with the specified signature in RSDT or XSDT.\r
+\r
+  @param Sdt              ACPI RSDT or XSDT.\r
+  @param Signature        ACPI table signature.\r
+  @param TablePointerSize Size of table pointer: 4 or 8.\r
+\r
+  @return ACPI table or NULL if not found.\r
+**/\r
+VOID *\r
+ScanTableInSDT (\r
+  IN EFI_ACPI_DESCRIPTION_HEADER    *Sdt,\r
+  IN UINT32                         Signature,\r
+  IN UINTN                          TablePointerSize\r
+  )\r
+{\r
+  UINTN                          Index;\r
+  UINTN                          EntryCount;\r
+  UINTN                          EntryBase;\r
+  EFI_ACPI_DESCRIPTION_HEADER    *Table;\r
+\r
+  EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / TablePointerSize;\r
+\r
+  EntryBase = (UINTN) (Sdt + 1);\r
+  for (Index = 0; Index < EntryCount; Index++) {\r
+    //\r
+    // When TablePointerSize is 4 while sizeof (VOID *) is 8, make sure the upper 4 bytes are zero.\r
+    //\r
+    Table = 0;\r
+    CopyMem (&Table, (VOID *) (EntryBase + Index * TablePointerSize), TablePointerSize);\r
+    if (Table->Signature == Signature) {\r
+      return Table;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Notification function of ACPI Table change.\r
+\r
+  This is a notification function registered on ACPI Table change event.\r
+  It saves the Century address stored in ACPI FADT table.\r
+\r
+  @param  Event        Event whose notification function is being invoked.\r
+  @param  Context      Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PcRtcAcpiTableChangeCallback (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  EFI_STATUS                                    Status;\r
+  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;\r
+  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;\r
+  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;\r
+  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt;\r
+  EFI_TIME                                      Time;\r
+  UINT8                                         Century;\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  ASSERT (Rsdp != NULL);\r
+\r
+  //\r
+  // Find FADT in XSDT\r
+  //\r
+  Fadt = NULL;\r
+  if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {\r
+    Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;\r
+    Fadt = ScanTableInSDT (Xsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, sizeof (UINT64));\r
+  }\r
+\r
+  if (Fadt == NULL) {\r
+    //\r
+    // Find FADT in RSDT\r
+    //\r
+    Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;\r
+    Fadt = ScanTableInSDT (Rsdt, EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, sizeof (UINT32));\r
+  }\r
+\r
+  if ((Fadt != NULL) &&\r
+      (Fadt->Century > RTC_ADDRESS_REGISTER_D) && (Fadt->Century < 0x80) &&\r
+      (mModuleGlobal.CenturyRtcAddress != Fadt->Century)\r
+      ) {\r
+    mModuleGlobal.CenturyRtcAddress = Fadt->Century;\r
+    Status = PcRtcGetTime (&Time, NULL, &mModuleGlobal);\r
+    if (!EFI_ERROR (Status)) {\r
+      Century = (UINT8) (Time.Year / 100);\r
+      Century = DecimalToBcd8 (Century);\r
+      DEBUG ((EFI_D_INFO, "PcRtc: Write 0x%x to CMOS location 0x%x\n", Century, mModuleGlobal.CenturyRtcAddress));\r
+      RtcWrite (mModuleGlobal.CenturyRtcAddress, Century);\r
+    }\r
+  }\r
+}\r