On Mon, Nov 06, 2017 at 06:20:36PM +0000, Ard Biesheuvel wrote: > RealTimeClockRuntimeDxe defers the hardware/platform specific handling > of reading/setting the hardware clock to RealTimeClockLib, but for > unknown reasons, it also defers common functionality such as input > validation and recording the timezone and DST settings (which are > informational only and not managed by hardware) > > This has led to a lot of duplication in implementations of RealTimeClockLib > as well as TimeBaseLib, to the point where each library implementation > has its own set of UEFI variables to record the timezone and DST settings. > This makes little sense, and so let's update RealTimeClockRuntimeDxe now > to allow future implementations to rely on the core driver to take care of > these things. > > Note that reading the timezone and DST settings occurs before calling into > the library, so we can phase out this behavior gradually from library > implementations in EDK2, edk2-platforms or out of tree.
Great consolidation, couple of minor questions/comments below: > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org> > --- > EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c | 171 > +++++++++++++++++++- > EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf | 11 +- > 2 files changed, 171 insertions(+), 11 deletions(-) > > diff --git a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c > b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c > index f1e067c0b59e..6b7cc876fa33 100644 > --- a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c > +++ b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c > @@ -1,10 +1,8 @@ > /** @file > Implement EFI RealTimeClock runtime services via RTC Lib. > > - Currently this driver does not support runtime virtual calling. > - > - > Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> > + Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR> > > This program and the accompanying materials > are licensed and made available under the terms and conditions of the BSD > License > @@ -17,14 +15,116 @@ > **/ > > #include <PiDxe.h> > +#include <Library/DebugLib.h> > +#include <Library/RealTimeClockLib.h> > #include <Library/UefiLib.h> > #include <Library/UefiBootServicesTableLib.h> > -#include <Library/RealTimeClockLib.h> > +#include <Library/UefiRuntimeLib.h> > #include <Protocol/RealTimeClock.h> > > EFI_HANDLE mHandle = NULL; > > +// > +// These values can be set by SetTime () and need to be returned by GetTime > () > +// but cannot usually be kept by the RTC hardware, so we store them in a UEFI > +// variable instead. > +// > +typedef struct { > + INT16 TimeZone; > + UINT8 Daylight; > +} NON_VOLATILE_TIME_SETTINGS; > + > +STATIC CONST CHAR16 mTimeSettingsVariableName[] = L"RtcTimeSettings"; > +STATIC NON_VOLATILE_TIME_SETTINGS mTimeSettings; > + > +STATIC > +BOOLEAN > +IsValidTimeZone ( > + IN INT16 TimeZone > + ) > +{ > + return TimeZone == EFI_UNSPECIFIED_TIMEZONE || > + (TimeZone >= -1440 && TimeZone <= 1440); > +} > + > +STATIC > +BOOLEAN > +IsValidDaylight ( > + IN INT8 Daylight > + ) > +{ > + return Daylight == 0 || > + Daylight == EFI_TIME_ADJUST_DAYLIGHT || > + Daylight == (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT); > +} > > +STATIC > +BOOLEAN > +EFIAPI > +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; > + } > +} > + > +STATIC CONST INTN mDayOfMonth[12] = { > + 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 > +}; > + > +STATIC > +BOOLEAN > +EFIAPI > +IsDayValid ( > + IN EFI_TIME *Time > + ) > +{ > + ASSERT (Time->Day >= 1); > + ASSERT (Time->Day <= mDayOfMonth[Time->Month - 1]); > + ASSERT (Time->Month != 2 || (IsLeapYear (Time) && Time->Day <= 29)); Is this me getting confused by basic logic operations, or should the above be something like ASSERT (Time->Month != 2 || (Time->Day <= (28 + IsLeapYear (Time) ? 1 : 0))); ? > + > + if (Time->Day < 1 || > + Time->Day > mDayOfMonth[Time->Month - 1] || > + (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))) { > + return FALSE; > + } > + return TRUE; > +} > + > +STATIC > +BOOLEAN > +EFIAPI > +IsTimeValid( > + IN EFI_TIME *Time > + ) > +{ > + // Check the input parameters are within the range specified by UEFI > + if (Time->Year < 1900 || > + Time->Year > 9999 || > + Time->Month < 1 || > + Time->Month > 12 || > + !IsDayValid (Time) || > + Time->Hour > 23 || > + Time->Minute > 59 || > + Time->Second > 59 || > + !IsValidTimeZone (Time->TimeZone) || > + !IsValidDaylight (Time->Daylight)) { > + return FALSE; > + } > + return TRUE; > +} > > /** > Returns the current time and date information, and the time-keeping > capabilities > @@ -43,9 +143,20 @@ EFI_STATUS > EFIAPI > GetTime ( > OUT EFI_TIME *Time, > - OUT EFI_TIME_CAPABILITIES *Capabilities > + OUT EFI_TIME_CAPABILITIES *Capabilities > ) > { > + if (Time == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Set these first so the RealTimeClockLib implementation > + // can override them based on its own settings. > + // > + Time->TimeZone = mTimeSettings.TimeZone; > + Time->Daylight = mTimeSettings.Daylight; > + > return LibGetTime (Time, Capabilities); > } > > @@ -67,7 +178,41 @@ SetTime ( > IN EFI_TIME *Time > ) > { > - return LibSetTime (Time); > + EFI_STATUS Status; > + BOOLEAN TimeSettingsChanged; > + > + if (Time == NULL || !IsTimeValid (Time)) { > + return EFI_INVALID_PARAMETER; > + } > + > + TimeSettingsChanged = FALSE; > + if (mTimeSettings.TimeZone != Time->TimeZone || > + mTimeSettings.Daylight != Time->Daylight) { > + > + mTimeSettings.TimeZone = Time->TimeZone; > + mTimeSettings.Daylight = Time->Daylight; > + TimeSettingsChanged = TRUE; > + } > + > + Status = LibSetTime (Time); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (TimeSettingsChanged) { > + Status = EfiSetVariable ( > + (CHAR16 *)mTimeSettingsVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > + EFI_VARIABLE_RUNTIME_ACCESS, > + sizeof (mTimeSettings), > + (VOID *)&mTimeSettings); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + } > + return EFI_SUCCESS; > } > > > @@ -138,12 +283,26 @@ InitializeRealTimeClock ( > ) > { > EFI_STATUS Status; > + UINTN Size; > > Status = LibRtcInitialize (ImageHandle, SystemTable); > if (EFI_ERROR (Status)) { > return Status; > } > > + Size = sizeof (mTimeSettings); > + Status = EfiGetVariable ((CHAR16 *)mTimeSettingsVariableName, > + &gEfiCallerIdGuid, NULL, &Size, (VOID *)&mTimeSettings); Funky indentation? / Leif > + if (EFI_ERROR (Status) || > + !IsValidTimeZone (mTimeSettings.TimeZone) || > + !IsValidDaylight (mTimeSettings.Daylight)) { > + DEBUG ((DEBUG_WARN, "%a: using default timezone/daylight settings\n", > + __FUNCTION__)); > + > + mTimeSettings.TimeZone = EFI_UNSPECIFIED_TIMEZONE; > + mTimeSettings.Daylight = 0; > + } > + > SystemTable->RuntimeServices->GetTime = GetTime; > SystemTable->RuntimeServices->SetTime = SetTime; > SystemTable->RuntimeServices->GetWakeupTime = GetWakeupTime; > diff --git a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf > b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf > index 186d4610bd42..d0520392f145 100644 > --- a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf > +++ b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf > @@ -1,8 +1,8 @@ > #/** @file > -# Reset Architectural Protocol Driver as defined in PI > +# Real Time Clock Architectural Protocol Driver as defined in PI > # > -# This Reset module simulates system reset by process exit on NT. > -# Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR> > +# Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR> > +# Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR> > # > # This program and the accompanying materials > # are licensed and made available under the terms and conditions of the BSD > License > @@ -31,10 +31,11 @@ [Packages] > EmbeddedPkg/EmbeddedPkg.dec > > [LibraryClasses] > - UefiBootServicesTableLib > - UefiDriverEntryPoint > DebugLib > RealTimeClockLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiRuntimeLib > > [Protocols] > gEfiRealTimeClockArchProtocolGuid > -- > 2.11.0 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel