From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) by mx.groups.io with SMTP id smtpd.web12.10879.1612986059941660013 for ; Wed, 10 Feb 2021 11:41:00 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=g1vaKobM; spf=pass (domain: nuviainc.com, ip: 209.85.128.49, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f49.google.com with SMTP id j11so2823953wmi.3 for ; Wed, 10 Feb 2021 11:40:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=pBG4zkMoNAzmlwPHKBRxmcx90h7Za4GMG1FXU3q4tgo=; b=g1vaKobMeNmuyDH3WhZdwrur8gtAxglDeG0Ghc5xO3Wdlta+vC1N6d4N/KMYrM3iwU mb/yE4bsmRzF+Hv+/NUnIJVLcI/3fwpWmHINx98x6tI6lrtSbISEQ8BZdo9Fr40+Dc3G jEKWHJWgQ6dYbZY0IHkWoVmf4qbQNAy99FY5aGow/e2hepSbW95YWX83xb2J7E3tAdTV +RZdoqGMy5mv4RlZfFjz0zWpst2TrBagWH0OuwQ0XsTDDzNhgSt7SR/tbDkg+xTUBYGJ jJl8M8lkVueIY9kAAckM02hEwlCLyqtPs4PK6QI8Q8noPQ088mtXqC9rVOyhznBZ0Fg0 D62A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=pBG4zkMoNAzmlwPHKBRxmcx90h7Za4GMG1FXU3q4tgo=; b=p1J+j9jh2uM3/3mMptwU6DtGrs73X69IC/Y+GiGhCk6KjLXubpT9jbKExCKwxTF6Tr ayrDCzouNBinVgfGWrAs2jfktv2ds7bV+DKN6AaE35kPWcUUF04YTWA0n3y3tWrRHFA4 erSTfeYqi2RSGScNFbLNozarC2C9SGDuTfQxm2175umgUMpnEa517f9eCgYv/O19FQUY HxEmi7JuFa7Qq3YHq9EWNKEGIwFoJRzH5TKu/aR5lVoHVZUiZhJF/9eCOe+xwE/F44GL YDipbvTxPhfrwQASh3Z3e7ktl8sBCl/z/lvbKI9t7ng2GAZxz19GEvcGdx68Q+T+mL3W LRqQ== X-Gm-Message-State: AOAM530XuK1F8+nWCrYi9uDWNaGhxTiozK2MjG0Oj0ivfUd2zfZx4ZEA TfL59BqlfQh/tlk4pucXJcJXAjiQD09cvQ== X-Google-Smtp-Source: ABdhPJzHpMokae2GVcXSN8bF6mGwRE4RsEZoib4Qcfu0Y8my3SNnWlwr0xCpy9GARZLI+K/adY3R1g== X-Received: by 2002:a1c:e104:: with SMTP id y4mr508091wmg.89.1612986058348; Wed, 10 Feb 2021 11:40:58 -0800 (PST) Return-Path: Received: from vanye (cpc1-cmbg19-2-0-cust915.5-4.cable.virginm.net. [82.27.183.148]) by smtp.gmail.com with ESMTPSA id h207sm4342984wme.18.2021.02.10.11.40.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Feb 2021 11:40:57 -0800 (PST) Date: Wed, 10 Feb 2021 19:40:56 +0000 From: "Leif Lindholm" To: Ling Jia Cc: devel@edk2.groups.io Subject: Re: [PATCH v1 09/10] Silicon/Phytium: Added Rtc driver to FT2000/4 Message-ID: <20210210194056.GU1664@vanye> References: <20210205100630.46848-1-jialing@phytium.com.cn> <20210205100630.46848-21-jialing@phytium.com.cn> MIME-Version: 1.0 In-Reply-To: <20210205100630.46848-21-jialing@phytium.com.cn> User-Agent: Mutt/1.10.1 (2018-07-13) Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Feb 05, 2021 at 18:06:29 +0800, Ling Jia wrote: > The RealTimeClockLib implemented EFI RealTimeClock > runtime services via RTC Lib. > > Signed-off-by: Ling Jia > --- > Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec | 1 + > Platform/Phytium/DurianPkg/DurianPkg.dsc | 4 + > Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf | 39 ++ > Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h | 24 ++ > Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c | 456 ++++++++++++++++++++ > 5 files changed, 524 insertions(+) > > diff --git a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec > index 2686ba3cc3a2..4c6c5c5f1118 100644 > --- a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec > +++ b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec > @@ -45,6 +45,7 @@ [PcdsFixedAtBuild.common] > gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize|0x0|UINT64|0x00000005 > gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerBase|0x0|UINT64|0x00000006 > gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerSize|0x0|UINT64|0x00000007 > + gPhytiumPlatformTokenSpaceGuid.PcdRtcBaseAddress|0x0|UINT32|0x00000008 > > [Protocols] > gSpiMasterProtocolGuid = { 0xdf093560, 0xf955, 0x11ea, { 0x96, 0x42, 0x43, 0x9d, 0x80, 0xdd, 0x0b, 0x7c}} > diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/DurianPkg/DurianPkg.dsc > index 48fe1b4fd4ad..89d707569748 100644 > --- a/Platform/Phytium/DurianPkg/DurianPkg.dsc > +++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc > @@ -29,6 +29,10 @@ [LibraryClasses.common] > # Phytium Platform library > ArmPlatformLib|Silicon/Phytium/FT2000-4Pkg/Library/PlatformLib/PlatformLib.inf > > + #FT2000-4Pkg RTC Driver > + RealTimeClockLib|Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf > + TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf > + > # PL011 UART Driver and Dependency Libraries > SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf > PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf > diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf > new file mode 100644 > index 000000000000..8aea6175d8ef > --- /dev/null > +++ b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf > @@ -0,0 +1,39 @@ > +#/** @file > +# Phytium RealTime Clock Library file. > +# > +# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x0001001b > + BASE_NAME = RealTimeClockLib > + FILE_GUID = fb320c94-40fe-11eb-b990-171865af292c > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = RealTimeClockLib > + > +[Sources.common] > + RealTimeClockLib.c > + RealTimeClockLib.h > + > +[Packages] > + ArmPlatformPkg/ArmPlatformPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec > + > +[LibraryClasses] > + IoLib > + DebugLib > + DxeServicesTableLib > + TimeBaseLib > + UefiRuntimeLib > + > +[Guids] > + gEfiEventVirtualAddressChangeGuid > + > +[Pcd] > + gPhytiumPlatformTokenSpaceGuid.PcdRtcBaseAddress > diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h > new file mode 100644 > index 000000000000..41ce002dc3be > --- /dev/null > +++ b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h > @@ -0,0 +1,24 @@ > +/** @file > + Phytium RealTime Clock Header. > + > + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef REAL_TIME_CLOCK_H_ > +#define REAL_TIME_CLOCK_H_ > + > +#define RTC_CMR 0x4 > +#define RTC_AES_SEL 0x8 > +#define RTC_CCR 0xC > +#define RTC_STAT 0x10 > +#define RTC_RSTAT 0x14 > +#define RTC_EOI 0x18 > +#define RTC_CDR_LOW 0x20 > +#define RTC_CCVR 0x24 > +#define RTC_CLR_LOW 0x28 > +#define RTC_CLR 0x2C > + > +#endif // REAL_TIME_CLOCK_H_ > diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c > new file mode 100644 > index 000000000000..42a5b7a57c00 > --- /dev/null > +++ b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c > @@ -0,0 +1,456 @@ > +/** @file > + Implement EFI RealTimeClock runtime services via RTC Lib. > + > + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "RealTimeClockLib.h" > + > +STATIC EFI_EVENT mRtcVirtualAddrChangeEvent; > +STATIC UINTN mRtcBase; > +STATIC CONST CHAR16 mTimeZoneVariableName[] = L"RtcTimeZone"; > +STATIC CONST CHAR16 mDaylightVariableName[] = L"RtcDaylight"; > + > +/** > + 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. > + @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. > + > +**/ > +EFI_STATUS > +EFIAPI > +LibGetTime ( > + OUT EFI_TIME *Time, > + OUT EFI_TIME_CAPABILITIES *Capabilities > + ) > +{ > + UINT32 EpochSeconds; > + INT16 TimeZone; > + UINT8 Daylight; > + UINTN Size; > + EFI_STATUS Status; > + > + // Ensure Time is a valid pointer > + if (Time == NULL) { > + return EFI_INVALID_PARAMETER; Missing indentation. > + } > + > + MmioWrite32 (mRtcBase + RTC_AES_SEL, 0x100); > + // > + //read cdr high 32bit > + // > + EpochSeconds = MmioRead32 (mRtcBase + RTC_CCVR); > + MmioRead32 (mRtcBase + RTC_CDR_LOW); > + // > + // Get the current time zone information from non-volatile storage > + // > + Size = sizeof (TimeZone); > + Status = EfiGetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + NULL, > + &Size, > + (VOID *)&TimeZone > + ); > + > + if (EFI_ERROR (Status)) { > + ASSERT (Status != EFI_INVALID_PARAMETER); > + ASSERT (Status != EFI_BUFFER_TOO_SMALL); > + // > + // The time zone variable does not exist in non-volatile storage, so create it. > + //UTC+8:00 > + // > + Time->TimeZone = -480; > + // > + // Store it > + // > + Status = EfiSetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + Size, > + (VOID *)&(Time->TimeZone) > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else { > + // > + // Got the time zone > + // > + Time->TimeZone = TimeZone; > + // > + // Check TimeZone bounds: -1440 to 1440 or 2047 > + // > + if (((Time->TimeZone < -1440) || (Time->TimeZone > 1440)) > + && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) { Please use IsValidTimeZone () from EmbeddedPkg/Library/TimeBaseLib. / Leif > + Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; > + } > + // > + // Adjust for the correct time zone > + // > + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { > + EpochSeconds -= Time->TimeZone * SEC_PER_MIN; > + } > + } > + // > + // Get the current daylight information from non-volatile storage > + // > + Size = sizeof (Daylight); > + Status = EfiGetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + NULL, > + &Size, > + (VOID *)&Daylight > + ); > + if (EFI_ERROR (Status)) { > + ASSERT(Status != EFI_INVALID_PARAMETER); > + ASSERT(Status != EFI_BUFFER_TOO_SMALL); > + // > + // The daylight variable does not exist in non-volatile storage, so create it. > + // > + Time->Daylight = 0; > + // > + // Store it > + // > + Status = EfiSetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + Size, > + (VOID *)&(Time->Daylight) > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } else { > + // > + // Got the daylight information > + // > + Time->Daylight = Daylight; > + // > + // 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; > + } > + } > + > + // > + // Convert from internal 32-bit time to UEFI time > + // > + EpochToEfiTime (EpochSeconds, Time); > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Sets the current local time and date information. > + > + @param[in] 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 > + ) > +{ > + UINTN EpochSeconds; > + EFI_STATUS Status; > + // > + // the maximum time span is just over 136 years. > + // Time is stored in Unix Epoch format, so it starts in 1970, > + // Therefore it can not exceed the year 2106. > + // > + if ((Time->Year < 1970) || (Time->Year >= 2106)) { > + return EFI_UNSUPPORTED; > + } > + 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 > + // > + if (((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) > + && (EpochSeconds > SEC_PER_HOUR)) { > + // > + // Convert to un-adjusted time, i.e. fall back one hour > + // > + EpochSeconds -= SEC_PER_HOUR; > + } > + // > + // Set the Rtc > + // > + MmioWrite32(mRtcBase + RTC_AES_SEL, 0x100); > + MmioWrite32 (mRtcBase + RTC_CLR_LOW, 0x0); > + MmioWrite32 (mRtcBase + RTC_CLR, (UINT32)EpochSeconds); > + // > + // Save the current time zone information into non-volatile storage > + // > + Status = EfiSetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + sizeof (Time->TimeZone), > + (VOID *)&(Time->TimeZone) > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // > + // Save the current daylight information into non-volatile storage > + // > + Status = EfiSetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + sizeof(Time->Daylight), > + (VOID *)&(Time->Daylight) > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + return EFI_SUCCESS; > +} > + > + > +/** > + Returns the current wakeup alarm clock setting. > + > + @param[out] Enabled Indicates if the alarm is currently enabled or disabled. > + @param[out] Pending Indicates if the alarm signal is pending and requires acknowledgement. > + @param[out] 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 > + ) > +{ > + // Not a required feature > + return EFI_UNSUPPORTED; > +} > + > + > +/** > + Sets the system wakeup alarm clock time. > + > + @param[in] Enabled Enable or disable the wakeup alarm. > + @param[out] 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 > + ) > +{ > + // Not a required feature > + 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. > + // > + EfiConvertPointer (0x0, (VOID**)&mRtcBase); > + > + return; > +} > + > +/** > + 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[in] ImageHandle Handle that identifies the loaded image. > + @param[in] 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; > + EFI_HANDLE Handle; > + INT16 TimeZone; > + UINTN Size; > + EFI_TIME Time; > + UINT8 Daylight; > + // > + // Initialize RTC Base Address > + // > + mRtcBase = PcdGet32(PcdRtcBaseAddress); > + // > + // Declare the controller as EFI_MEMORY_RUNTIME > + // > + Status = gDS->AddMemorySpace ( > + EfiGcdMemoryTypeMemoryMappedIo, > + mRtcBase, SIZE_4KB, > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // > + //init timezone > + // > + Size = sizeof (TimeZone); > + Status = EfiGetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + NULL, > + &Size, > + (VOID *)&TimeZone > + ); > + if (EFI_ERROR (Status)) { > + ASSERT(Status != EFI_INVALID_PARAMETER); > + ASSERT(Status != EFI_BUFFER_TOO_SMALL); > + // > + // The time zone variable does not exist in non-volatile storage, so create it. > + //UTC 8:00 > + // > + Time.TimeZone = -480; > + // > + // Store it > + // > + Status = EfiSetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + Size, > + (VOID *)&(Time.TimeZone) > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + // > + //daylight init > + // > + Size = sizeof (Daylight); > + Status = EfiGetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + NULL, > + &Size, > + (VOID *)&Daylight > + ); > + if (EFI_ERROR (Status)) { > + ASSERT(Status != EFI_INVALID_PARAMETER); > + ASSERT(Status != EFI_BUFFER_TOO_SMALL); > + // > + // The daylight variable does not exist in non-volatile storage, so create it. > + // > + Time.Daylight = 0; > + // > + // Store it > + // > + Status = EfiSetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + Size, > + (VOID *)&(Time.Daylight) > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + Status = gDS->SetMemorySpaceAttributes (mRtcBase, SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // > + // Install the protocol > + // > + Handle = NULL; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &Handle, > + &gEfiRealTimeClockArchProtocolGuid, NULL, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + // > + // Register for the virtual address change event > + // > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + LibRtcVirtualNotifyEvent, > + NULL, > + &gEfiEventVirtualAddressChangeGuid, > + &mRtcVirtualAddrChangeEvent > + ); > + ASSERT_EFI_ERROR (Status); > + return Status; > +} > -- > 2.25.1 >