[edk2,edk2-platforms,v1,06/12] Silicon/Hisilicon: Modify for SBBR fwts SetTime_Func test case

Message ID 20181029033249.45363-7-ming.huang@linaro.org
State New
Headers show
Series
  • [edk2,edk2-platforms,v1,01/12] Silicon/Hisilicon/D06: Add watchdog to GTDT
Related show

Commit Message

Ming Huang Oct. 29, 2018, 3:32 a.m.
There is no variable to keep timezone and daylight, so read it from
the hardware first and create a new variable to keep it for the next
gettime process.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ming Huang <ming.huang@linaro.org>

---
 Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf |   2 +-
 Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h      |   4 +
 Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c   | 175 +++++++++++++++++++-
 3 files changed, 179 insertions(+), 2 deletions(-)

-- 
2.18.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Leif Lindholm Nov. 13, 2018, 11:52 p.m. | #1
On Mon, Oct 29, 2018 at 11:32:43AM +0800, Ming Huang wrote:
> There is no variable to keep timezone and daylight, so read it from

> the hardware first and create a new variable to keep it for the next

> gettime process.


Can you make use of EmbeddedPkg/RealTimeClockRuntimeDxe instead?

/
    Leif

> Contributed-under: TianoCore Contribution Agreement 1.1

> Signed-off-by: Ming Huang <ming.huang@linaro.org>

> ---

>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf |   2 +-

>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h      |   4 +

>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c   | 175 +++++++++++++++++++-

>  3 files changed, 179 insertions(+), 2 deletions(-)

> 

> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

> index 4e963fd453..8e559d7b70 100644

> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

> @@ -42,4 +42,4 @@

>    UefiRuntimeLib        # Use EFiAtRuntime to check stage

>  

>  [Depex]

> -  gEfiCpuArchProtocolGuid

> +  gEfiCpuArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid

> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

> index f329108858..b95ebc654a 100644

> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

> @@ -41,6 +41,10 @@

>  #define M41T83_REGADDR_ALARM2DATE       0x15

>  #define M41T83_REGADDR_ALARM2MONTH      0x14

>  

> +//UEFI SPEC 2.7,page 295

> +#define TIME_ZONE_MIN                 -1440

> +#define TIME_ZONE_MAX                 1440

> +

>  typedef union {

>    struct {

>      UINT8 TD0:1;

> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

> index 1f50ad4b64..a2063aff76 100644

> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

> @@ -32,6 +32,9 @@ extern I2C_DEVICE gRtcDevice;

>  

>  STATIC EFI_LOCK  mRtcLock;

>  

> +STATIC CONST CHAR16  mTimeZoneVariableName[] = L"M41T83RtcTimeZone";

> +STATIC CONST CHAR16  mDaylightVariableName[] = L"M41T83RtcDaylight";

> +

>  /**

>    Read RTC content through its registers.

>  

> @@ -182,6 +185,7 @@ LibSetTime (

>    RTC_M41T83_TIME             BcdTime;

>    UINT16                      CenturyBase = 2000;

>    UINTN                       LineNum = 0;

> +  UINTN                       EpochSeconds;

>  

>    if (NULL == Time) {

>      return EFI_INVALID_PARAMETER;

> @@ -206,6 +210,21 @@ LibSetTime (

>  

>    SetMem (&BcdTime, sizeof (RTC_M41T83_TIME), 0);

>  

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

> +    // Convert to un-adjusted time, i.e. fall back one hour

> +    EpochSeconds -= SEC_PER_HOUR;

> +  }

> +

> +  EpochToEfiTime (EpochSeconds, Time);

> +

>    // Acquire RTC Lock to make access to RTC atomic

>    if (!EfiAtRuntime ()) {

>      EfiAcquireLock (&mRtcLock);

> @@ -254,6 +273,43 @@ LibSetTime (

>      LineNum = __LINE__;

>      goto Exit;

>    }

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

> +    DEBUG ((

> +      DEBUG_ERROR,

> +      "LibSetTime: can not save %s variable to non-volatile storage, Status = %r\n",

> +      mTimeZoneVariableName,

> +      Status

> +      ));

> +    LineNum = __LINE__;

> +    goto Exit;

> +  }

> +

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

> +    DEBUG ((

> +      DEBUG_ERROR,

> +      "LibSetTime: can not to save %s variable to non-volatile storage, Status = %r\n",

> +      mDaylightVariableName,

> +      Status

> +      ));

> +    LineNum = __LINE__;

> +    goto Exit;

> +  }

>  

>  Exit:

>    OemReleaseOwnershipOfRtc ();

> @@ -295,6 +351,10 @@ LibGetTime (

>    UINTN                       LineNum = 0;

>    BOOLEAN                     IsTimeInvalid = FALSE;

>    UINT8                       TimeTemp[7] = {0};

> +  UINTN                       EpochSeconds;

> +  INT16                       TimeZone;

> +  UINT8                       Daylight;

> +  UINTN                       Size;

>  

>    // Ensure Time is a valid pointer

>    if (Time == NULL) {

> @@ -336,7 +396,6 @@ LibGetTime (

>    Time->Hour = BcdToDecimal8 (BcdTime.Hour.Bits.Hours);

>    Time->Minute = BcdToDecimal8 (BcdTime.Minute.Bits.Minutes);

>    Time->Second = BcdToDecimal8 (BcdTime.Second.Bits.Seconds);

> -  Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;

>  

>    if (!IsTimeValid (Time)) {

>        Status = EFI_DEVICE_ERROR;

> @@ -345,6 +404,120 @@ LibGetTime (

>        goto Exit;

>    }

>  

> +  EpochSeconds = EfiTimeToEpoch (Time);

> +

> +  Size = sizeof (TimeZone);

> +  Status = EfiGetVariable (

> +             (CHAR16 *)mTimeZoneVariableName,

> +             &gEfiCallerIdGuid,

> +             NULL,

> +             &Size,

> +             (VOID *)&TimeZone

> +             );

> +

> +  if (EFI_ERROR (Status)) {

> +    DEBUG ((

> +      DEBUG_ERROR,

> +      "LibGetTime: can not get %s variable, Status = %r\n",

> +      mTimeZoneVariableName,

> +      Status

> +      ));

> +    if (Status != EFI_NOT_FOUND) {

> +      LineNum = __LINE__;

> +      goto Exit;

> +    }

> +

> +    // The time zone variable does not exist in non-volatile storage, so create it.

> +    Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;

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

> +      DEBUG ((

> +        DEBUG_ERROR,

> +        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",

> +        mTimeZoneVariableName,

> +        Status

> +        ));

> +      LineNum = __LINE__;

> +      goto Exit;

> +    }

> +  } else {

> +    // Got the time zone

> +    Time->TimeZone = TimeZone;

> +

> +    // Check TimeZone bounds:   -1440 to 1440 or 2047

> +    if (((Time->TimeZone < TIME_ZONE_MIN) || (Time->TimeZone > TIME_ZONE_MAX))

> +          && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {

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

> +    DEBUG ((

> +      DEBUG_ERROR,

> +      "LibGetTime: Failed to get %s variable, Status = %r\n",

> +      mDaylightVariableName,

> +      Status

> +      ));

> +    if (Status != EFI_NOT_FOUND) {

> +      goto Exit;

> +    }

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

> +      DEBUG ((

> +        DEBUG_ERROR,

> +        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",

> +        mDaylightVariableName,

> +        Status

> +        ));

> +      LineNum = __LINE__;

> +      goto Exit;

> +    }

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

> +

>  Exit:

>    OemReleaseOwnershipOfRtc ();

>    // Release RTC Lock.

> -- 

> 2.18.0

> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Ming Huang Nov. 14, 2018, 2:31 p.m. | #2
On 11/14/2018 7:52 AM, Leif Lindholm wrote:
> On Mon, Oct 29, 2018 at 11:32:43AM +0800, Ming Huang wrote:

>> There is no variable to keep timezone and daylight, so read it from

>> the hardware first and create a new variable to keep it for the next

>> gettime process.

> 

> Can you make use of EmbeddedPkg/RealTimeClockRuntimeDxe instead?


Do you mean merge this patch into EmbeddedPkg/RealTimeClockRuntimeDxe?

> 

> /

>     Leif

> 

>> Contributed-under: TianoCore Contribution Agreement 1.1

>> Signed-off-by: Ming Huang <ming.huang@linaro.org>

>> ---

>>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf |   2 +-

>>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h      |   4 +

>>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c   | 175 +++++++++++++++++++-

>>  3 files changed, 179 insertions(+), 2 deletions(-)

>>

>> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

>> index 4e963fd453..8e559d7b70 100644

>> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

>> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

>> @@ -42,4 +42,4 @@

>>    UefiRuntimeLib        # Use EFiAtRuntime to check stage

>>  

>>  [Depex]

>> -  gEfiCpuArchProtocolGuid

>> +  gEfiCpuArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid

>> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

>> index f329108858..b95ebc654a 100644

>> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

>> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

>> @@ -41,6 +41,10 @@

>>  #define M41T83_REGADDR_ALARM2DATE       0x15

>>  #define M41T83_REGADDR_ALARM2MONTH      0x14

>>  

>> +//UEFI SPEC 2.7,page 295

>> +#define TIME_ZONE_MIN                 -1440

>> +#define TIME_ZONE_MAX                 1440

>> +

>>  typedef union {

>>    struct {

>>      UINT8 TD0:1;

>> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

>> index 1f50ad4b64..a2063aff76 100644

>> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

>> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

>> @@ -32,6 +32,9 @@ extern I2C_DEVICE gRtcDevice;

>>  

>>  STATIC EFI_LOCK  mRtcLock;

>>  

>> +STATIC CONST CHAR16  mTimeZoneVariableName[] = L"M41T83RtcTimeZone";

>> +STATIC CONST CHAR16  mDaylightVariableName[] = L"M41T83RtcDaylight";

>> +

>>  /**

>>    Read RTC content through its registers.

>>  

>> @@ -182,6 +185,7 @@ LibSetTime (

>>    RTC_M41T83_TIME             BcdTime;

>>    UINT16                      CenturyBase = 2000;

>>    UINTN                       LineNum = 0;

>> +  UINTN                       EpochSeconds;

>>  

>>    if (NULL == Time) {

>>      return EFI_INVALID_PARAMETER;

>> @@ -206,6 +210,21 @@ LibSetTime (

>>  

>>    SetMem (&BcdTime, sizeof (RTC_M41T83_TIME), 0);

>>  

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

>> +    // Convert to un-adjusted time, i.e. fall back one hour

>> +    EpochSeconds -= SEC_PER_HOUR;

>> +  }

>> +

>> +  EpochToEfiTime (EpochSeconds, Time);

>> +

>>    // Acquire RTC Lock to make access to RTC atomic

>>    if (!EfiAtRuntime ()) {

>>      EfiAcquireLock (&mRtcLock);

>> @@ -254,6 +273,43 @@ LibSetTime (

>>      LineNum = __LINE__;

>>      goto Exit;

>>    }

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

>> +    DEBUG ((

>> +      DEBUG_ERROR,

>> +      "LibSetTime: can not save %s variable to non-volatile storage, Status = %r\n",

>> +      mTimeZoneVariableName,

>> +      Status

>> +      ));

>> +    LineNum = __LINE__;

>> +    goto Exit;

>> +  }

>> +

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

>> +    DEBUG ((

>> +      DEBUG_ERROR,

>> +      "LibSetTime: can not to save %s variable to non-volatile storage, Status = %r\n",

>> +      mDaylightVariableName,

>> +      Status

>> +      ));

>> +    LineNum = __LINE__;

>> +    goto Exit;

>> +  }

>>  

>>  Exit:

>>    OemReleaseOwnershipOfRtc ();

>> @@ -295,6 +351,10 @@ LibGetTime (

>>    UINTN                       LineNum = 0;

>>    BOOLEAN                     IsTimeInvalid = FALSE;

>>    UINT8                       TimeTemp[7] = {0};

>> +  UINTN                       EpochSeconds;

>> +  INT16                       TimeZone;

>> +  UINT8                       Daylight;

>> +  UINTN                       Size;

>>  

>>    // Ensure Time is a valid pointer

>>    if (Time == NULL) {

>> @@ -336,7 +396,6 @@ LibGetTime (

>>    Time->Hour = BcdToDecimal8 (BcdTime.Hour.Bits.Hours);

>>    Time->Minute = BcdToDecimal8 (BcdTime.Minute.Bits.Minutes);

>>    Time->Second = BcdToDecimal8 (BcdTime.Second.Bits.Seconds);

>> -  Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;

>>  

>>    if (!IsTimeValid (Time)) {

>>        Status = EFI_DEVICE_ERROR;

>> @@ -345,6 +404,120 @@ LibGetTime (

>>        goto Exit;

>>    }

>>  

>> +  EpochSeconds = EfiTimeToEpoch (Time);

>> +

>> +  Size = sizeof (TimeZone);

>> +  Status = EfiGetVariable (

>> +             (CHAR16 *)mTimeZoneVariableName,

>> +             &gEfiCallerIdGuid,

>> +             NULL,

>> +             &Size,

>> +             (VOID *)&TimeZone

>> +             );

>> +

>> +  if (EFI_ERROR (Status)) {

>> +    DEBUG ((

>> +      DEBUG_ERROR,

>> +      "LibGetTime: can not get %s variable, Status = %r\n",

>> +      mTimeZoneVariableName,

>> +      Status

>> +      ));

>> +    if (Status != EFI_NOT_FOUND) {

>> +      LineNum = __LINE__;

>> +      goto Exit;

>> +    }

>> +

>> +    // The time zone variable does not exist in non-volatile storage, so create it.

>> +    Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;

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

>> +      DEBUG ((

>> +        DEBUG_ERROR,

>> +        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",

>> +        mTimeZoneVariableName,

>> +        Status

>> +        ));

>> +      LineNum = __LINE__;

>> +      goto Exit;

>> +    }

>> +  } else {

>> +    // Got the time zone

>> +    Time->TimeZone = TimeZone;

>> +

>> +    // Check TimeZone bounds:   -1440 to 1440 or 2047

>> +    if (((Time->TimeZone < TIME_ZONE_MIN) || (Time->TimeZone > TIME_ZONE_MAX))

>> +          && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {

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

>> +    DEBUG ((

>> +      DEBUG_ERROR,

>> +      "LibGetTime: Failed to get %s variable, Status = %r\n",

>> +      mDaylightVariableName,

>> +      Status

>> +      ));

>> +    if (Status != EFI_NOT_FOUND) {

>> +      goto Exit;

>> +    }

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

>> +      DEBUG ((

>> +        DEBUG_ERROR,

>> +        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",

>> +        mDaylightVariableName,

>> +        Status

>> +        ));

>> +      LineNum = __LINE__;

>> +      goto Exit;

>> +    }

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

>> +

>>  Exit:

>>    OemReleaseOwnershipOfRtc ();

>>    // Release RTC Lock.

>> -- 

>> 2.18.0

>>

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Leif Lindholm Nov. 14, 2018, 5:20 p.m. | #3
On Wed, Nov 14, 2018 at 10:31:12PM +0800, Ming Huang wrote:
> On 11/14/2018 7:52 AM, Leif Lindholm wrote:

> > On Mon, Oct 29, 2018 at 11:32:43AM +0800, Ming Huang wrote:

> >> There is no variable to keep timezone and daylight, so read it from

> >> the hardware first and create a new variable to keep it for the next

> >> gettime process.

> > 

> > Can you make use of EmbeddedPkg/RealTimeClockRuntimeDxe instead?

> 

> Do you mean merge this patch into EmbeddedPkg/RealTimeClockRuntimeDxe?


If that makes sense. Certainly the bits that deal with saving
timezone ariables should be in core rather than in a
component-specific library. It already has NON_VOLATILE_TIME_SETTINGS.

/
    Leif

> > 

> > /

> >     Leif

> > 

> >> Contributed-under: TianoCore Contribution Agreement 1.1

> >> Signed-off-by: Ming Huang <ming.huang@linaro.org>

> >> ---

> >>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf |   2 +-

> >>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h      |   4 +

> >>  Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c   | 175 +++++++++++++++++++-

> >>  3 files changed, 179 insertions(+), 2 deletions(-)

> >>

> >> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

> >> index 4e963fd453..8e559d7b70 100644

> >> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

> >> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf

> >> @@ -42,4 +42,4 @@

> >>    UefiRuntimeLib        # Use EFiAtRuntime to check stage

> >>  

> >>  [Depex]

> >> -  gEfiCpuArchProtocolGuid

> >> +  gEfiCpuArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid

> >> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

> >> index f329108858..b95ebc654a 100644

> >> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

> >> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h

> >> @@ -41,6 +41,10 @@

> >>  #define M41T83_REGADDR_ALARM2DATE       0x15

> >>  #define M41T83_REGADDR_ALARM2MONTH      0x14

> >>  

> >> +//UEFI SPEC 2.7,page 295

> >> +#define TIME_ZONE_MIN                 -1440

> >> +#define TIME_ZONE_MAX                 1440

> >> +

> >>  typedef union {

> >>    struct {

> >>      UINT8 TD0:1;

> >> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

> >> index 1f50ad4b64..a2063aff76 100644

> >> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

> >> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c

> >> @@ -32,6 +32,9 @@ extern I2C_DEVICE gRtcDevice;

> >>  

> >>  STATIC EFI_LOCK  mRtcLock;

> >>  

> >> +STATIC CONST CHAR16  mTimeZoneVariableName[] = L"M41T83RtcTimeZone";

> >> +STATIC CONST CHAR16  mDaylightVariableName[] = L"M41T83RtcDaylight";

> >> +

> >>  /**

> >>    Read RTC content through its registers.

> >>  

> >> @@ -182,6 +185,7 @@ LibSetTime (

> >>    RTC_M41T83_TIME             BcdTime;

> >>    UINT16                      CenturyBase = 2000;

> >>    UINTN                       LineNum = 0;

> >> +  UINTN                       EpochSeconds;

> >>  

> >>    if (NULL == Time) {

> >>      return EFI_INVALID_PARAMETER;

> >> @@ -206,6 +210,21 @@ LibSetTime (

> >>  

> >>    SetMem (&BcdTime, sizeof (RTC_M41T83_TIME), 0);

> >>  

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

> >> +    // Convert to un-adjusted time, i.e. fall back one hour

> >> +    EpochSeconds -= SEC_PER_HOUR;

> >> +  }

> >> +

> >> +  EpochToEfiTime (EpochSeconds, Time);

> >> +

> >>    // Acquire RTC Lock to make access to RTC atomic

> >>    if (!EfiAtRuntime ()) {

> >>      EfiAcquireLock (&mRtcLock);

> >> @@ -254,6 +273,43 @@ LibSetTime (

> >>      LineNum = __LINE__;

> >>      goto Exit;

> >>    }

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

> >> +    DEBUG ((

> >> +      DEBUG_ERROR,

> >> +      "LibSetTime: can not save %s variable to non-volatile storage, Status = %r\n",

> >> +      mTimeZoneVariableName,

> >> +      Status

> >> +      ));

> >> +    LineNum = __LINE__;

> >> +    goto Exit;

> >> +  }

> >> +

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

> >> +    DEBUG ((

> >> +      DEBUG_ERROR,

> >> +      "LibSetTime: can not to save %s variable to non-volatile storage, Status = %r\n",

> >> +      mDaylightVariableName,

> >> +      Status

> >> +      ));

> >> +    LineNum = __LINE__;

> >> +    goto Exit;

> >> +  }

> >>  

> >>  Exit:

> >>    OemReleaseOwnershipOfRtc ();

> >> @@ -295,6 +351,10 @@ LibGetTime (

> >>    UINTN                       LineNum = 0;

> >>    BOOLEAN                     IsTimeInvalid = FALSE;

> >>    UINT8                       TimeTemp[7] = {0};

> >> +  UINTN                       EpochSeconds;

> >> +  INT16                       TimeZone;

> >> +  UINT8                       Daylight;

> >> +  UINTN                       Size;

> >>  

> >>    // Ensure Time is a valid pointer

> >>    if (Time == NULL) {

> >> @@ -336,7 +396,6 @@ LibGetTime (

> >>    Time->Hour = BcdToDecimal8 (BcdTime.Hour.Bits.Hours);

> >>    Time->Minute = BcdToDecimal8 (BcdTime.Minute.Bits.Minutes);

> >>    Time->Second = BcdToDecimal8 (BcdTime.Second.Bits.Seconds);

> >> -  Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;

> >>  

> >>    if (!IsTimeValid (Time)) {

> >>        Status = EFI_DEVICE_ERROR;

> >> @@ -345,6 +404,120 @@ LibGetTime (

> >>        goto Exit;

> >>    }

> >>  

> >> +  EpochSeconds = EfiTimeToEpoch (Time);

> >> +

> >> +  Size = sizeof (TimeZone);

> >> +  Status = EfiGetVariable (

> >> +             (CHAR16 *)mTimeZoneVariableName,

> >> +             &gEfiCallerIdGuid,

> >> +             NULL,

> >> +             &Size,

> >> +             (VOID *)&TimeZone

> >> +             );

> >> +

> >> +  if (EFI_ERROR (Status)) {

> >> +    DEBUG ((

> >> +      DEBUG_ERROR,

> >> +      "LibGetTime: can not get %s variable, Status = %r\n",

> >> +      mTimeZoneVariableName,

> >> +      Status

> >> +      ));

> >> +    if (Status != EFI_NOT_FOUND) {

> >> +      LineNum = __LINE__;

> >> +      goto Exit;

> >> +    }

> >> +

> >> +    // The time zone variable does not exist in non-volatile storage, so create it.

> >> +    Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;

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

> >> +      DEBUG ((

> >> +        DEBUG_ERROR,

> >> +        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",

> >> +        mTimeZoneVariableName,

> >> +        Status

> >> +        ));

> >> +      LineNum = __LINE__;

> >> +      goto Exit;

> >> +    }

> >> +  } else {

> >> +    // Got the time zone

> >> +    Time->TimeZone = TimeZone;

> >> +

> >> +    // Check TimeZone bounds:   -1440 to 1440 or 2047

> >> +    if (((Time->TimeZone < TIME_ZONE_MIN) || (Time->TimeZone > TIME_ZONE_MAX))

> >> +          && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {

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

> >> +    DEBUG ((

> >> +      DEBUG_ERROR,

> >> +      "LibGetTime: Failed to get %s variable, Status = %r\n",

> >> +      mDaylightVariableName,

> >> +      Status

> >> +      ));

> >> +    if (Status != EFI_NOT_FOUND) {

> >> +      goto Exit;

> >> +    }

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

> >> +      DEBUG ((

> >> +        DEBUG_ERROR,

> >> +        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",

> >> +        mDaylightVariableName,

> >> +        Status

> >> +        ));

> >> +      LineNum = __LINE__;

> >> +      goto Exit;

> >> +    }

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

> >> +

> >>  Exit:

> >>    OemReleaseOwnershipOfRtc ();

> >>    // Release RTC Lock.

> >> -- 

> >> 2.18.0

> >>

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf
index 4e963fd453..8e559d7b70 100644
--- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf
+++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf
@@ -42,4 +42,4 @@ 
   UefiRuntimeLib        # Use EFiAtRuntime to check stage
 
 [Depex]
-  gEfiCpuArchProtocolGuid
+  gEfiCpuArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h
index f329108858..b95ebc654a 100644
--- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h
+++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClock.h
@@ -41,6 +41,10 @@ 
 #define M41T83_REGADDR_ALARM2DATE       0x15
 #define M41T83_REGADDR_ALARM2MONTH      0x14
 
+//UEFI SPEC 2.7,page 295
+#define TIME_ZONE_MIN                 -1440
+#define TIME_ZONE_MAX                 1440
+
 typedef union {
   struct {
     UINT8 TD0:1;
diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c
index 1f50ad4b64..a2063aff76 100644
--- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c
+++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c
@@ -32,6 +32,9 @@  extern I2C_DEVICE gRtcDevice;
 
 STATIC EFI_LOCK  mRtcLock;
 
+STATIC CONST CHAR16  mTimeZoneVariableName[] = L"M41T83RtcTimeZone";
+STATIC CONST CHAR16  mDaylightVariableName[] = L"M41T83RtcDaylight";
+
 /**
   Read RTC content through its registers.
 
@@ -182,6 +185,7 @@  LibSetTime (
   RTC_M41T83_TIME             BcdTime;
   UINT16                      CenturyBase = 2000;
   UINTN                       LineNum = 0;
+  UINTN                       EpochSeconds;
 
   if (NULL == Time) {
     return EFI_INVALID_PARAMETER;
@@ -206,6 +210,21 @@  LibSetTime (
 
   SetMem (&BcdTime, sizeof (RTC_M41T83_TIME), 0);
 
+  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) {
+    // Convert to un-adjusted time, i.e. fall back one hour
+    EpochSeconds -= SEC_PER_HOUR;
+  }
+
+  EpochToEfiTime (EpochSeconds, Time);
+
   // Acquire RTC Lock to make access to RTC atomic
   if (!EfiAtRuntime ()) {
     EfiAcquireLock (&mRtcLock);
@@ -254,6 +273,43 @@  LibSetTime (
     LineNum = __LINE__;
     goto Exit;
   }
+  // 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)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "LibSetTime: can not save %s variable to non-volatile storage, Status = %r\n",
+      mTimeZoneVariableName,
+      Status
+      ));
+    LineNum = __LINE__;
+    goto Exit;
+  }
+
+  // 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)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "LibSetTime: can not to save %s variable to non-volatile storage, Status = %r\n",
+      mDaylightVariableName,
+      Status
+      ));
+    LineNum = __LINE__;
+    goto Exit;
+  }
 
 Exit:
   OemReleaseOwnershipOfRtc ();
@@ -295,6 +351,10 @@  LibGetTime (
   UINTN                       LineNum = 0;
   BOOLEAN                     IsTimeInvalid = FALSE;
   UINT8                       TimeTemp[7] = {0};
+  UINTN                       EpochSeconds;
+  INT16                       TimeZone;
+  UINT8                       Daylight;
+  UINTN                       Size;
 
   // Ensure Time is a valid pointer
   if (Time == NULL) {
@@ -336,7 +396,6 @@  LibGetTime (
   Time->Hour = BcdToDecimal8 (BcdTime.Hour.Bits.Hours);
   Time->Minute = BcdToDecimal8 (BcdTime.Minute.Bits.Minutes);
   Time->Second = BcdToDecimal8 (BcdTime.Second.Bits.Seconds);
-  Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
 
   if (!IsTimeValid (Time)) {
       Status = EFI_DEVICE_ERROR;
@@ -345,6 +404,120 @@  LibGetTime (
       goto Exit;
   }
 
+  EpochSeconds = EfiTimeToEpoch (Time);
+
+  Size = sizeof (TimeZone);
+  Status = EfiGetVariable (
+             (CHAR16 *)mTimeZoneVariableName,
+             &gEfiCallerIdGuid,
+             NULL,
+             &Size,
+             (VOID *)&TimeZone
+             );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "LibGetTime: can not get %s variable, Status = %r\n",
+      mTimeZoneVariableName,
+      Status
+      ));
+    if (Status != EFI_NOT_FOUND) {
+      LineNum = __LINE__;
+      goto Exit;
+    }
+
+    // The time zone variable does not exist in non-volatile storage, so create it.
+    Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+    // 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)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",
+        mTimeZoneVariableName,
+        Status
+        ));
+      LineNum = __LINE__;
+      goto Exit;
+    }
+  } else {
+    // Got the time zone
+    Time->TimeZone = TimeZone;
+
+    // Check TimeZone bounds:   -1440 to 1440 or 2047
+    if (((Time->TimeZone < TIME_ZONE_MIN) || (Time->TimeZone > TIME_ZONE_MAX))
+          && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {
+      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)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "LibGetTime: Failed to get %s variable, Status = %r\n",
+      mDaylightVariableName,
+      Status
+      ));
+    if (Status != EFI_NOT_FOUND) {
+      goto Exit;
+    }
+    // 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)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "LibGetTime: can not save %s variable to non-volatile storage, Status = %r\n",
+        mDaylightVariableName,
+        Status
+        ));
+      LineNum = __LINE__;
+      goto Exit;
+    }
+  } 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);
+
 Exit:
   OemReleaseOwnershipOfRtc ();
   // Release RTC Lock.