1 | /** @file
|
---|
2 | *
|
---|
3 | * Copyright (c) 2016, Hisilicon Limited. All rights reserved.
|
---|
4 | * Copyright (c) 2016-2019, Linaro Limited. All rights reserved.
|
---|
5 | *
|
---|
6 | * SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 | *
|
---|
8 | **/
|
---|
9 |
|
---|
10 | #include <Uefi/UefiBaseType.h>
|
---|
11 | #include <Uefi/UefiSpec.h>
|
---|
12 | #include <Library/DebugLib.h>
|
---|
13 | #include <Library/TimeBaseLib.h>
|
---|
14 |
|
---|
15 | /**
|
---|
16 | Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
|
---|
17 | **/
|
---|
18 | VOID
|
---|
19 | EFIAPI
|
---|
20 | EpochToEfiTime (
|
---|
21 | IN UINTN EpochSeconds,
|
---|
22 | OUT EFI_TIME *Time
|
---|
23 | )
|
---|
24 | {
|
---|
25 | UINTN a;
|
---|
26 | UINTN b;
|
---|
27 | UINTN c;
|
---|
28 | UINTN d;
|
---|
29 | UINTN g;
|
---|
30 | UINTN j;
|
---|
31 | UINTN m;
|
---|
32 | UINTN y;
|
---|
33 | UINTN da;
|
---|
34 | UINTN db;
|
---|
35 | UINTN dc;
|
---|
36 | UINTN dg;
|
---|
37 | UINTN hh;
|
---|
38 | UINTN mm;
|
---|
39 | UINTN ss;
|
---|
40 | UINTN J;
|
---|
41 |
|
---|
42 | J = (EpochSeconds / 86400) + 2440588;
|
---|
43 | j = J + 32044;
|
---|
44 | g = j / 146097;
|
---|
45 | dg = j % 146097;
|
---|
46 | c = (((dg / 36524) + 1) * 3) / 4;
|
---|
47 | dc = dg - (c * 36524);
|
---|
48 | b = dc / 1461;
|
---|
49 | db = dc % 1461;
|
---|
50 | a = (((db / 365) + 1) * 3) / 4;
|
---|
51 | da = db - (a * 365);
|
---|
52 | y = (g * 400) + (c * 100) + (b * 4) + a;
|
---|
53 | m = (((da * 5) + 308) / 153) - 2;
|
---|
54 | d = da - (((m + 4) * 153) / 5) + 122;
|
---|
55 |
|
---|
56 | Time->Year = (UINT16)(y - 4800 + ((m + 2) / 12));
|
---|
57 | Time->Month = ((m + 2) % 12) + 1;
|
---|
58 | Time->Day = (UINT8)(d + 1);
|
---|
59 |
|
---|
60 | ss = EpochSeconds % 60;
|
---|
61 | a = (EpochSeconds - ss) / 60;
|
---|
62 | mm = a % 60;
|
---|
63 | b = (a - mm) / 60;
|
---|
64 | hh = b % 24;
|
---|
65 |
|
---|
66 | Time->Hour = (UINT8)hh;
|
---|
67 | Time->Minute = (UINT8)mm;
|
---|
68 | Time->Second = (UINT8)ss;
|
---|
69 | Time->Nanosecond = 0;
|
---|
70 |
|
---|
71 | }
|
---|
72 |
|
---|
73 | /**
|
---|
74 | Calculate Epoch days
|
---|
75 | **/
|
---|
76 | UINTN
|
---|
77 | EFIAPI
|
---|
78 | EfiGetEpochDays (
|
---|
79 | IN EFI_TIME *Time
|
---|
80 | )
|
---|
81 | {
|
---|
82 | UINTN a;
|
---|
83 | UINTN y;
|
---|
84 | UINTN m;
|
---|
85 | UINTN JulianDate; // Absolute Julian Date representation of the supplied Time
|
---|
86 | UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
|
---|
87 |
|
---|
88 | a = (14 - Time->Month) / 12 ;
|
---|
89 | y = Time->Year + 4800 - a;
|
---|
90 | m = Time->Month + (12*a) - 3;
|
---|
91 |
|
---|
92 | JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;
|
---|
93 |
|
---|
94 | ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
|
---|
95 | EpochDays = JulianDate - EPOCH_JULIAN_DATE;
|
---|
96 |
|
---|
97 | return EpochDays;
|
---|
98 | }
|
---|
99 | /**
|
---|
100 | Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC)
|
---|
101 | **/
|
---|
102 | UINT32
|
---|
103 | EFIAPI
|
---|
104 | EfiTimeToEpoch (
|
---|
105 | IN EFI_TIME *Time
|
---|
106 | )
|
---|
107 | {
|
---|
108 | UINT32 EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
|
---|
109 | UINT32 EpochSeconds;
|
---|
110 |
|
---|
111 | EpochDays = EfiGetEpochDays (Time);
|
---|
112 |
|
---|
113 | EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;
|
---|
114 |
|
---|
115 | return EpochSeconds;
|
---|
116 | }
|
---|
117 |
|
---|
118 | /**
|
---|
119 | returns Day of the week [0-6] 0=Sunday
|
---|
120 | **/
|
---|
121 | UINTN
|
---|
122 | EfiTimeToWday (
|
---|
123 | IN EFI_TIME *Time
|
---|
124 | )
|
---|
125 | {
|
---|
126 | UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
|
---|
127 |
|
---|
128 | EpochDays = EfiGetEpochDays (Time);
|
---|
129 |
|
---|
130 | // 4=1/1/1970 was a Thursday
|
---|
131 |
|
---|
132 | return (EpochDays + 4) % 7;
|
---|
133 | }
|
---|
134 |
|
---|
135 | BOOLEAN
|
---|
136 | EFIAPI
|
---|
137 | IsLeapYear (
|
---|
138 | IN EFI_TIME *Time
|
---|
139 | )
|
---|
140 | {
|
---|
141 | if (Time->Year % 4 == 0) {
|
---|
142 | if (Time->Year % 100 == 0) {
|
---|
143 | if (Time->Year % 400 == 0) {
|
---|
144 | return TRUE;
|
---|
145 | } else {
|
---|
146 | return FALSE;
|
---|
147 | }
|
---|
148 | } else {
|
---|
149 | return TRUE;
|
---|
150 | }
|
---|
151 | } else {
|
---|
152 | return FALSE;
|
---|
153 | }
|
---|
154 | }
|
---|
155 |
|
---|
156 | BOOLEAN
|
---|
157 | EFIAPI
|
---|
158 | IsDayValid (
|
---|
159 | IN EFI_TIME *Time
|
---|
160 | )
|
---|
161 | {
|
---|
162 | STATIC CONST INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
---|
163 |
|
---|
164 | if (Time->Day < 1 ||
|
---|
165 | Time->Day > DayOfMonth[Time->Month - 1] ||
|
---|
166 | (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
|
---|
167 | ) {
|
---|
168 | return FALSE;
|
---|
169 | }
|
---|
170 |
|
---|
171 | return TRUE;
|
---|
172 | }
|
---|
173 |
|
---|
174 | BOOLEAN
|
---|
175 | EFIAPI
|
---|
176 | IsTimeValid(
|
---|
177 | IN EFI_TIME *Time
|
---|
178 | )
|
---|
179 | {
|
---|
180 | // Check the input parameters are within the range specified by UEFI
|
---|
181 | if ((Time->Year < 2000) ||
|
---|
182 | (Time->Year > 2099) ||
|
---|
183 | (Time->Month < 1 ) ||
|
---|
184 | (Time->Month > 12 ) ||
|
---|
185 | (!IsDayValid (Time) ) ||
|
---|
186 | (Time->Hour > 23 ) ||
|
---|
187 | (Time->Minute > 59 ) ||
|
---|
188 | (Time->Second > 59 ) ||
|
---|
189 | (Time->Nanosecond > 999999999) ||
|
---|
190 | (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||
|
---|
191 | (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
|
---|
192 | ) {
|
---|
193 | return FALSE;
|
---|
194 | }
|
---|
195 |
|
---|
196 | return TRUE;
|
---|
197 | }
|
---|