From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Leif Lindholm <leif.lindholm@linaro.org>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
Udit Kumar <udit.kumar@nxp.com>
Subject: Re: [PATCH v2 1/3] EmbeddedPkg/RealTimeClockRuntimeDxe: move common functionality into core
Date: Thu, 9 Nov 2017 21:23:03 +0000 [thread overview]
Message-ID: <CAKv+Gu-_TmP_D=_urTo9RCiRVURFywkF3p1YZacsuhuhuGG=1A@mail.gmail.com> (raw)
In-Reply-To: <20171109162602.a5saxky2klnkytnd@bivouac.eciton.net>
On 9 November 2017 at 16:26, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> 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.biesheuvel@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)));
> ?
>
Yeah that does like dodgy. This actuall originates from TimeBaseLib,
which I would like to phase out as well (or reduce to the
EfiToEpochSeconds routines)
I think this should be
ASSERT (Time->Month != 2 || IsLeapYear (Time) || Time->Day <= 28);
>> +
>> + if (Time->Day < 1 ||
>> + Time->Day > mDayOfMonth[Time->Month - 1] ||
>> + (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))) {
Here, we should probably drop the inner parens, which will make the
expression more obviously the negation of the one above.
>> + 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?
>
Yeah. Will fix.
>
>> + 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
>>
next prev parent reply other threads:[~2017-11-09 21:19 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-06 18:20 [PATCH v2 0/3] ArmPlatformPkg EmbeddedPkg: consolidate shared RTC functionality Ard Biesheuvel
2017-11-06 18:20 ` [PATCH v2 1/3] EmbeddedPkg/RealTimeClockRuntimeDxe: move common functionality into core Ard Biesheuvel
2017-11-09 16:26 ` Leif Lindholm
2017-11-09 21:23 ` Ard Biesheuvel [this message]
2017-11-06 18:20 ` [PATCH v2 2/3] ArmPlatformPkg/PL031RealTimeClockLib: remove validation and DST handling Ard Biesheuvel
2017-11-09 16:27 ` Leif Lindholm
2017-11-06 18:20 ` [PATCH v2 3/3] ArmPlatformPkg/PL031RealTimeClockLib: ignore DST setting when timezone is set Ard Biesheuvel
2017-11-09 16:34 ` Leif Lindholm
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='CAKv+Gu-_TmP_D=_urTo9RCiRVURFywkF3p1YZacsuhuhuGG=1A@mail.gmail.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