/** @file * * Copyright (c) 2016, Hisilicon Limited. All rights reserved. * Copyright (c) 2016, Linaro Limited. All rights reserved. * * This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License * which accompanies this distribution. The full text of the license may be found at * http://opensource.org/licenses/bsd-license.php * * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * **/ #include #include #include #include /** Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME **/ 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 = y - 4800 + ((m + 2) / 12); Time->Month = ((m + 2) % 12) + 1; Time->Day = d + 1; ss = EpochSeconds % 60; a = (EpochSeconds - ss) / 60; mm = a % 60; b = (a - mm) / 60; hh = b % 24; Time->Hour = hh; Time->Minute = mm; Time->Second = ss; Time->Nanosecond = 0; } /** Calculate Epoch 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) **/ 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; } /** returns Day of the week [0-6] 0=Sunday **/ 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; } 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; } } 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; } 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) || (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) || (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) ) { return FALSE; } return TRUE; }