On Wed, May 26, 2021 at 17:06:59 +0700, Nhi Pham wrote: > From: Vu Nguyen <vungu...@os.amperecomputing.com> > > This library adds the support for retrieving and updating system > datetime over real RTC PCF85063 device on Mt. Jade platform instead of > using virtual RTC. > > Cc: Thang Nguyen <th...@os.amperecomputing.com> > Cc: Chuong Tran <chu...@os.amperecomputing.com> > Cc: Phong Vo <ph...@os.amperecomputing.com> > Cc: Leif Lindholm <l...@nuviainc.com> > Cc: Michael D Kinney <michael.d.kin...@intel.com> > Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> > Cc: Nate DeSimone <nathaniel.l.desim...@intel.com> > > Signed-off-by: Vu Nguyen <vungu...@os.amperecomputing.com> > --- > Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > | 2 + > Platform/Ampere/JadePkg/Jade.dsc > | 2 +- > > Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf > | 44 +++ > Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h > | 91 ++++++ > Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c > | 317 ++++++++++++++++++++ > > Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c > | 257 ++++++++++++++++ > 6 files changed, 712 insertions(+), 1 deletion(-) > > diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > index 6a6f72e995af..9f19f495fad2 100755 > --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > @@ -84,6 +84,8 @@ [LibraryClasses.common] > > SystemFirmwareInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf > > AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf > TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf > + I2cLib|Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf > + GpioLib|Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf > > MmCommunicationLib|Silicon/Ampere/AmpereAltraPkg/Library/MmCommunicationLib/MmCommunicationLib.inf > > # > diff --git a/Platform/Ampere/JadePkg/Jade.dsc > b/Platform/Ampere/JadePkg/Jade.dsc > index f92855af99ab..f37ab1a92e44 100755 > --- a/Platform/Ampere/JadePkg/Jade.dsc > +++ b/Platform/Ampere/JadePkg/Jade.dsc > @@ -73,7 +73,7 @@ [LibraryClasses] > # > # RTC Library: Common RTC > # > - > RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf > + > RealTimeClockLib|Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf > > # > # Library for FailSafe support > diff --git > a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf > > b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf > new file mode 100644 > index 000000000000..1fe561cc0ec9 > --- /dev/null > +++ > b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf > @@ -0,0 +1,44 @@ > +## @file > +# > +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + MODULE_TYPE = BASE > + BASE_NAME = PCF85063RealTimeClockLib > + FILE_GUID = 271569F6-5522-4006-9FF5-F07A59473AAC > + LIBRARY_CLASS = RealTimeClockLib > + VERSION_STRING = 1.0 > + > +[Sources.common] > + PCF85063.c > + PCF85063.h > + PCF85063RealTimeClockLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec > + > +[LibraryClasses] > + ArmGenericTimerCounterLib > + ArmLib > + BaseLib > + DebugLib > + GpioLib > + DxeServicesTableLib > + I2cLib > + TimeBaseLib > + TimerLib > + UefiLib > + UefiRuntimeLib > + > +[Guids] > + gEfiEventVirtualAddressChangeGuid > diff --git > a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h > b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h > new file mode 100644 > index 000000000000..03ce4d29a03f > --- /dev/null > +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h > @@ -0,0 +1,91 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PCF85063_H_ > +#define PCF85063_H_ > + > +#include <Uefi.h> > + > +#include <Library/BaseLib.h> > +#include <Library/RealTimeClockLib.h> > + > +// > +// I2C bus address that RTC connected to > +// > +#define I2C_RTC_BUS_ADDRESS 1 > + > +// > +// I2C RTC bus speed > +// > +#define I2C_RTC_BUS_SPEED 100000 > + > +// > +// I2C chip address that RTC connected to > +// > +#define I2C_RTC_CHIP_ADDRESS 0x51 > + > +// > +// The GPI PIN that tell if RTC can be access > +// > +#define I2C_RTC_ACCESS_GPIO_PIN 28 > + > +/** > + * Returns the current time and date information of the hardware platform. > + * > + * @param Time A pointer to storage to receive a snapshot > of the current time. > + * > + * > + * @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 > +PlatformGetTime ( > + OUT EFI_TIME *Time > + ); > + > +/** > + * Set the time and date information to the hardware platform. > + * > + * @param Time A pointer to storage to set the current > time to hardware platform. > + * > + * > + * @retval EFI_SUCCESS The operation completed successfully. > + * @retval EFI_INVALID_PARAMETER Time is NULL. > + * @retval EFI_DEVICE_ERROR The time could not be set due due to > hardware error. > + **/ > +EFI_STATUS > +EFIAPI > +PlatformSetTime ( > + IN EFI_TIME *Time > + ); > + > +/** > + * Callback function for hardware platform to convert data pointers to > virtual address > + */ > +VOID > +EFIAPI > +PlatformVirtualAddressChangeEvent ( > + VOID > + ); > + > +/** > + * Callback function for hardware platform to initialize private data > + * > + * > + * @retval EFI_SUCCESS The operation completed successfully. > + * @retval Others The error status indicates the error > + */ > +EFI_STATUS > +EFIAPI > +PlatformInitialize ( > + VOID > + ); > + > +#endif /* PCF85063_H_ */ > diff --git > a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c > b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c > new file mode 100644 > index 000000000000..f9fa125d9d7e > --- /dev/null > +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c > @@ -0,0 +1,317 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Uefi.h> > + > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/GpioLib.h> > +#include <Library/I2cLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/PcdLib.h> > +#include <Library/TimerLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiLib.h> > +#include <Library/UefiRuntimeLib.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > + > +#include "PCF85063.h" > + > +#define RTC_TIMEOUT_WAIT_ACCESS 100000 /* 100 miliseconds */ > +#define RTC_DEFAULT_MIN_YEAR 2000 > +#define RTC_DEFAULT_MAX_YEAR 2099 > + > +#define RTC_ADDR 0x4 > +#define RTC_DATA_BUF_LEN 8 > + > +/** > + * PCF85063 register offsets > + */ > +#define PCF85063_OFFSET_SEC 0x0 > +#define PCF85063_OFFSET_MIN 0x1 > +#define PCF85063_OFFSET_HR 0x2 > +#define PCF85063_OFFSET_DAY 0x3 > +#define PCF85063_OFFSET_WKD 0x4 > +#define PCF85063_OFFSET_MON 0x5 > +#define PCF85063_OFFSET_YEA 0x6 > + > +/** > + * PCF85063 encoding macros > + */ > +#define PCF85063_SEC_ENC(s) (((((s) / 10) & 0x7) << 4) | (((s) % 10) & 0xf)) > +#define PCF85063_MIN_ENC(m) (((((m) / 10) & 0x7) << 4) | (((m) % 10) & 0xf)) > +#define PCF85063_HR_ENC(h) (((((h) / 10) & 0x3) << 4) | (((h) % 10) & 0xf)) > +#define PCF85063_DAY_ENC(d) (((((d) / 10) & 0x3) << 4) | (((d) % 10) & 0xf)) > +#define PCF85063_WKD_ENC(w) ((w) & 0x7) > +#define PCF85063_MON_ENC(m) (((((m) / 10) & 0x1) << 4) | (((m) % 10) & 0xf)) > +#define PCF85063_YEA_ENC(y) (((((y) / 10) & 0xf) << 4) | (((y) % 10) & 0xf)) > + > +/** > + * PCF85063 decoding macros > + */ > +#define PCF85063_SEC_DEC(s) (((((s) & 0x70) >> 4) * 10) + ((s) & 0xf)) > +#define PCF85063_MIN_DEC(m) (((((m) & 0x70) >> 4) * 10) + ((m) & 0xf)) > +#define PCF85063_HR_DEC(h) (((((h) & 0x30) >> 4) * 10) + ((h) & 0xf)) > +#define PCF85063_DAY_DEC(d) (((((d) & 0x30) >> 4)* 10) + ((d) & 0xf))
*twitch* Please add that space before '*' like on all other lines. With that: Reviewed-by: Leif Lindholm <l...@nuviainc.com> / Leif > +#define PCF85063_WKD_DEC(w) ((w) & 0x7) > +#define PCF85063_MON_DEC(m) (((((m) & 0x10) >> 4) * 10) + ((m) & 0xf)) > +#define PCF85063_YEA_DEC(y) (((((y) & 0xf0) >> 4) * 10) + ((y) & 0xf)) > + > +/* Buffer pointers to convert Vir2Phys and Phy2Vir */ > +STATIC volatile UINT64 RtcBufVir; > +STATIC volatile UINT64 RtcBufPhy; > + > +STATIC > +EFI_STATUS > +RtcI2cWaitAccess ( > + VOID > + ) > +{ > + INTN Timeout; > + > + Timeout = RTC_TIMEOUT_WAIT_ACCESS; > + while ((GpioReadBit (I2C_RTC_ACCESS_GPIO_PIN) != 0) && (Timeout > 0)) { > + MicroSecondDelay (100); > + Timeout -= 100; > + } > + > + if (Timeout <= 0) { > + DEBUG ((DEBUG_ERROR, "%a: Timeout while waiting access RTC\n", > __FUNCTION__)); > + return EFI_TIMEOUT; > + } > + > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +RtcI2cRead ( > + IN UINT8 Addr, > + IN OUT UINT64 Data, > + IN UINT32 DataLen > + ) > +{ > + EFI_STATUS Status; > + UINT32 TmpLen; > + > + if (EFI_ERROR (RtcI2cWaitAccess ())) { > + return EFI_DEVICE_ERROR; > + } > + > + Status = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + // > + // Send the slave address for read > + // > + TmpLen = 1; > + Status = I2cWrite (I2C_RTC_BUS_ADDRESS, I2C_RTC_CHIP_ADDRESS, (UINT8 > *)&Addr, &TmpLen); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + // > + // Read back the time > + // > + Status = I2cRead (I2C_RTC_BUS_ADDRESS, I2C_RTC_CHIP_ADDRESS, NULL, 0, > (UINT8 *)Data, &DataLen); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +RtcI2cWrite ( > + IN UINT8 Addr, > + IN UINT64 Data, > + IN UINT32 DataLen > + ) > +{ > + EFI_STATUS Status; > + UINT8 TmpBuf[RTC_DATA_BUF_LEN + 1]; > + UINT32 TmpLen; > + > + if (EFI_ERROR (RtcI2cWaitAccess ())) { > + return EFI_DEVICE_ERROR; > + } > + > + if (DataLen > sizeof (TmpBuf) - 1) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + // > + // The first byte is the address > + // > + TmpBuf[0] = Addr; > + TmpLen = DataLen + 1; > + CopyMem ((VOID *)(TmpBuf + 1), (VOID *)Data, DataLen); > + > + Status = I2cWrite (I2C_RTC_BUS_ADDRESS, I2C_RTC_CHIP_ADDRESS, TmpBuf, > &TmpLen); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + * Returns the current time and date information of the hardware platform. > + * > + * @param Time A pointer to storage to receive a snapshot > of the current time. > + * > + * > + * @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 > +PlatformGetTime ( > + OUT EFI_TIME *Time > + ) > +{ > + EFI_STATUS Status; > + UINT8 *Data; > + > + if (Time == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = RtcI2cRead (RTC_ADDR, RtcBufVir, RTC_DATA_BUF_LEN); > + > + Data = (UINT8 *)RtcBufVir; > + if (Status == EFI_SUCCESS) { > + Time->Second = PCF85063_SEC_DEC (Data[PCF85063_OFFSET_SEC]); > + Time->Minute = PCF85063_MIN_DEC (Data[PCF85063_OFFSET_MIN]); > + Time->Hour = PCF85063_HR_DEC (Data[PCF85063_OFFSET_HR]); > + Time->Day = PCF85063_DAY_DEC (Data[PCF85063_OFFSET_DAY]); > + Time->Month = PCF85063_MON_DEC (Data[PCF85063_OFFSET_MON]); > + Time->Year = PCF85063_YEA_DEC (Data[PCF85063_OFFSET_YEA]); > + Time->Year += RTC_DEFAULT_MIN_YEAR; > + if (Time->Year > RTC_DEFAULT_MAX_YEAR) { > + Time->Year = RTC_DEFAULT_MAX_YEAR; > + } > + if (Time->Year < RTC_DEFAULT_MIN_YEAR) { > + Time->Year = RTC_DEFAULT_MIN_YEAR; > + } > + } > + > + return Status; > +} > + > +/** > + * Set the time and date information to the hardware platform. > + * > + * @param Time A pointer to storage to set the current > time to hardware platform. > + * > + * > + * @retval EFI_SUCCESS The operation completed successfully. > + * @retval EFI_INVALID_PARAMETER Time is NULL. > + * @retval EFI_DEVICE_ERROR The time could not be set due due to > hardware error. > + **/ > +EFI_STATUS > +EFIAPI > +PlatformSetTime ( > + IN EFI_TIME *Time > + ) > +{ > + UINT8 *Data; > + > + if (Time == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Time->Year < RTC_DEFAULT_MIN_YEAR || > + Time->Year > RTC_DEFAULT_MAX_YEAR) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + Data = (UINT8 *)RtcBufVir; > + Data[PCF85063_OFFSET_SEC] = PCF85063_SEC_ENC (Time->Second); > + Data[PCF85063_OFFSET_MIN] = PCF85063_MIN_ENC (Time->Minute); > + Data[PCF85063_OFFSET_HR] = PCF85063_HR_ENC (Time->Hour); > + Data[PCF85063_OFFSET_DAY] = PCF85063_DAY_ENC (Time->Day); > + Data[PCF85063_OFFSET_MON] = PCF85063_MON_ENC (Time->Month); > + Data[PCF85063_OFFSET_YEA] = PCF85063_YEA_ENC (Time->Year - > RTC_DEFAULT_MIN_YEAR); > + > + return RtcI2cWrite (RTC_ADDR, RtcBufVir, RTC_DATA_BUF_LEN); > +} > + > +/** > + * Callback function for hardware platform to convert data pointers to > virtual address > + */ > +VOID > +EFIAPI > +PlatformVirtualAddressChangeEvent ( > + VOID > + ) > +{ > + EfiConvertPointer (0x0, (VOID **)&RtcBufVir); > +} > + > +/** > + * Callback function for hardware platform to initialize private data > + * > + * > + * @retval EFI_SUCCESS The operation completed successfully. > + * @retval Others The error status indicates the error > + */ > +EFI_STATUS > +EFIAPI > +PlatformInitialize ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + > + /* > + * Allocate the buffer for RTC data > + * The buffer can be accessible after ExitBootServices > + */ > + RtcBufVir = (UINT64)AllocateRuntimeZeroPool (RTC_DATA_BUF_LEN); > + ASSERT_EFI_ERROR (RtcBufVir); > + RtcBufPhy = (UINT64)RtcBufVir; > + > + Status = I2cSetupRuntime (I2C_RTC_BUS_ADDRESS); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a:%d I2cSetupRuntime() failed - %r \n", > + __FUNCTION__, > + __LINE__, > + Status > + )); > + return Status; > + } > + > + Status = GpioSetupRuntime (I2C_RTC_ACCESS_GPIO_PIN); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a:%d GpioSetupRuntime() failed - %r \n", > + __FUNCTION__, > + __LINE__, > + Status > + )); > + return Status; > + } > + > + return EFI_SUCCESS; > +} > diff --git > a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c > > b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c > new file mode 100755 > index 000000000000..ef8c71e92c18 > --- /dev/null > +++ > b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c > @@ -0,0 +1,257 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <PiDxe.h> > +#include <Uefi.h> > + > +#include <Guid/EventGroup.h> > +#include <Library/ArmGenericTimerCounterLib.h> > +#include <Library/ArmLib.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DxeServicesTableLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/RealTimeClockLib.h> > +#include <Library/TimeBaseLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiLib.h> > +#include <Library/UefiRuntimeLib.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > +#include <Protocol/RealTimeClock.h> > + > +#include "PCF85063.h" > + > +#define TICKS_PER_SEC (ArmGenericTimerGetTimerFreq ()) > + > +STATIC EFI_EVENT mVirtualAddressChangeEvent = NULL; > + > +STATIC UINT64 mLastSavedSystemCount = 0; > +STATIC UINT64 mLastSavedTimeEpoch = 0; > + > +/** > + * 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 > +LibGetTime ( > + OUT EFI_TIME *Time, > + OUT EFI_TIME_CAPABILITIES *Capabilities > + ) > +{ > + EFI_STATUS Status; > + UINT64 CurrentSystemCount; > + UINT64 TimeElapsed; > + UINTN EpochSeconds; > + > + if ((mLastSavedTimeEpoch == 0) || EfiAtRuntime ()) { > + Status = PlatformGetTime (Time); > + if (EFI_ERROR (Status)) { > + // Failed to read platform RTC so create fake time > + Time->Second = 0; > + Time->Minute = 0; > + Time->Hour = 10; > + Time->Day = 1; > + Time->Month = 1; > + Time->Year = 2017; > + } > + > + EpochSeconds = EfiTimeToEpoch (Time); > + if (!EfiAtRuntime ()) { > + mLastSavedTimeEpoch = EpochSeconds; > + mLastSavedSystemCount = ArmGenericTimerGetSystemCount (); > + } > + } else { > + CurrentSystemCount = ArmGenericTimerGetSystemCount (); > + if (CurrentSystemCount >= mLastSavedSystemCount) { > + TimeElapsed = (CurrentSystemCount - mLastSavedSystemCount) / > MultU64x32 (1, TICKS_PER_SEC); > + EpochSeconds = mLastSavedTimeEpoch + TimeElapsed; > + } else { > + // System counter overflow 64 bits > + // Call GetTime again to read the date from RTC HW, not using generic > timer system counter > + mLastSavedTimeEpoch = 0; > + return LibGetTime (Time, Capabilities); > + } > + } > + > + // Adjust for the correct timezone > + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { > + EpochSeconds += Time->TimeZone * SEC_PER_MIN; > + } > + > + // Adjust for the correct period > + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { > + // Convert to adjusted time, i.e. spring forwards one hour > + EpochSeconds += SEC_PER_HOUR; > + } > + > + EpochToEfiTime (EpochSeconds, Time); > + > + return EFI_SUCCESS; > +} > + > +/** > + * 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 > +LibSetTime ( > + IN EFI_TIME *Time > + ) > +{ > + EFI_STATUS Status; > + UINTN EpochSeconds; > + > + EpochSeconds = EfiTimeToEpoch (Time); > + > + // Adjust for the correct time zone, i.e. convert to UTC time zone > + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { > + EpochSeconds -= Time->TimeZone * SEC_PER_MIN; > + } > + > + // Adjust for the correct period, i.e. fall back one hour > + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { > + EpochSeconds -= SEC_PER_HOUR; > + } > + > + EpochToEfiTime (EpochSeconds, Time); > + > + Status = PlatformSetTime (Time); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (!EfiAtRuntime ()) { > + mLastSavedTimeEpoch = EpochSeconds; > + mLastSavedSystemCount = ArmGenericTimerGetSystemCount (); > + } > + > + 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 acknowledgement. > + * @param Time The current alarm setting. > + * > + * @retval EFI_SUCCESS The alarm settings were returned. > + * @retval EFI_INVALID_PARAMETER Any parameter is NULL. > + * @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due > to a hardware error. > + */ > +EFI_STATUS > +EFIAPI > +LibGetWakeupTime ( > + OUT BOOLEAN *Enabled, > + OUT BOOLEAN *Pending, > + OUT EFI_TIME *Time > + ) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + * 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. > + * > + * @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 > +LibSetWakeupTime ( > + IN BOOLEAN Enabled, > + OUT EFI_TIME *Time > + ) > +{ > + return EFI_UNSUPPORTED; > +} > + > +/** > + Fixup internal data so that EFI can be call in virtual mode. > + Call the passed in Child Notify event and convert any pointers in > + lib to virtual mode. > + > + @param[in] Event The Event that is being processed > + @param[in] Context Event Context > +**/ > +VOID > +EFIAPI > +LibRtcVirtualNotifyEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + // > + // Only needed if you are going to support the OS calling RTC functions in > virtual mode. > + // You will need to call EfiConvertPointer (). To convert any stored > physical addresses > + // to virtual address. After the OS transitions to calling in virtual > mode, all future > + // runtime calls will be made in virtual mode. > + // > + PlatformVirtualAddressChangeEvent (); > +} > + > +/** > + * This is the declaration of an EFI image entry point. This can be the > entry point to an application > + * written to this specification, an EFI boot service driver, or an EFI > runtime driver. > + * > + * @param ImageHandle Handle that identifies the loaded image. > + * @param SystemTable System Table for this image. > + * > + * @retval EFI_SUCCESS The operation completed successfully. > + */ > +EFI_STATUS > +EFIAPI > +LibRtcInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + Status = PlatformInitialize (); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // > + // Register for the virtual address change event > + // > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + LibRtcVirtualNotifyEvent, > + NULL, > + &gEfiEventVirtualAddressChangeGuid, > + &mVirtualAddressChangeEvent > + ); > + ASSERT_EFI_ERROR (Status); > + > + return EFI_SUCCESS; > +} > -- > 2.17.1 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#76088): https://edk2.groups.io/g/devel/message/76088 Mute This Topic: https://groups.io/mt/83097102/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-