1/** @file 2* 3* Copyright (c) 2016, Hisilicon Limited. All rights reserved. 4* Copyright (c) 2016, Linaro Limited. All rights reserved. 5* 6* This program and the accompanying materials 7* are licensed and made available under the terms and conditions of the BSD License 8* which accompanies this distribution. The full text of the license may be found at 9* http://opensource.org/licenses/bsd-license.php 10* 11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13* 14**/ 15 16#include <Uefi/UefiBaseType.h> 17#include <Uefi/UefiSpec.h> 18#include <Library/DebugLib.h> 19#include <Library/EfiTimeBaseLib.h> 20 21// Define EPOCH (1970-JANUARY-01) in the Julian Date representation 22#define EPOCH_JULIAN_DATE 2440588 23 24BOOLEAN 25EFIAPI 26IsLeapYear ( 27 IN EFI_TIME *Time 28 ) 29{ 30 if (Time->Year % 4 == 0) { 31 if (Time->Year % 100 == 0) { 32 if (Time->Year % 400 == 0) { 33 return TRUE; 34 } else { 35 return FALSE; 36 } 37 } else { 38 return TRUE; 39 } 40 } else { 41 return FALSE; 42 } 43} 44 45BOOLEAN 46EFIAPI 47IsDayValid ( 48 IN EFI_TIME *Time 49 ) 50{ 51 INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 52 53 if (Time->Day < 1 || 54 Time->Day > DayOfMonth[Time->Month - 1] || 55 (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28)) 56 ) { 57 return FALSE; 58 } 59 60 return TRUE; 61} 62 63BOOLEAN 64EFIAPI 65IsTimeValid( 66 IN EFI_TIME *Time 67 ) 68{ 69 // Check the input parameters are within the range specified by UEFI 70 if ((Time->Year < 2000) || 71 (Time->Year > 2099) || 72 (Time->Month < 1 ) || 73 (Time->Month > 12 ) || 74 (!IsDayValid (Time) ) || 75 (Time->Hour > 23 ) || 76 (Time->Minute > 59 ) || 77 (Time->Second > 59 ) || 78 (Time->Nanosecond > 999999999) || 79 (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) || 80 (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) 81 ) { 82 return FALSE; 83 } 84 85 return TRUE; 86} 87 88/** 89 Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME 90 **/ 91VOID 92EpochToEfiTime ( 93 IN UINTN EpochSeconds, 94 OUT EFI_TIME *Time 95 ) 96{ 97 UINTN a; 98 UINTN b; 99 UINTN c; 100 UINTN d; 101 UINTN g; 102 UINTN j; 103 UINTN m; 104 UINTN y; 105 UINTN da; 106 UINTN db; 107 UINTN dc; 108 UINTN dg; 109 UINTN hh; 110 UINTN mm; 111 UINTN ss; 112 UINTN J; 113 114 J = (EpochSeconds / 86400) + 2440588; 115 j = J + 32044; 116 g = j / 146097; 117 dg = j % 146097; 118 c = (((dg / 36524) + 1) * 3) / 4; 119 dc = dg - (c * 36524); 120 b = dc / 1461; 121 db = dc % 1461; 122 a = (((db / 365) + 1) * 3) / 4; 123 da = db - (a * 365); 124 y = (g * 400) + (c * 100) + (b * 4) + a; 125 m = (((da * 5) + 308) / 153) - 2; 126 d = da - (((m + 4) * 153) / 5) + 122; 127 128 Time->Year = y - 4800 + ((m + 2) / 12); 129 Time->Month = ((m + 2) % 12) + 1; 130 Time->Day = d + 1; 131 132 ss = EpochSeconds % 60; 133 a = (EpochSeconds - ss) / 60; 134 mm = a % 60; 135 b = (a - mm) / 60; 136 hh = b % 24; 137 138 Time->Hour = hh; 139 Time->Minute = mm; 140 Time->Second = ss; 141 Time->Nanosecond = 0; 142 143} 144 145/** 146 Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) 147 **/ 148UINTN 149EfiTimeToEpoch ( 150 IN EFI_TIME *Time 151 ) 152{ 153 UINTN a; 154 UINTN y; 155 UINTN m; 156 UINTN JulianDate; // Absolute Julian Date representation of the supplied Time 157 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY 158 UINTN EpochSeconds; 159 160 a = (14 - Time->Month) / 12 ; 161 y = Time->Year + 4800 - a; 162 m = Time->Month + (12*a) - 3; 163 164 JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045; 165 166 ASSERT (JulianDate >= EPOCH_JULIAN_DATE); 167 EpochDays = JulianDate - EPOCH_JULIAN_DATE; 168 169 EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second; 170 171 return EpochSeconds; 172} 173