VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c

Last change on this file was 99404, checked in by vboxsync, 2 years ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1/** @file
2*
3* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
4* Copyright (c) 2016-2019, Linaro Limited. All rights reserved.
5* Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
6*
7* SPDX-License-Identifier: BSD-2-Clause-Patent
8*
9**/
10
11#include <Uefi/UefiBaseType.h>
12#include <Uefi/UefiSpec.h>
13#include <Library/DebugLib.h>
14#include <Library/TimeBaseLib.h>
15
16/**
17 Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME.
18
19 @param EpochSeconds Epoch seconds.
20 @param Time The time converted to UEFI format.
21
22**/
23VOID
24EFIAPI
25EpochToEfiTime (
26 IN UINTN EpochSeconds,
27 OUT EFI_TIME *Time
28 )
29{
30 UINTN a;
31 UINTN b;
32 UINTN c;
33 UINTN d;
34 UINTN g;
35 UINTN j;
36 UINTN m;
37 UINTN y;
38 UINTN da;
39 UINTN db;
40 UINTN dc;
41 UINTN dg;
42 UINTN hh;
43 UINTN mm;
44 UINTN ss;
45 UINTN J;
46
47 J = (EpochSeconds / 86400) + 2440588;
48 j = J + 32044;
49 g = j / 146097;
50 dg = j % 146097;
51 c = (((dg / 36524) + 1) * 3) / 4;
52 dc = dg - (c * 36524);
53 b = dc / 1461;
54 db = dc % 1461;
55 a = (((db / 365) + 1) * 3) / 4;
56 da = db - (a * 365);
57 y = (g * 400) + (c * 100) + (b * 4) + a;
58 m = (((da * 5) + 308) / 153) - 2;
59 d = da - (((m + 4) * 153) / 5) + 122;
60
61 Time->Year = (UINT16)(y - 4800 + ((m + 2) / 12));
62 Time->Month = ((m + 2) % 12) + 1;
63 Time->Day = (UINT8)(d + 1);
64
65 ss = EpochSeconds % 60;
66 a = (EpochSeconds - ss) / 60;
67 mm = a % 60;
68 b = (a - mm) / 60;
69 hh = b % 24;
70
71 Time->Hour = (UINT8)hh;
72 Time->Minute = (UINT8)mm;
73 Time->Second = (UINT8)ss;
74 Time->Nanosecond = 0;
75}
76
77/**
78 Calculate Epoch days.
79
80 @param Time The UEFI time to be calculated.
81
82 @return Number of days.
83
84**/
85UINTN
86EFIAPI
87EfiGetEpochDays (
88 IN EFI_TIME *Time
89 )
90{
91 UINTN a;
92 UINTN y;
93 UINTN m;
94 UINTN JulianDate; // Absolute Julian Date representation of the supplied Time
95 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
96
97 a = (14 - Time->Month) / 12;
98 y = Time->Year + 4800 - a;
99 m = Time->Month + (12*a) - 3;
100
101 JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;
102
103 ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
104 EpochDays = JulianDate - EPOCH_JULIAN_DATE;
105
106 return EpochDays;
107}
108
109/**
110 Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC).
111
112 @param Time The UEFI time to be converted.
113
114 @return Number of seconds.
115
116**/
117UINTN
118EFIAPI
119EfiTimeToEpoch (
120 IN EFI_TIME *Time
121 )
122{
123 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
124 UINTN EpochSeconds;
125
126 EpochDays = EfiGetEpochDays (Time);
127
128 EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;
129
130 return EpochSeconds;
131}
132
133/**
134 Get the day of the week from the UEFI time.
135
136 @param Time The UEFI time to be calculated.
137
138 @return The day of the week: Sunday=0, Monday=1, ... Saturday=6
139
140**/
141UINTN
142EfiTimeToWday (
143 IN EFI_TIME *Time
144 )
145{
146 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
147
148 EpochDays = EfiGetEpochDays (Time);
149
150 // 4=1/1/1970 was a Thursday
151
152 return (EpochDays + 4) % 7;
153}
154
155/**
156 Check if it is a leap year.
157
158 @param Time The UEFI time to be checked.
159
160 @retval TRUE It is a leap year.
161 @retval FALSE It is NOT a leap year.
162
163**/
164BOOLEAN
165EFIAPI
166IsLeapYear (
167 IN EFI_TIME *Time
168 )
169{
170 if (Time->Year % 4 == 0) {
171 if (Time->Year % 100 == 0) {
172 if (Time->Year % 400 == 0) {
173 return TRUE;
174 } else {
175 return FALSE;
176 }
177 } else {
178 return TRUE;
179 }
180 } else {
181 return FALSE;
182 }
183}
184
185/**
186 Check if the day in the UEFI time is valid.
187
188 @param Time The UEFI time to be checked.
189
190 @retval TRUE Valid.
191 @retval FALSE Invalid.
192
193**/
194BOOLEAN
195EFIAPI
196IsDayValid (
197 IN EFI_TIME *Time
198 )
199{
200 STATIC CONST INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
201
202 if ((Time->Day < 1) ||
203 (Time->Day > DayOfMonth[Time->Month - 1]) ||
204 ((Time->Month == 2) && (!IsLeapYear (Time) && (Time->Day > 28)))
205 )
206 {
207 return FALSE;
208 }
209
210 return TRUE;
211}
212
213/**
214 Check if the time zone is valid.
215 Valid values are between -1440 and 1440 or 2047 (EFI_UNSPECIFIED_TIMEZONE).
216
217 @param TimeZone The time zone to be checked.
218
219 @retval TRUE Valid.
220 @retval FALSE Invalid.
221
222**/
223BOOLEAN
224EFIAPI
225IsValidTimeZone (
226 IN INT16 TimeZone
227 )
228{
229 return TimeZone == EFI_UNSPECIFIED_TIMEZONE ||
230 (TimeZone >= -1440 && TimeZone <= 1440);
231}
232
233/**
234 Check if the daylight is valid.
235 Valid values are:
236 0 : Time is not affected.
237 1 : Time is affected, and has not been adjusted for daylight savings.
238 3 : Time is affected, and has been adjusted for daylight savings.
239 All other values are invalid.
240
241 @param Daylight The daylight to be checked.
242
243 @retval TRUE Valid.
244 @retval FALSE Invalid.
245
246**/
247BOOLEAN
248EFIAPI
249IsValidDaylight (
250 IN INT8 Daylight
251 )
252{
253 return Daylight == 0 ||
254 Daylight == EFI_TIME_ADJUST_DAYLIGHT ||
255 Daylight == (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT);
256}
257
258/**
259 Check if the UEFI time is valid.
260
261 @param Time The UEFI time to be checked.
262
263 @retval TRUE Valid.
264 @retval FALSE Invalid.
265
266**/
267BOOLEAN
268EFIAPI
269IsTimeValid (
270 IN EFI_TIME *Time
271 )
272{
273 // Check the input parameters are within the range specified by UEFI
274 if ((Time->Year < 2000) ||
275 (Time->Year > 2099) ||
276 (Time->Month < 1) ||
277 (Time->Month > 12) ||
278 (!IsDayValid (Time)) ||
279 (Time->Hour > 23) ||
280 (Time->Minute > 59) ||
281 (Time->Second > 59) ||
282 (Time->Nanosecond > 999999999) ||
283 (!IsValidTimeZone (Time->TimeZone)) ||
284 (!IsValidDaylight (Time->Daylight)))
285 {
286 return FALSE;
287 }
288
289 return TRUE;
290}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette