0c0d9403017c81fd89c33e87e6852f6f7c20235b
[mirror_edk2.git] / EmbeddedPkg / Library / TimeBaseLib / TimeBaseLib.c
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/TimeBaseLib.h>
20
21 /**
22 Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
23 **/
24 VOID
25 EFIAPI
26 EpochToEfiTime (
27 IN UINTN EpochSeconds,
28 OUT EFI_TIME *Time
29 )
30 {
31 UINTN a;
32 UINTN b;
33 UINTN c;
34 UINTN d;
35 UINTN g;
36 UINTN j;
37 UINTN m;
38 UINTN y;
39 UINTN da;
40 UINTN db;
41 UINTN dc;
42 UINTN dg;
43 UINTN hh;
44 UINTN mm;
45 UINTN ss;
46 UINTN J;
47
48 J = (EpochSeconds / 86400) + 2440588;
49 j = J + 32044;
50 g = j / 146097;
51 dg = j % 146097;
52 c = (((dg / 36524) + 1) * 3) / 4;
53 dc = dg - (c * 36524);
54 b = dc / 1461;
55 db = dc % 1461;
56 a = (((db / 365) + 1) * 3) / 4;
57 da = db - (a * 365);
58 y = (g * 400) + (c * 100) + (b * 4) + a;
59 m = (((da * 5) + 308) / 153) - 2;
60 d = da - (((m + 4) * 153) / 5) + 122;
61
62 Time->Year = y - 4800 + ((m + 2) / 12);
63 Time->Month = ((m + 2) % 12) + 1;
64 Time->Day = d + 1;
65
66 ss = EpochSeconds % 60;
67 a = (EpochSeconds - ss) / 60;
68 mm = a % 60;
69 b = (a - mm) / 60;
70 hh = b % 24;
71
72 Time->Hour = hh;
73 Time->Minute = mm;
74 Time->Second = ss;
75 Time->Nanosecond = 0;
76
77 }
78
79 /**
80 Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC)
81 **/
82 UINTN
83 EFIAPI
84 EfiTimeToEpoch (
85 IN EFI_TIME *Time
86 )
87 {
88 UINTN a;
89 UINTN y;
90 UINTN m;
91 UINTN JulianDate; // Absolute Julian Date representation of the supplied Time
92 UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
93 UINTN EpochSeconds;
94
95 a = (14 - Time->Month) / 12 ;
96 y = Time->Year + 4800 - a;
97 m = Time->Month + (12*a) - 3;
98
99 JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;
100
101 ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
102 EpochDays = JulianDate - EPOCH_JULIAN_DATE;
103
104 EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;
105
106 return EpochSeconds;
107 }
108
109 BOOLEAN
110 EFIAPI
111 IsLeapYear (
112 IN EFI_TIME *Time
113 )
114 {
115 if (Time->Year % 4 == 0) {
116 if (Time->Year % 100 == 0) {
117 if (Time->Year % 400 == 0) {
118 return TRUE;
119 } else {
120 return FALSE;
121 }
122 } else {
123 return TRUE;
124 }
125 } else {
126 return FALSE;
127 }
128 }
129
130 BOOLEAN
131 EFIAPI
132 IsDayValid (
133 IN EFI_TIME *Time
134 )
135 {
136 STATIC CONST INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
137
138 if (Time->Day < 1 ||
139 Time->Day > DayOfMonth[Time->Month - 1] ||
140 (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
141 ) {
142 return FALSE;
143 }
144
145 return TRUE;
146 }
147
148 BOOLEAN
149 EFIAPI
150 IsTimeValid(
151 IN EFI_TIME *Time
152 )
153 {
154 // Check the input parameters are within the range specified by UEFI
155 if ((Time->Year < 2000) ||
156 (Time->Year > 2099) ||
157 (Time->Month < 1 ) ||
158 (Time->Month > 12 ) ||
159 (!IsDayValid (Time) ) ||
160 (Time->Hour > 23 ) ||
161 (Time->Minute > 59 ) ||
162 (Time->Second > 59 ) ||
163 (Time->Nanosecond > 999999999) ||
164 (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||
165 (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
166 ) {
167 return FALSE;
168 }
169
170 return TRUE;
171 }