mirror of https://github.com/acidanthera/audk.git
291 lines
6.1 KiB
C
291 lines
6.1 KiB
C
/** @file
|
|
*
|
|
* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
|
|
* Copyright (c) 2016-2019, Linaro Limited. All rights reserved.
|
|
* Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
*
|
|
**/
|
|
|
|
#include <Uefi/UefiBaseType.h>
|
|
#include <Uefi/UefiSpec.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/TimeBaseLib.h>
|
|
|
|
/**
|
|
Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME.
|
|
|
|
@param EpochSeconds Epoch seconds.
|
|
@param Time The time converted to UEFI format.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EpochToEfiTime (
|
|
IN UINTN EpochSeconds,
|
|
OUT EFI_TIME *Time
|
|
)
|
|
{
|
|
UINTN a;
|
|
UINTN b;
|
|
UINTN c;
|
|
UINTN d;
|
|
UINTN g;
|
|
UINTN j;
|
|
UINTN m;
|
|
UINTN y;
|
|
UINTN da;
|
|
UINTN db;
|
|
UINTN dc;
|
|
UINTN dg;
|
|
UINTN hh;
|
|
UINTN mm;
|
|
UINTN ss;
|
|
UINTN J;
|
|
|
|
J = (EpochSeconds / 86400) + 2440588;
|
|
j = J + 32044;
|
|
g = j / 146097;
|
|
dg = j % 146097;
|
|
c = (((dg / 36524) + 1) * 3) / 4;
|
|
dc = dg - (c * 36524);
|
|
b = dc / 1461;
|
|
db = dc % 1461;
|
|
a = (((db / 365) + 1) * 3) / 4;
|
|
da = db - (a * 365);
|
|
y = (g * 400) + (c * 100) + (b * 4) + a;
|
|
m = (((da * 5) + 308) / 153) - 2;
|
|
d = da - (((m + 4) * 153) / 5) + 122;
|
|
|
|
Time->Year = (UINT16)(y - 4800 + ((m + 2) / 12));
|
|
Time->Month = ((m + 2) % 12) + 1;
|
|
Time->Day = (UINT8)(d + 1);
|
|
|
|
ss = EpochSeconds % 60;
|
|
a = (EpochSeconds - ss) / 60;
|
|
mm = a % 60;
|
|
b = (a - mm) / 60;
|
|
hh = b % 24;
|
|
|
|
Time->Hour = (UINT8)hh;
|
|
Time->Minute = (UINT8)mm;
|
|
Time->Second = (UINT8)ss;
|
|
Time->Nanosecond = 0;
|
|
}
|
|
|
|
/**
|
|
Calculate Epoch days.
|
|
|
|
@param Time The UEFI time to be calculated.
|
|
|
|
@return Number of days.
|
|
|
|
**/
|
|
UINTN
|
|
EFIAPI
|
|
EfiGetEpochDays (
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
UINTN a;
|
|
UINTN y;
|
|
UINTN m;
|
|
UINTN JulianDate; // Absolute Julian Date representation of the supplied Time
|
|
UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
|
|
|
|
a = (14 - Time->Month) / 12;
|
|
y = Time->Year + 4800 - a;
|
|
m = Time->Month + (12*a) - 3;
|
|
|
|
JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;
|
|
|
|
ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
|
|
EpochDays = JulianDate - EPOCH_JULIAN_DATE;
|
|
|
|
return EpochDays;
|
|
}
|
|
|
|
/**
|
|
Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC).
|
|
|
|
@param Time The UEFI time to be converted.
|
|
|
|
@return Number of seconds.
|
|
|
|
**/
|
|
UINTN
|
|
EFIAPI
|
|
EfiTimeToEpoch (
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
|
|
UINTN EpochSeconds;
|
|
|
|
EpochDays = EfiGetEpochDays (Time);
|
|
|
|
EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;
|
|
|
|
return EpochSeconds;
|
|
}
|
|
|
|
/**
|
|
Get the day of the week from the UEFI time.
|
|
|
|
@param Time The UEFI time to be calculated.
|
|
|
|
@return The day of the week: Sunday=0, Monday=1, ... Saturday=6
|
|
|
|
**/
|
|
UINTN
|
|
EfiTimeToWday (
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
|
|
|
|
EpochDays = EfiGetEpochDays (Time);
|
|
|
|
// 4=1/1/1970 was a Thursday
|
|
|
|
return (EpochDays + 4) % 7;
|
|
}
|
|
|
|
/**
|
|
Check if it is a leap year.
|
|
|
|
@param Time The UEFI time to be checked.
|
|
|
|
@retval TRUE It is a leap year.
|
|
@retval FALSE It is NOT a leap year.
|
|
|
|
**/
|
|
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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if the day in the UEFI time is valid.
|
|
|
|
@param Time The UEFI time to be checked.
|
|
|
|
@retval TRUE Valid.
|
|
@retval FALSE Invalid.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsDayValid (
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
STATIC CONST INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
|
|
|
if ((Time->Day < 1) ||
|
|
(Time->Day > DayOfMonth[Time->Month - 1]) ||
|
|
((Time->Month == 2) && (!IsLeapYear (Time) && (Time->Day > 28)))
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Check if the time zone is valid.
|
|
Valid values are between -1440 and 1440 or 2047 (EFI_UNSPECIFIED_TIMEZONE).
|
|
|
|
@param TimeZone The time zone to be checked.
|
|
|
|
@retval TRUE Valid.
|
|
@retval FALSE Invalid.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsValidTimeZone (
|
|
IN INT16 TimeZone
|
|
)
|
|
{
|
|
return TimeZone == EFI_UNSPECIFIED_TIMEZONE ||
|
|
(TimeZone >= -1440 && TimeZone <= 1440);
|
|
}
|
|
|
|
/**
|
|
Check if the daylight is valid.
|
|
Valid values are:
|
|
0 : Time is not affected.
|
|
1 : Time is affected, and has not been adjusted for daylight savings.
|
|
3 : Time is affected, and has been adjusted for daylight savings.
|
|
All other values are invalid.
|
|
|
|
@param Daylight The daylight to be checked.
|
|
|
|
@retval TRUE Valid.
|
|
@retval FALSE Invalid.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsValidDaylight (
|
|
IN INT8 Daylight
|
|
)
|
|
{
|
|
return Daylight == 0 ||
|
|
Daylight == EFI_TIME_ADJUST_DAYLIGHT ||
|
|
Daylight == (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT);
|
|
}
|
|
|
|
/**
|
|
Check if the UEFI time is valid.
|
|
|
|
@param Time The UEFI time to be checked.
|
|
|
|
@retval TRUE Valid.
|
|
@retval FALSE Invalid.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsTimeValid (
|
|
IN EFI_TIME *Time
|
|
)
|
|
{
|
|
// Check the input parameters are within the range specified by UEFI
|
|
if ((Time->Year < 2000) ||
|
|
(Time->Year > 2099) ||
|
|
(Time->Month < 1) ||
|
|
(Time->Month > 12) ||
|
|
(!IsDayValid (Time)) ||
|
|
(Time->Hour > 23) ||
|
|
(Time->Minute > 59) ||
|
|
(Time->Second > 59) ||
|
|
(Time->Nanosecond > 999999999) ||
|
|
(!IsValidTimeZone (Time->TimeZone)) ||
|
|
(!IsValidDaylight (Time->Daylight)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|