public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "duke.zhai via groups.io" <duke.zhai=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Eric Xing <eric.xing@amd.com>, Duke Zhai <duke.zhai@amd.com>,
	Igniculus Fu <igniculus.fu@amd.com>,
	Abner Chang <abner.chang@amd.com>
Subject: [edk2-devel] [PATCH 19/33] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe\r module.
Date: Thu, 18 Jan 2024 14:50:32 +0800	[thread overview]
Message-ID: <20240118065046.961-20-duke.zhai@amd.com> (raw)
In-Reply-To: <20240118065046.961-1-duke.zhai@amd.com>

From: Duke Zhai <Duke.Zhai@amd.com>


BZ #:4640

This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.

It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.



Signed-off-by: Ken Yao <ken.yao@amd.com>

Cc: Eric Xing <eric.xing@amd.com>

Cc: Duke Zhai <duke.zhai@amd.com>

Cc: Igniculus Fu <igniculus.fu@amd.com>

Cc: Abner Chang <abner.chang@amd.com>

---

 .../PcatRealTimeClockRuntimeDxe/PcRtc.c       | 1356 +++++++++++++++++

 .../PcatRealTimeClockRuntimeDxe/PcRtc.h       |  389 +++++

 .../PcatRealTimeClockRuntimeDxe/PcRtc.uni     |   35 +

 .../PcatRealTimeClockRuntimeDxe/PcRtcEntry.c  |  186 +++

 .../PcRtcExtra.uni                            |   30 +

 .../PcatRealTimeClockRuntimeDxe.inf           |   93 ++

 6 files changed, 2089 insertions(+)

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni

 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf



diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c

new file mode 100644

index 0000000000..37ba9d8b5d

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c

@@ -0,0 +1,1356 @@

+/** @file

+  Implements PcRtc.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  RTC Architectural Protocol GUID as defined in DxeCis 0.96.

+

+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "PcRtc.h"

+

+//

+// Days of month.

+//

+UINTN  mDayOfMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

+

+//

+// The name of NV variable to store the timezone and daylight saving information.

+//

+CHAR16  mTimeZoneVariableName[] = L"RTC";

+

+/**

+  Compare the Hour, Minute and Second of the From time and the To time.

+

+  Only compare H/M/S in EFI_TIME and ignore other fields here.

+

+  @param From   the first time

+  @param To     the second time

+

+  @return  >0   The H/M/S of the From time is later than those of To time

+  @return  ==0  The H/M/S of the From time is same as those of To time

+  @return  <0   The H/M/S of the From time is earlier than those of To time

+**/

+INTN

+CompareHMS (

+  IN EFI_TIME  *From,

+  IN EFI_TIME  *To

+  );

+

+/**

+  To check if second date is later than first date within 24 hours.

+

+  @param  From   the first date

+  @param  To     the second date

+

+  @retval TRUE   From is previous to To within 24 hours.

+  @retval FALSE  From is later, or it is previous to To more than 24 hours.

+**/

+BOOLEAN

+IsWithinOneDay (

+  IN EFI_TIME  *From,

+  IN EFI_TIME  *To

+  );

+

+/**

+  Read RTC content through its registers.

+

+  @param  Address  Address offset of RTC. It is recommended to use macros such as

+                   RTC_ADDRESS_SECONDS.

+

+  @return The data of UINT8 type read from RTC.

+**/

+UINT8

+RtcRead (

+  IN  UINT8  Address

+  )

+{

+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));

+  return IoRead8 (PCAT_RTC_DATA_REGISTER);

+}

+

+/**

+  Write RTC through its registers.

+

+  @param  Address  Address offset of RTC. It is recommended to use macros such as

+                   RTC_ADDRESS_SECONDS.

+  @param  Data     The content you want to write into RTC.

+

+**/

+VOID

+RtcWrite (

+  IN  UINT8  Address,

+  IN  UINT8  Data

+  )

+{

+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));

+  IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);

+}

+

+/**

+  Initialize RTC.

+

+  @param  Global            For global use inside this module.

+

+  @retval EFI_DEVICE_ERROR  Initialization failed due to device error.

+  @retval EFI_SUCCESS       Initialization successful.

+

+**/

+EFI_STATUS

+PcRtcInit (

+  IN PC_RTC_MODULE_GLOBALS  *Global

+  )

+{

+  EFI_STATUS      Status;

+  RTC_REGISTER_B  RegisterB;

+  EFI_TIME        Time;

+  UINTN           DataSize;

+  UINT32          TimerVar;

+  BOOLEAN         Enabled;

+  BOOLEAN         Pending;

+

+  //

+  // 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)) {

+    //

+    // Set the variable with default value if the RTC is functioning incorrectly.

+    //

+    Global->SavedTimeZone = EFI_UNSPECIFIED_TIMEZONE;

+    Global->Daylight      = 0;

+    if (!EfiAtRuntime ()) {

+      EfiReleaseLock (&Global->RtcLock);

+    }

+

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Get the Time/Date/Daylight Savings values.

+  //

+  Time.Second = RtcRead (RTC_ADDRESS_SECONDS);

+  Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);

+  Time.Hour   = RtcRead (RTC_ADDRESS_HOURS);

+  Time.Day    = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);

+  Time.Month  = RtcRead (RTC_ADDRESS_MONTH);

+  Time.Year   = RtcRead (RTC_ADDRESS_YEAR);

+

+  //

+  // Set RTC configuration after get original time

+  // The value of bit AIE should be reserved.

+  //

+  RegisterB.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterB) | (RegisterB.Data & BIT5);

+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);

+

+  //

+  // Release RTC Lock.

+  //

+  if (!EfiAtRuntime ()) {

+    EfiReleaseLock (&Global->RtcLock);

+  }

+

+  //

+  // Get the data of Daylight saving and time zone, if they have been

+  // stored in NV variable during previous boot.

+  //

+  DataSize = sizeof (UINT32);

+  Status   = EfiGetVariable (

+               mTimeZoneVariableName,

+               &gEfiCallerIdGuid,

+               NULL,

+               &DataSize,

+               &TimerVar

+               );

+  if (!EFI_ERROR (Status)) {

+    Time.TimeZone = (INT16)TimerVar;

+    Time.Daylight = (UINT8)(TimerVar >> 16);

+  } else {

+    Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;

+    Time.Daylight = 0;

+  }

+

+  //

+  // Validate time fields

+  //

+  Status = ConvertRtcTimeToEfiTime (&Time, RegisterB);

+  if (!EFI_ERROR (Status)) {

+    Status = RtcTimeFieldsValid (&Time);

+  }

+

+  if (EFI_ERROR (Status)) {

+    //

+    // Report Status Code to indicate that the RTC has bad date and time

+    //

+    REPORT_STATUS_CODE (

+      EFI_ERROR_CODE | EFI_ERROR_MINOR,

+      (EFI_SOFTWARE_DXE_RT_DRIVER | EFI_SW_EC_BAD_DATE_TIME)

+      );

+    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       = PcdGet16 (PcdMinimalValidYear);

+    Time.Nanosecond = 0;

+    Time.TimeZone   = EFI_UNSPECIFIED_TIMEZONE;

+    Time.Daylight   = 0;

+  }

+

+  //

+  // Reset time value according to new RTC configuration

+  //

+  Status = PcRtcSetTime (&Time, Global);

+  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;

+  }

+

+  //

+  // 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       = PcdGet16 (PcdMinimalValidYear);

+  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);

+

+  //

+  // 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;

+}

+

+/**

+  Returns the current time and date information, and the time-keeping capabilities

+  of the hardware platform.

+

+  @param  Time          A pointer to storage to receive a snapshot of the current time.

+  @param  Capabilities  An optional pointer to a buffer to receive the real time clock

+                        device's capabilities.

+  @param  Global        For global use inside this module.

+

+  @retval EFI_SUCCESS            The operation completed successfully.

+  @retval EFI_INVALID_PARAMETER  Time is NULL.

+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.

+

+**/

+EFI_STATUS

+PcRtcGetTime (

+  OUT  EFI_TIME *Time,

+  OUT  EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL

+  IN   PC_RTC_MODULE_GLOBALS  *Global

+  )

+{

+  EFI_STATUS      Status;

+  RTC_REGISTER_B  RegisterB;

+

+  //

+  // Check parameters for null pointer

+  //

+  if (Time == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // 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 Status;

+  }

+

+  //

+  // Read Register B

+  //

+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);

+

+  //

+  // Get the Time/Date/Daylight Savings values.

+  //

+  Time->Second = RtcRead (RTC_ADDRESS_SECONDS);

+  Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);

+  Time->Hour   = RtcRead (RTC_ADDRESS_HOURS);

+  Time->Day    = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);

+  Time->Month  = RtcRead (RTC_ADDRESS_MONTH);

+  Time->Year   = RtcRead (RTC_ADDRESS_YEAR);

+

+  //

+  // Release RTC Lock.

+  //

+  if (!EfiAtRuntime ()) {

+    EfiReleaseLock (&Global->RtcLock);

+  }

+

+  //

+  // Get the variable that contains the TimeZone and Daylight fields

+  //

+  Time->TimeZone = Global->SavedTimeZone;

+  Time->Daylight = Global->Daylight;

+

+  //

+  // Make sure all field values are in correct range

+  //

+  Status = ConvertRtcTimeToEfiTime (Time, RegisterB);

+  if (!EFI_ERROR (Status)) {

+    Status = RtcTimeFieldsValid (Time);

+  }

+

+  if (EFI_ERROR (Status)) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  //  Fill in Capabilities if it was passed in

+  //

+  if (Capabilities != NULL) {

+    Capabilities->Resolution = 1;

+    //

+    // 1 hertz

+    //

+    Capabilities->Accuracy = 50000000;

+    //

+    // 50 ppm

+    //

+    Capabilities->SetsToZero = FALSE;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Sets the current local time and date information.

+

+  @param  Time                  A pointer to the current time.

+  @param  Global                For global use inside this module.

+

+  @retval EFI_SUCCESS           The operation completed successfully.

+  @retval EFI_INVALID_PARAMETER A time field is out of range.

+  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.

+

+**/

+EFI_STATUS

+PcRtcSetTime (

+  IN EFI_TIME               *Time,

+  IN PC_RTC_MODULE_GLOBALS  *Global

+  )

+{

+  EFI_STATUS      Status;

+  EFI_TIME        RtcTime;

+  RTC_REGISTER_B  RegisterB;

+  UINT32          TimerVar;

+

+  if (Time == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Make sure that the time fields are valid

+  //

+  Status = RtcTimeFieldsValid (Time);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  CopyMem (&RtcTime, Time, sizeof (EFI_TIME));

+

+  //

+  // 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 Status;

+  }

+

+  //

+  // Write timezone and daylight to RTC variable

+  //

+  if ((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Time->Daylight == 0)) {

+    Status = EfiSetVariable (

+               mTimeZoneVariableName,

+               &gEfiCallerIdGuid,

+               0,

+               0,

+               NULL

+               );

+    if (Status == EFI_NOT_FOUND) {

+      Status = EFI_SUCCESS;

+    }

+  } else {

+    TimerVar = Time->Daylight;

+    TimerVar = (UINT32)((TimerVar << 16) | (UINT16)(Time->TimeZone));

+    Status   = EfiSetVariable (

+                 mTimeZoneVariableName,

+                 &gEfiCallerIdGuid,

+                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,

+                 sizeof (TimerVar),

+                 &TimerVar

+                 );

+  }

+

+  if (EFI_ERROR (Status)) {

+    if (!EfiAtRuntime ()) {

+      EfiReleaseLock (&Global->RtcLock);

+    }

+

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Read Register B, and inhibit updates of the RTC

+  //

+  RegisterB.Data     = RtcRead (RTC_ADDRESS_REGISTER_B);

+  RegisterB.Bits.Set = 1;

+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);

+

+  //

+  // Store the century value to RTC before converting to BCD format.

+  //

+  if (Global->CenturyRtcAddress != 0) {

+    RtcWrite (Global->CenturyRtcAddress, DecimalToBcd8 ((UINT8)(RtcTime.Year / 100)));

+  }

+

+  ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);

+

+  RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);

+  RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);

+  RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);

+  RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);

+  RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);

+  RtcWrite (RTC_ADDRESS_YEAR, (UINT8)RtcTime.Year);

+

+  //

+  // 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);

+  }

+

+  //

+  // Set the variable that contains the TimeZone and Daylight fields

+  //

+  Global->SavedTimeZone = Time->TimeZone;

+  Global->Daylight      = Time->Daylight;

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Returns the current wakeup alarm clock setting.

+

+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.

+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgment.

+  @param  Time     The current alarm setting.

+  @param  Global   For global use inside this module.

+

+  @retval EFI_SUCCESS           The alarm settings were returned.

+  @retval EFI_INVALID_PARAMETER Enabled is NULL.

+  @retval EFI_INVALID_PARAMETER Pending is NULL.

+  @retval EFI_INVALID_PARAMETER Time is NULL.

+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.

+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.

+

+**/

+EFI_STATUS

+PcRtcGetWakeupTime (

+  OUT BOOLEAN                *Enabled,

+  OUT BOOLEAN                *Pending,

+  OUT EFI_TIME               *Time,

+  IN  PC_RTC_MODULE_GLOBALS  *Global

+  )

+{

+  EFI_STATUS      Status;

+  RTC_REGISTER_B  RegisterB;

+  RTC_REGISTER_C  RegisterC;

+  EFI_TIME        RtcTime;

+  UINTN           DataSize;

+

+  //

+  // Check parameters for null pointers

+  //

+  if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // 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;

+  }

+

+  //

+  // Read Register B and Register C

+  //

+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);

+  RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);

+

+  //

+  // Get the Time/Date/Daylight Savings values.

+  //

+  *Enabled = RegisterB.Bits.Aie;

+  *Pending = RegisterC.Bits.Af;

+

+  Time->Second   = RtcRead (RTC_ADDRESS_SECONDS_ALARM);

+  Time->Minute   = RtcRead (RTC_ADDRESS_MINUTES_ALARM);

+  Time->Hour     = RtcRead (RTC_ADDRESS_HOURS_ALARM);

+  Time->Day      = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);

+  Time->Month    = RtcRead (RTC_ADDRESS_MONTH);

+  Time->Year     = RtcRead (RTC_ADDRESS_YEAR);

+  Time->TimeZone = Global->SavedTimeZone;

+  Time->Daylight = Global->Daylight;

+

+  //

+  // Get the alarm info from variable

+  //

+  DataSize = sizeof (EFI_TIME);

+  Status   = EfiGetVariable (

+               L"RTCALARM",

+               &gEfiCallerIdGuid,

+               NULL,

+               &DataSize,

+               &RtcTime

+               );

+  if (!EFI_ERROR (Status)) {

+    //

+    // The alarm variable exists. In this case, we read variable to get info.

+    //

+    Time->Day   = RtcTime.Day;

+    Time->Month = RtcTime.Month;

+    Time->Year  = RtcTime.Year;

+  }

+

+  //

+  // Release RTC Lock.

+  //

+  if (!EfiAtRuntime ()) {

+    EfiReleaseLock (&Global->RtcLock);

+  }

+

+  //

+  // Make sure all field values are in correct range

+  //

+  Status = ConvertRtcTimeToEfiTime (Time, RegisterB);

+  if (!EFI_ERROR (Status)) {

+    Status = RtcTimeFieldsValid (Time);

+  }

+

+  if (EFI_ERROR (Status)) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Sets the system wakeup alarm clock time.

+

+  @param  Enabled  Enable or disable the wakeup alarm.

+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.

+                   If Enable is FALSE, then this parameter is optional, and may be NULL.

+  @param  Global   For global use inside this module.

+

+  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled.

+                                If Enable is FALSE, then the wakeup alarm was disabled.

+  @retval EFI_INVALID_PARAMETER A time field is out of range.

+  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.

+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.

+

+**/

+EFI_STATUS

+PcRtcSetWakeupTime (

+  IN BOOLEAN Enable,

+  IN EFI_TIME *Time, OPTIONAL

+  IN PC_RTC_MODULE_GLOBALS  *Global

+  )

+{

+  EFI_STATUS             Status;

+  EFI_TIME               RtcTime;

+  RTC_REGISTER_B         RegisterB;

+  EFI_TIME_CAPABILITIES  Capabilities;

+

+  ZeroMem (&RtcTime, sizeof (RtcTime));

+

+  if (Enable) {

+    if (Time == NULL) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    //

+    // Make sure that the time fields are valid

+    //

+    Status = RtcTimeFieldsValid (Time);

+    if (EFI_ERROR (Status)) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    //

+    // Just support set alarm time within 24 hours

+    //

+    PcRtcGetTime (&RtcTime, &Capabilities, Global);

+    Status = RtcTimeFieldsValid (&RtcTime);

+    if (EFI_ERROR (Status)) {

+      return EFI_DEVICE_ERROR;

+    }

+

+    if (!IsWithinOneDay (&RtcTime, Time)) {

+      return EFI_UNSUPPORTED;

+    }

+

+    //

+    // Make a local copy of the time and date

+    //

+    CopyMem (&RtcTime, Time, sizeof (EFI_TIME));

+  }

+

+  //

+  // 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;

+  }

+

+  //

+  // Read Register B

+  //

+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);

+

+  if (Enable) {

+    ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);

+  } else {

+    //

+    // if the alarm is disable, record the current setting.

+    //

+    RtcTime.Second   = RtcRead (RTC_ADDRESS_SECONDS_ALARM);

+    RtcTime.Minute   = RtcRead (RTC_ADDRESS_MINUTES_ALARM);

+    RtcTime.Hour     = RtcRead (RTC_ADDRESS_HOURS_ALARM);

+    RtcTime.Day      = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);

+    RtcTime.Month    = RtcRead (RTC_ADDRESS_MONTH);

+    RtcTime.Year     = RtcRead (RTC_ADDRESS_YEAR);

+    RtcTime.TimeZone = Global->SavedTimeZone;

+    RtcTime.Daylight = Global->Daylight;

+  }

+

+  //

+  // 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 (RtcTime),

+              &RtcTime

+              );

+  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);

+

+  if (Enable) {

+    //

+    // Set RTC alarm time

+    //

+    RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);

+    RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);

+    RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);

+

+    RegisterB.Bits.Aie = 1;

+  } else {

+    RegisterB.Bits.Aie = 0;

+  }

+

+  //

+  // 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;

+}

+

+/**

+  Checks an 8-bit BCD value, and converts to an 8-bit value if valid.

+

+  This function checks the 8-bit BCD value specified by Value.

+  If valid, the function converts it to an 8-bit value and returns it.

+  Otherwise, return 0xff.

+

+  @param   Value The 8-bit BCD value to check and convert

+

+  @return  The 8-bit value converted. Or 0xff if Value is invalid.

+

+**/

+UINT8

+CheckAndConvertBcd8ToDecimal8 (

+  IN  UINT8  Value

+  )

+{

+  if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {

+    return BcdToDecimal8 (Value);

+  }

+

+  return 0xff;

+}

+

+/**

+  Converts time read from RTC to EFI_TIME format defined by UEFI spec.

+

+  This function converts raw time data read from RTC to the EFI_TIME format

+  defined by UEFI spec.

+  If data mode of RTC is BCD, then converts it to decimal,

+  If RTC is in 12-hour format, then converts it to 24-hour format.

+

+  @param   Time       On input, the time data read from RTC to convert

+                      On output, the time converted to UEFI format

+  @param   RegisterB  Value of Register B of RTC, indicating data mode

+                      and hour format.

+

+  @retval  EFI_INVALID_PARAMETER  Parameters passed in are invalid.

+  @retval  EFI_SUCCESS            Convert RTC time to EFI time successfully.

+

+**/

+EFI_STATUS

+ConvertRtcTimeToEfiTime (

+  IN OUT EFI_TIME        *Time,

+  IN     RTC_REGISTER_B  RegisterB

+  )

+{

+  BOOLEAN  IsPM;

+  UINT8    Century;

+

+  if ((Time->Hour & 0x80) != 0) {

+    IsPM = TRUE;

+  } else {

+    IsPM = FALSE;

+  }

+

+  Time->Hour = (UINT8)(Time->Hour & 0x7f);

+

+  if (RegisterB.Bits.Dm == 0) {

+    Time->Year   = CheckAndConvertBcd8ToDecimal8 ((UINT8)Time->Year);

+    Time->Month  = CheckAndConvertBcd8ToDecimal8 (Time->Month);

+    Time->Day    = CheckAndConvertBcd8ToDecimal8 (Time->Day);

+    Time->Hour   = CheckAndConvertBcd8ToDecimal8 (Time->Hour);

+    Time->Minute = CheckAndConvertBcd8ToDecimal8 (Time->Minute);

+    Time->Second = CheckAndConvertBcd8ToDecimal8 (Time->Second);

+  }

+

+  if ((Time->Year == 0xff) || (Time->Month == 0xff) || (Time->Day == 0xff) ||

+      (Time->Hour == 0xff) || (Time->Minute == 0xff) || (Time->Second == 0xff))

+  {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // For minimal/maximum year range [1970, 2069],

+  //   Century is 19 if RTC year >= 70,

+  //   Century is 20 otherwise.

+  //

+  Century = (UINT8)(PcdGet16 (PcdMinimalValidYear) / 100);

+  if (Time->Year < PcdGet16 (PcdMinimalValidYear) % 100) {

+    Century++;

+  }

+

+  Time->Year = (UINT16)(Century * 100 + Time->Year);

+

+  //

+  // If time is in 12 hour format, convert it to 24 hour format

+  //

+  if (RegisterB.Bits.Mil == 0) {

+    if (IsPM && (Time->Hour < 12)) {

+      Time->Hour = (UINT8)(Time->Hour + 12);

+    }

+

+    if (!IsPM && (Time->Hour == 12)) {

+      Time->Hour = 0;

+    }

+  }

+

+  Time->Nanosecond = 0;

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Wait for a period for the RTC to be ready.

+

+  @param    Timeout  Tell how long it should take to wait.

+

+  @retval   EFI_DEVICE_ERROR   RTC device error.

+  @retval   EFI_SUCCESS        RTC is updated and ready.

+**/

+EFI_STATUS

+RtcWaitToUpdate (

+  UINTN  Timeout

+  )

+{

+  RTC_REGISTER_A  RegisterA;

+  RTC_REGISTER_D  RegisterD;

+

+  //

+  // See if the RTC is functioning correctly

+  //

+  RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);

+

+  if (RegisterD.Bits.Vrt == 0) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Wait for up to 0.1 seconds for the RTC to be ready.

+  //

+  Timeout        = (Timeout / 10) + 1;

+  RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);

+  while (RegisterA.Bits.Uip == 1 && Timeout > 0) {

+    MicroSecondDelay (10);

+    RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);

+    Timeout--;

+  }

+

+  RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);

+  if ((Timeout == 0) || (RegisterD.Bits.Vrt == 0)) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  See if all fields of a variable of EFI_TIME type is correct.

+

+  @param   Time   The time to be checked.

+

+  @retval  EFI_INVALID_PARAMETER  Some fields of Time are not correct.

+  @retval  EFI_SUCCESS            Time is a valid EFI_TIME variable.

+

+**/

+EFI_STATUS

+RtcTimeFieldsValid (

+  IN EFI_TIME  *Time

+  )

+{

+  if ((Time->Year < PcdGet16 (PcdMinimalValidYear)) ||

+      (Time->Year > PcdGet16 (PcdMaximalValidYear)) ||

+      (Time->Month < 1) ||

+      (Time->Month > 12) ||

+      (!DayValid (Time)) ||

+      (Time->Hour > 23) ||

+      (Time->Minute > 59) ||

+      (Time->Second > 59) ||

+      (Time->Nanosecond > 999999999) ||

+      (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||

+      ((Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) != 0))

+  {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  See if field Day of an EFI_TIME is correct.

+

+  @param    Time   Its Day field is to be checked.

+

+  @retval   TRUE   Day field of Time is correct.

+  @retval   FALSE  Day field of Time is NOT correct.

+**/

+BOOLEAN

+DayValid (

+  IN  EFI_TIME  *Time

+  )

+{

+  //

+  // The validity of Time->Month field should be checked before

+  //

+  ASSERT (Time->Month >= 1);

+  ASSERT (Time->Month <= 12);

+  if ((Time->Day < 1) ||

+      (Time->Day > mDayOfMonth[Time->Month - 1]) ||

+      ((Time->Month == 2) && (!IsLeapYear (Time) && (Time->Day > 28)))

+      )

+  {

+    return FALSE;

+  }

+

+  return TRUE;

+}

+

+/**

+  Check if it is a leap year.

+

+  @param    Time   The time to be checked.

+

+  @retval   TRUE   It is a leap year.

+  @retval   FALSE  It is NOT a leap year.

+**/

+BOOLEAN

+IsLeapYear (

+  IN EFI_TIME  *Time

+  )

+{

+  if (Time->Year % 4 == 0) {

+    if (Time->Year % 100 == 0) {

+      if (Time->Year % 400 == 0) {

+        return TRUE;

+      } else {

+        return FALSE;

+      }

+    } else {

+      return TRUE;

+    }

+  } else {

+    return FALSE;

+  }

+}

+

+/**

+  Converts time from EFI_TIME format defined by UEFI spec to RTC's.

+

+  This function converts time from EFI_TIME format defined by UEFI spec to RTC's.

+  If data mode of RTC is BCD, then converts EFI_TIME to it.

+  If RTC is in 12-hour format, then converts EFI_TIME to it.

+

+  @param   Time       On input, the time data read from UEFI to convert

+                      On output, the time converted to RTC format

+  @param   RegisterB  Value of Register B of RTC, indicating data mode

+**/

+VOID

+ConvertEfiTimeToRtcTime (

+  IN OUT EFI_TIME        *Time,

+  IN     RTC_REGISTER_B  RegisterB

+  )

+{

+  BOOLEAN  IsPM;

+

+  IsPM = TRUE;

+  //

+  // Adjust hour field if RTC is in 12 hour mode

+  //

+  if (RegisterB.Bits.Mil == 0) {

+    if (Time->Hour < 12) {

+      IsPM = FALSE;

+    }

+

+    if (Time->Hour >= 13) {

+      Time->Hour = (UINT8)(Time->Hour - 12);

+    } else if (Time->Hour == 0) {

+      Time->Hour = 12;

+    }

+  }

+

+  //

+  // Set the Time/Date values.

+  //

+  Time->Year = (UINT16)(Time->Year % 100);

+

+  if (RegisterB.Bits.Dm == 0) {

+    Time->Year   = DecimalToBcd8 ((UINT8)Time->Year);

+    Time->Month  = DecimalToBcd8 (Time->Month);

+    Time->Day    = DecimalToBcd8 (Time->Day);

+    Time->Hour   = DecimalToBcd8 (Time->Hour);

+    Time->Minute = DecimalToBcd8 (Time->Minute);

+    Time->Second = DecimalToBcd8 (Time->Second);

+  }

+

+  //

+  // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.

+  //

+  if ((RegisterB.Bits.Mil == 0) && IsPM) {

+    Time->Hour = (UINT8)(Time->Hour | 0x80);

+  }

+}

+

+/**

+  Compare the Hour, Minute and Second of the From time and the To time.

+

+  Only compare H/M/S in EFI_TIME and ignore other fields here.

+

+  @param From   the first time

+  @param To     the second time

+

+  @return  >0   The H/M/S of the From time is later than those of To time

+  @return  ==0  The H/M/S of the From time is same as those of To time

+  @return  <0   The H/M/S of the From time is earlier than those of To time

+**/

+INTN

+CompareHMS (

+  IN EFI_TIME  *From,

+  IN EFI_TIME  *To

+  )

+{

+  if ((From->Hour > To->Hour) ||

+      ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||

+      ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second)))

+  {

+    return 1;

+  } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {

+    return 0;

+  } else {

+    return -1;

+  }

+}

+

+/**

+  To check if second date is later than first date within 24 hours.

+

+  @param  From   the first date

+  @param  To     the second date

+

+  @retval TRUE   From is previous to To within 24 hours.

+  @retval FALSE  From is later, or it is previous to To more than 24 hours.

+**/

+BOOLEAN

+IsWithinOneDay (

+  IN EFI_TIME  *From,

+  IN EFI_TIME  *To

+  )

+{

+  BOOLEAN  Adjacent;

+

+  Adjacent = FALSE;

+

+  //

+  // The validity of From->Month field should be checked before

+  //

+  ASSERT (From->Month >= 1);

+  ASSERT (From->Month <= 12);

+

+  if (From->Year == To->Year) {

+    if (From->Month == To->Month) {

+      if ((From->Day + 1) == To->Day) {

+        if ((CompareHMS (From, To) >= 0)) {

+          Adjacent = TRUE;

+        }

+      } else if (From->Day == To->Day) {

+        if ((CompareHMS (From, To) <= 0)) {

+          Adjacent = TRUE;

+        }

+      }

+    } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {

+      if ((From->Month == 2) && !IsLeapYear (From)) {

+        if (From->Day == 28) {

+          if ((CompareHMS (From, To) >= 0)) {

+            Adjacent = TRUE;

+          }

+        }

+      } else if (From->Day == mDayOfMonth[From->Month - 1]) {

+        if ((CompareHMS (From, To) >= 0)) {

+          Adjacent = TRUE;

+        }

+      }

+    }

+  } else if (((From->Year + 1) == To->Year) &&

+             (From->Month == 12) &&

+             (From->Day   == 31) &&

+             (To->Month   == 1)  &&

+             (To->Day     == 1))

+  {

+    if ((CompareHMS (From, To) >= 0)) {

+      Adjacent = TRUE;

+    }

+  }

+

+  return Adjacent;

+}

+

+/**

+  This function find ACPI table with the specified signature in RSDT or XSDT.

+

+  @param Sdt              ACPI RSDT or XSDT.

+  @param Signature        ACPI table signature.

+  @param TablePointerSize Size of table pointer: 4 or 8.

+

+  @return ACPI table or NULL if not found.

+**/

+VOID *

+ScanTableInSDTRtc (

+  IN EFI_ACPI_DESCRIPTION_HEADER  *Sdt,

+  IN UINT32                       Signature,

+  IN UINTN                        TablePointerSize

+  )

+{

+  UINTN                        Index;

+  UINTN                        EntryCount;

+  UINTN                        EntryBase;

+  EFI_ACPI_DESCRIPTION_HEADER  *Table;

+

+  EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / TablePointerSize;

+

+  EntryBase = (UINTN)(Sdt + 1);

+  for (Index = 0; Index < EntryCount; Index++) {

+    //

+    // When TablePointerSize is 4 while sizeof (VOID *) is 8, make sure the upper 4 bytes are zero.

+    //

+    Table = 0;

+    CopyMem (&Table, (VOID *)(EntryBase + Index * TablePointerSize), TablePointerSize);

+

+    if (Table == NULL) {

+      continue;

+    }

+

+    if (Table->Signature == Signature) {

+      return Table;

+    }

+  }

+

+  return NULL;

+}

+

+/**

+  Get the century RTC address from the ACPI FADT table.

+

+  @return  The century RTC address or 0 if not found.

+**/

+UINT8

+GetCenturyRtcAddress (

+  VOID

+  )

+{

+  EFI_STATUS                                    Status;

+  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;

+  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt;

+

+  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp);

+  if (EFI_ERROR (Status)) {

+    Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&Rsdp);

+  }

+

+  if (EFI_ERROR (Status) || (Rsdp == NULL)) {

+    return 0;

+  }

+

+  Fadt = NULL;

+

+  //

+  // Find FADT in XSDT

+  //

+  if ((Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) && (Rsdp->XsdtAddress != 0)) {

+    Fadt = ScanTableInSDTRtc (

+             (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress,

+             EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,

+             sizeof (UINTN)

+             );

+  }

+

+  //

+  // Find FADT in RSDT

+  //

+  if ((Fadt == NULL) && (Rsdp->RsdtAddress != 0)) {

+    Fadt = ScanTableInSDTRtc (

+             (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress,

+             EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,

+             sizeof (UINT32)

+             );

+  }

+

+  if ((Fadt != NULL) &&

+      (Fadt->Century > RTC_ADDRESS_REGISTER_D) && (Fadt->Century < 0x80)

+      )

+  {

+    return Fadt->Century;

+  } else {

+    return 0;

+  }

+}

+

+/**

+  Notification function of ACPI Table change.

+

+  This is a notification function registered on ACPI Table change event.

+  It saves the Century address stored in ACPI FADT table.

+

+  @param  Event        Event whose notification function is being invoked.

+  @param  Context      Pointer to the notification function's context.

+

+**/

+VOID

+EFIAPI

+PcRtcAcpiTableChangeCallback (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS  Status;

+  EFI_TIME    Time;

+  UINT8       CenturyRtcAddress;

+  UINT8       Century;

+

+  CenturyRtcAddress = GetCenturyRtcAddress ();

+  if ((CenturyRtcAddress != 0) && (mModuleGlobal.CenturyRtcAddress != CenturyRtcAddress)) {

+    mModuleGlobal.CenturyRtcAddress = CenturyRtcAddress;

+    Status                          = PcRtcGetTime (&Time, NULL, &mModuleGlobal);

+    if (!EFI_ERROR (Status)) {

+      Century = (UINT8)(Time.Year / 100);

+      Century = DecimalToBcd8 (Century);

+      DEBUG ((EFI_D_INFO, "PcRtc: Write 0x%x to CMOS location 0x%x\n", Century, mModuleGlobal.CenturyRtcAddress));

+      RtcWrite (mModuleGlobal.CenturyRtcAddress, Century);

+    }

+  }

+}

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h

new file mode 100644

index 0000000000..15e2646040

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h

@@ -0,0 +1,389 @@

+/** @file

+  Implements PcRtc.h

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  Header file for real time clock driver.

+

+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#ifndef _RTC_H_

+#define _RTC_H_

+

+#include <Uefi.h>

+

+#include <Guid/Acpi.h>

+

+#include <Protocol/RealTimeClock.h>

+

+#include <Library/BaseLib.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/IoLib.h>

+#include <Library/TimerLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiRuntimeLib.h>

+#include <Library/UefiRuntimeServicesTableLib.h>

+#include <Library/PcdLib.h>

+#include <Library/ReportStatusCodeLib.h>

+

+typedef struct {

+  EFI_LOCK    RtcLock;

+  INT16       SavedTimeZone;

+  UINT8       Daylight;

+  UINT8       CenturyRtcAddress;

+} PC_RTC_MODULE_GLOBALS;

+

+extern PC_RTC_MODULE_GLOBALS  mModuleGlobal;

+

+#define PCAT_RTC_ADDRESS_REGISTER  0x70

+#define PCAT_RTC_DATA_REGISTER     0x71

+

+//

+// Dallas DS12C887 Real Time Clock

+//

+#define RTC_ADDRESS_SECONDS           0   // R/W  Range 0..59

+#define RTC_ADDRESS_SECONDS_ALARM     1   // R/W  Range 0..59

+#define RTC_ADDRESS_MINUTES           2   // R/W  Range 0..59

+#define RTC_ADDRESS_MINUTES_ALARM     3   // R/W  Range 0..59

+#define RTC_ADDRESS_HOURS             4   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM

+#define RTC_ADDRESS_HOURS_ALARM       5   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM

+#define RTC_ADDRESS_DAY_OF_THE_WEEK   6   // R/W  Range 1..7

+#define RTC_ADDRESS_DAY_OF_THE_MONTH  7   // R/W  Range 1..31

+#define RTC_ADDRESS_MONTH             8   // R/W  Range 1..12

+#define RTC_ADDRESS_YEAR              9   // R/W  Range 0..99

+#define RTC_ADDRESS_REGISTER_A        10  // R/W[0..6]  R0[7]

+#define RTC_ADDRESS_REGISTER_B        11  // R/W

+#define RTC_ADDRESS_REGISTER_C        12  // RO

+#define RTC_ADDRESS_REGISTER_D        13  // RO

+//

+// Date and time initial values.

+// They are used if the RTC values are invalid during driver initialization

+//

+#define RTC_INIT_SECOND  0

+#define RTC_INIT_MINUTE  0

+#define RTC_INIT_HOUR    0

+#define RTC_INIT_DAY     1

+#define RTC_INIT_MONTH   1

+

+#pragma pack(1)

+//

+// Register A

+//

+typedef struct {

+  UINT8    Rs  : 4; // Rate Selection Bits

+  UINT8    Dv  : 3; // Divisor

+  UINT8    Uip : 1; // Update in progress

+} RTC_REGISTER_A_BITS;

+

+typedef union {

+  RTC_REGISTER_A_BITS    Bits;

+  UINT8                  Data;

+} RTC_REGISTER_A;

+

+//

+// Register B

+//

+typedef struct {

+  UINT8    Dse  : 1; // 0 - Daylight saving disabled  1 - Daylight savings enabled

+  UINT8    Mil  : 1; // 0 - 12 hour mode              1 - 24 hour mode

+  UINT8    Dm   : 1; // 0 - BCD Format                1 - Binary Format

+  UINT8    Sqwe : 1; // 0 - Disable SQWE output       1 - Enable SQWE output

+  UINT8    Uie  : 1; // 0 - Update INT disabled       1 - Update INT enabled

+  UINT8    Aie  : 1; // 0 - Alarm INT disabled        1 - Alarm INT Enabled

+  UINT8    Pie  : 1; // 0 - Periodic INT disabled     1 - Periodic INT Enabled

+  UINT8    Set  : 1; // 0 - Normal operation.         1 - Updates inhibited

+} RTC_REGISTER_B_BITS;

+

+typedef union {

+  RTC_REGISTER_B_BITS    Bits;

+  UINT8                  Data;

+} RTC_REGISTER_B;

+

+//

+// Register C

+//

+typedef struct {

+  UINT8    Reserved : 4; // Read as zero.  Can not be written.

+  UINT8    Uf       : 1; // Update End Interrupt Flag

+  UINT8    Af       : 1; // Alarm Interrupt Flag

+  UINT8    Pf       : 1; // Periodic Interrupt Flag

+  UINT8    Irqf     : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE

+} RTC_REGISTER_C_BITS;

+

+typedef union {

+  RTC_REGISTER_C_BITS    Bits;

+  UINT8                  Data;

+} RTC_REGISTER_C;

+

+//

+// Register D

+//

+typedef struct {

+  UINT8    Reserved : 7; // Read as zero.  Can not be written.

+  UINT8    Vrt      : 1; // Valid RAM and Time

+} RTC_REGISTER_D_BITS;

+

+typedef union {

+  RTC_REGISTER_D_BITS    Bits;

+  UINT8                  Data;

+} RTC_REGISTER_D;

+

+#pragma pack()

+

+/**

+  Initialize RTC.

+

+  @param  Global            For global use inside this module.

+

+  @retval EFI_DEVICE_ERROR  Initialization failed due to device error.

+  @retval EFI_SUCCESS       Initialization successful.

+

+**/

+EFI_STATUS

+PcRtcInit (

+  IN PC_RTC_MODULE_GLOBALS  *Global

+  );

+

+/**

+  Sets the current local time and date information.

+

+  @param  Time                  A pointer to the current time.

+  @param  Global                For global use inside this module.

+

+  @retval EFI_SUCCESS           The operation completed successfully.

+  @retval EFI_INVALID_PARAMETER A time field is out of range.

+  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.

+

+**/

+EFI_STATUS

+PcRtcSetTime (

+  IN EFI_TIME               *Time,

+  IN PC_RTC_MODULE_GLOBALS  *Global

+  );

+

+/**

+  Returns the current time and date information, and the time-keeping capabilities

+  of the hardware platform.

+

+  @param  Time          A pointer to storage to receive a snapshot of the current time.

+  @param  Capabilities  An optional pointer to a buffer to receive the real time clock

+                        device's capabilities.

+  @param  Global        For global use inside this module.

+

+  @retval EFI_SUCCESS            The operation completed successfully.

+  @retval EFI_INVALID_PARAMETER  Time is NULL.

+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.

+

+**/

+EFI_STATUS

+PcRtcGetTime (

+  OUT EFI_TIME *Time,

+  OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL

+  IN  PC_RTC_MODULE_GLOBALS *Global

+  );

+

+/**

+  Sets the system wakeup alarm clock time.

+

+  @param  Enabled  Enable or disable the wakeup alarm.

+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.

+                   If Enable is FALSE, then this parameter is optional, and may be NULL.

+  @param  Global   For global use inside this module.

+

+  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled.

+                                If Enable is FALSE, then the wakeup alarm was disabled.

+  @retval EFI_INVALID_PARAMETER A time field is out of range.

+  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.

+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.

+

+**/

+EFI_STATUS

+PcRtcSetWakeupTime (

+  IN BOOLEAN Enable,

+  IN EFI_TIME *Time, OPTIONAL

+  IN PC_RTC_MODULE_GLOBALS  *Global

+  );

+

+/**

+  Returns the current wakeup alarm clock setting.

+

+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.

+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgement.

+  @param  Time     The current alarm setting.

+  @param  Global   For global use inside this module.

+

+  @retval EFI_SUCCESS           The alarm settings were returned.

+  @retval EFI_INVALID_PARAMETER Enabled is NULL.

+  @retval EFI_INVALID_PARAMETER Pending is NULL.

+  @retval EFI_INVALID_PARAMETER Time is NULL.

+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.

+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.

+

+**/

+EFI_STATUS

+PcRtcGetWakeupTime (

+  OUT BOOLEAN                *Enabled,

+  OUT BOOLEAN                *Pending,

+  OUT EFI_TIME               *Time,

+  IN  PC_RTC_MODULE_GLOBALS  *Global

+  );

+

+/**

+  The user Entry Point for PcRTC module.

+

+  This is the entrhy point for PcRTC module. It installs the UEFI runtime service

+  including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().

+

+  @param  ImageHandle    The firmware allocated handle for the EFI image.

+  @param  SystemTable    A pointer to the EFI System Table.

+

+  @retval EFI_SUCCESS    The entry point is executed successfully.

+  @retval Others         Some error occurs when executing this entry point.

+

+**/

+EFI_STATUS

+EFIAPI

+InitializePcRtc (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  );

+

+/**

+  See if all fields of a variable of EFI_TIME type is correct.

+

+  @param   Time   The time to be checked.

+

+  @retval  EFI_INVALID_PARAMETER  Some fields of Time are not correct.

+  @retval  EFI_SUCCESS            Time is a valid EFI_TIME variable.

+

+**/

+EFI_STATUS

+RtcTimeFieldsValid (

+  IN EFI_TIME  *Time

+  );

+

+/**

+  Converts time from EFI_TIME format defined by UEFI spec to RTC's.

+

+  This function converts time from EFI_TIME format defined by UEFI spec to RTC's.

+  If data mode of RTC is BCD, then converts EFI_TIME to it.

+  If RTC is in 12-hour format, then converts EFI_TIME to it.

+

+  @param   Time       On input, the time data read from UEFI to convert

+                      On output, the time converted to RTC format

+  @param   RegisterB  Value of Register B of RTC, indicating data mode

+**/

+VOID

+ConvertEfiTimeToRtcTime (

+  IN OUT EFI_TIME        *Time,

+  IN     RTC_REGISTER_B  RegisterB

+  );

+

+/**

+  Converts time read from RTC to EFI_TIME format defined by UEFI spec.

+

+  This function converts raw time data read from RTC to the EFI_TIME format

+  defined by UEFI spec.

+  If data mode of RTC is BCD, then converts it to decimal,

+  If RTC is in 12-hour format, then converts it to 24-hour format.

+

+  @param   Time       On input, the time data read from RTC to convert

+                      On output, the time converted to UEFI format

+  @param   RegisterB  Value of Register B of RTC, indicating data mode

+                      and hour format.

+

+  @retval  EFI_INVALID_PARAMETER  Parameters passed in are invalid.

+  @retval  EFI_SUCCESS            Convert RTC time to EFI time successfully.

+

+**/

+EFI_STATUS

+ConvertRtcTimeToEfiTime (

+  IN OUT EFI_TIME        *Time,

+  IN     RTC_REGISTER_B  RegisterB

+  );

+

+/**

+  Wait for a period for the RTC to be ready.

+

+  @param    Timeout  Tell how long it should take to wait.

+

+  @retval   EFI_DEVICE_ERROR   RTC device error.

+  @retval   EFI_SUCCESS        RTC is updated and ready.

+**/

+EFI_STATUS

+RtcWaitToUpdate (

+  UINTN  Timeout

+  );

+

+/**

+  See if field Day of an EFI_TIME is correct.

+

+  @param    Time   Its Day field is to be checked.

+

+  @retval   TRUE   Day field of Time is correct.

+  @retval   FALSE  Day field of Time is NOT correct.

+**/

+BOOLEAN

+DayValid (

+  IN  EFI_TIME  *Time

+  );

+

+/**

+  Check if it is a leapyear.

+

+  @param    Time   The time to be checked.

+

+  @retval   TRUE   It is a leapyear.

+  @retval   FALSE  It is NOT a leapyear.

+**/

+BOOLEAN

+IsLeapYear (

+  IN EFI_TIME  *Time

+  );

+

+/**

+  Get the century RTC address from the ACPI FADT table.

+

+  @return  The century RTC address or 0 if not found.

+**/

+UINT8

+GetCenturyRtcAddress (

+  VOID

+  );

+

+/**

+  Notification function of ACPI Table change.

+

+  This is a notification function registered on ACPI Table change event.

+  It saves the Century address stored in ACPI FADT table.

+

+  @param  Event        Event whose notification function is being invoked.

+  @param  Context      Pointer to the notification function's context.

+

+**/

+VOID

+EFIAPI

+PcRtcAcpiTableChangeCallback (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  );

+

+#endif

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni

new file mode 100644

index 0000000000..29813a45fe

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni

@@ -0,0 +1,35 @@

+// /** @file

+// PcRtc Localized Strings and Content

+//

+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+//

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+// This file includes code originally published under the following license.

+

+// /** @file

+// PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL

+//

+// PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL.

+//

+// This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.

+// It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.

+//

+// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>

+//

+// This program and the accompanying materials

+// are licensed and made available under the terms and conditions of the BSD License

+// which accompanies this distribution.  The full text of the license may be found at

+// http://opensource.org/licenses/bsd-license.php

+//

+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+//

+// **/

+

+

+#string STR_MODULE_ABSTRACT             #language en-US "PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL"

+

+#string STR_MODULE_DESCRIPTION          #language en-US "This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table. It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid."

+

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c

new file mode 100644

index 0000000000..f6dc844861

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c

@@ -0,0 +1,186 @@

+/** @file

+  Implements PcRtcEntry.c

+

+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+  SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+/* This file includes code originally published under the following license. */

+

+/** @file

+  Provides Set/Get time operations.

+

+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "PcRtc.h"

+

+PC_RTC_MODULE_GLOBALS  mModuleGlobal;

+

+EFI_HANDLE  mHandle = NULL;

+

+/**

+  Returns the current time and date information, and the time-keeping capabilities

+  of the hardware platform.

+

+  @param  Time          A pointer to storage to receive a snapshot of the current time.

+  @param  Capabilities  An optional pointer to a buffer to receive the real time

+                        clock device's capabilities.

+

+  @retval EFI_SUCCESS            The operation completed successfully.

+  @retval EFI_INVALID_PARAMETER  Time is NULL.

+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.

+

+**/

+EFI_STATUS

+EFIAPI

+PcRtcEfiGetTime (

+  OUT EFI_TIME               *Time,

+  OUT EFI_TIME_CAPABILITIES  *Capabilities  OPTIONAL

+  )

+{

+  return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);

+}

+

+/**

+  Sets the current local time and date information.

+

+  @param  Time                   A pointer to the current time.

+

+  @retval EFI_SUCCESS            The operation completed successfully.

+  @retval EFI_INVALID_PARAMETER  A time field is out of range.

+  @retval EFI_DEVICE_ERROR       The time could not be set due due to hardware error.

+

+**/

+EFI_STATUS

+EFIAPI

+PcRtcEfiSetTime (

+  IN EFI_TIME  *Time

+  )

+{

+  return PcRtcSetTime (Time, &mModuleGlobal);

+}

+

+/**

+  Returns the current wakeup alarm clock setting.

+

+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.

+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgement.

+  @param  Time     The current alarm setting.

+

+  @retval EFI_SUCCESS           The alarm settings were returned.

+  @retval EFI_INVALID_PARAMETER Enabled is NULL.

+  @retval EFI_INVALID_PARAMETER Pending is NULL.

+  @retval EFI_INVALID_PARAMETER Time is NULL.

+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.

+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.

+

+**/

+EFI_STATUS

+EFIAPI

+PcRtcEfiGetWakeupTime (

+  OUT BOOLEAN   *Enabled,

+  OUT BOOLEAN   *Pending,

+  OUT EFI_TIME  *Time

+  )

+{

+  return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);

+}

+

+/**

+  Sets the system wakeup alarm clock time.

+

+  @param  Enabled  Enable or disable the wakeup alarm.

+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.

+                   If Enable is FALSE, then this parameter is optional, and may be NULL.

+

+  @retval EFI_SUCCESS            If Enable is TRUE, then the wakeup alarm was enabled.

+                                 If Enable is FALSE, then the wakeup alarm was disabled.

+  @retval EFI_INVALID_PARAMETER  A time field is out of range.

+  @retval EFI_DEVICE_ERROR       The wakeup time could not be set due to a hardware error.

+  @retval EFI_UNSUPPORTED        A wakeup timer is not supported on this platform.

+

+**/

+EFI_STATUS

+EFIAPI

+PcRtcEfiSetWakeupTime (

+  IN BOOLEAN   Enabled,

+  IN EFI_TIME  *Time       OPTIONAL

+  )

+{

+  return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);

+}

+

+/**

+  The user Entry Point for PcRTC module.

+

+  This is the entrhy point for PcRTC module. It installs the UEFI runtime service

+  including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().

+

+  @param  ImageHandle    The firmware allocated handle for the EFI image.

+  @param  SystemTable    A pointer to the EFI System Table.

+

+  @retval EFI_SUCCESS    The entry point is executed successfully.

+  @retval Others         Some error occurs when executing this entry point.

+

+**/

+EFI_STATUS

+EFIAPI

+InitializePcRtc (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS  Status;

+  EFI_EVENT   Event;

+

+  EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK);

+  mModuleGlobal.CenturyRtcAddress = GetCenturyRtcAddress ();

+

+  Status = PcRtcInit (&mModuleGlobal);

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_CALLBACK,

+                  PcRtcAcpiTableChangeCallback,

+                  NULL,

+                  &gEfiAcpi10TableGuid,

+                  &Event

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_CALLBACK,

+                  PcRtcAcpiTableChangeCallback,

+                  NULL,

+                  &gEfiAcpiTableGuid,

+                  &Event

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  gRT->GetTime       = PcRtcEfiGetTime;

+  gRT->SetTime       = PcRtcEfiSetTime;

+  gRT->GetWakeupTime = PcRtcEfiGetWakeupTime;

+  gRT->SetWakeupTime = PcRtcEfiSetWakeupTime;

+

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &mHandle,

+                  &gEfiRealTimeClockArchProtocolGuid,

+                  NULL,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni

new file mode 100644

index 0000000000..8901872767

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni

@@ -0,0 +1,30 @@

+// /** @file

+// PcRtc Extra Localized Strings and Content

+//

+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+//

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+// This file includes code originally published under the following license.

+

+// /** @file

+// PcRtc Localized Strings and Content

+//

+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>

+//

+// This program and the accompanying materials

+// are licensed and made available under the terms and conditions of the BSD License

+// which accompanies this distribution.  The full text of the license may be found at

+// http://opensource.org/licenses/bsd-license.php

+//

+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+//

+// **/

+

+#string STR_PROPERTIES_MODULE_NAME

+#language en-US

+"PCAT Real Time Clock DXE Driver"

+

+

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

new file mode 100644

index 0000000000..8964795fc7

--- /dev/null

+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

@@ -0,0 +1,93 @@

+## @file

+#  Pcat RealTimeClock Runtime Dxe

+#

+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+# This file includes code originally published under the following license.

+

+## @file

+# PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL.

+#

+# This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.

+# It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.

+#

+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials

+# are licensed and made available under the terms and conditions of the BSD License

+# which accompanies this distribution.  The full text of the license may be found at

+# http://opensource.org/licenses/bsd-license.php

+#

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = PcRtc

+  MODULE_UNI_FILE                = PcRtc.uni

+  FILE_GUID                      = 378D7B65-8DA9-4773-B6E4-A47826A833E1

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = InitializePcRtc

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64 EBC

+#

+

+[Sources]

+  PcRtcEntry.c

+  PcRtc.c

+  PcRtc.h

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  PcAtChipsetPkg/PcAtChipsetPkg.dec

+

+[LibraryClasses]

+  UefiRuntimeServicesTableLib

+  UefiRuntimeLib

+  UefiBootServicesTableLib

+  UefiDriverEntryPoint

+  TimerLib

+  IoLib

+  BaseMemoryLib

+  UefiLib

+  DebugLib

+  BaseLib

+  PcdLib

+  ReportStatusCodeLib

+

+[Protocols]

+  gEfiRealTimeClockArchProtocolGuid             ## PRODUCES

+

+[Guids]

+  ## SOMETIMES_CONSUMES ## Event

+  ## SOMETIMES_CONSUMES ## SystemTable

+  gEfiAcpi10TableGuid

+

+  ## SOMETIMES_CONSUMES ## Event

+  ## SOMETIMES_CONSUMES ## SystemTable

+  gEfiAcpiTableGuid

+

+[FixedPcd]

+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA     ## CONSUMES

+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterB     ## CONSUMES

+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterD     ## CONSUMES

+

+[Pcd]

+  gPcAtChipsetPkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout  ## CONSUMES

+  gPcAtChipsetPkgTokenSpaceGuid.PcdMinimalValidYear             ## CONSUMES

+  gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear             ## CONSUMES

+

+[Depex]

+  gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid

+

+[UserExtensions.TianoCore."ExtraFiles"]

+  PcRtcExtra.uni

--

2.31.1





-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114068): https://edk2.groups.io/g/devel/message/114068
Mute This Topic: https://groups.io/mt/103831180/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-01-19 14:57 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-18  6:50 [edk2-devel] [PATCH 00/33] Introduce AMD Vangogh platform reference code duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 01/33] AMD/AmdPlatformPkg: Check in AMD S3 logo duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 02/33] AMD/VanGoghBoard: Check in ACPI tables duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 03/33] AMD/VanGoghBoard: Check in Capsule update duke.zhai via groups.io
2024-01-23  4:42   ` Chang, Abner via groups.io
2024-01-25  8:25     ` Zhai, MingXin (Duke) via groups.io
2024-01-25 11:45       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 04/33] AMD/VanGoghBoard: Check in AgesaPublic pkg duke.zhai via groups.io
2024-01-23  4:44   ` Chang, Abner via groups.io
2024-01-25  8:17     ` Xing, Eric via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 05/33] AMD/VanGoghBoard: Check in PlatformSecLib duke.zhai via groups.io
2024-01-23  4:46   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 06/33] AMD/VanGoghBoard: Check in AmdIdsExtLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 07/33] AMD/VanGoghBoard: Check in PciPlatform duke.zhai via groups.io
2024-01-23  4:50   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 08/33] AMD/VanGoghBoard: Check in UDKFlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 09/33] AMD/VanGoghBoard: Check in Flash_AB duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 10/33] AMD/VanGoghBoard: Check in FlashUpdate duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 11/33] AMD/VanGoghBoard: Check in FvbServices duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 12/33] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 13/33] AMD/VanGoghBoard: Check in PlatformFlashAccessLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 14/33] AMD/VanGoghBoard: Check in SmbiosLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 15/33] AMD/VanGoghBoard: Check in SpiFlashDeviceLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 16/33] AMD/VanGoghBoard: Check in BaseTscTimerLib duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 17/33] AMD/VanGoghBoard: Check in Smm access module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 18/33] AMD/VanGoghBoard: Check in PciHostBridge module duke.zhai via groups.io
2024-01-18  6:50 ` duke.zhai via groups.io [this message]
2024-01-18  6:50 ` [edk2-devel] [PATCH 20/33] AMD/VanGoghBoard: Check in FTPM module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 22/33] AMD/VanGoghBoard: Check in Vtf0 duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 23/33] AMD/VanGoghBoard: Check in AcpiPlatform duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 24/33] AMD/VanGoghBoard: Check in FchSpi module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module duke.zhai via groups.io
2024-01-23  6:35   ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 26/33] AMD/VanGoghBoard: Check in Smbios platform dxe drivers duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 27/33] AMD/VanGoghBoard: Check in Fsp2WrapperPkg duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 28/33] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module duke.zhai via groups.io
2024-01-23  5:14   ` Chang, Abner via groups.io
2024-01-23 10:20     ` Xing, Eric via groups.io
2024-01-23 10:44       ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 29/33] AMD/VanGoghBoard: Check in SmramSaveState module duke.zhai via groups.io
2024-01-20 14:37   ` Abdul Lateef Attar via groups.io
2024-01-23  5:15     ` Chang, Abner via groups.io
2024-01-23 10:27       ` Xing, Eric via groups.io
2024-01-23 10:44         ` Chang, Abner via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 30/33] AMD/VanGoghBoard: Check in EDK2 override files duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 31/33] AMD/VanGoghBoard: Check in AMD SmmControlPei module duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 32/33] AMD/VanGoghBoard: Check in Chachani board project files and build script duke.zhai via groups.io
2024-01-18  6:50 ` [edk2-devel] [PATCH 33/33] AMD/VanGoghBoard: Improvement coding style duke.zhai via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240118065046.961-20-duke.zhai@amd.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox