]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c
CryptoPkg/BaseCryptLib:time overflow
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / SysCall / TimerWrapper.c
1 /** @file
2 C Run-Time Libraries (CRT) Time Management Routines Wrapper Implementation
3 for OpenSSL-based Cryptographic Library (used in DXE & RUNTIME).
4
5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <Uefi.h>
11 #include <CrtLibSupport.h>
12 #include <Library/UefiRuntimeServicesTableLib.h>
13
14 //
15 // -- Time Management Routines --
16 //
17
18 #define SECSPERMIN (60)
19 #define SECSPERHOUR (60 * 60)
20 #define SECSPERDAY (24 * SECSPERHOUR)
21
22 //
23 // The arrays give the cumulative number of days up to the first of the
24 // month number used as the index (1 -> 12) for regular and leap years.
25 // The value at index 13 is for the whole year.
26 //
27 UINTN CumulativeDays[2][14] = {
28 {
29 0,
30 0,
31 31,
32 31 + 28,
33 31 + 28 + 31,
34 31 + 28 + 31 + 30,
35 31 + 28 + 31 + 30 + 31,
36 31 + 28 + 31 + 30 + 31 + 30,
37 31 + 28 + 31 + 30 + 31 + 30 + 31,
38 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
39 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
40 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
41 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
42 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
43 },
44 {
45 0,
46 0,
47 31,
48 31 + 29,
49 31 + 29 + 31,
50 31 + 29 + 31 + 30,
51 31 + 29 + 31 + 30 + 31,
52 31 + 29 + 31 + 30 + 31 + 30,
53 31 + 29 + 31 + 30 + 31 + 30 + 31,
54 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
55 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
56 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
57 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
58 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
59 }
60 };
61
62 /* Check the year is leap or not. */
63 // BOOLEAN IsLeap(
64 // INTN timer
65 // )
66 BOOLEAN
67 IsLeap (
68 time_t timer
69 )
70 {
71 INT64 Remainder1;
72 INT64 Remainder2;
73 INT64 Remainder3;
74
75 DivS64x64Remainder (timer, 4, &Remainder1);
76 DivS64x64Remainder (timer, 100, &Remainder2);
77 DivS64x64Remainder (timer, 400, &Remainder3);
78
79 return (Remainder1 == 0 && (Remainder2 != 0 || Remainder3 == 0));
80 }
81
82 /* Get the system time as seconds elapsed since midnight, January 1, 1970. */
83 // INTN time(
84 // INTN *timer
85 // )
86 time_t
87 time (
88 time_t *timer
89 )
90 {
91 EFI_STATUS Status;
92 EFI_TIME Time;
93 time_t CalTime;
94 UINTN Year;
95
96 //
97 // Get the current time and date information
98 //
99 Status = gRT->GetTime (&Time, NULL);
100 if (EFI_ERROR (Status) || (Time.Year < 1970)) {
101 return 0;
102 }
103
104 //
105 // Years Handling
106 // UTime should now be set to 00:00:00 on Jan 1 of the current year.
107 //
108 for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
109 CalTime = CalTime + (time_t)(CumulativeDays[IsLeap (Year)][13] * SECSPERDAY);
110 }
111
112 //
113 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
114 //
115 CalTime = CalTime +
116 (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
117 (time_t)(CumulativeDays[IsLeap (Time.Year)][Time.Month] * SECSPERDAY) +
118 (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
119 (time_t)(Time.Hour * SECSPERHOUR) +
120 (time_t)(Time.Minute * 60) +
121 (time_t)Time.Second;
122
123 if (timer != NULL) {
124 *timer = CalTime;
125 }
126
127 return CalTime;
128 }
129
130 //
131 // Convert a time value from type time_t to struct tm.
132 //
133 struct tm *
134 gmtime (
135 const time_t *timer
136 )
137 {
138 struct tm *GmTime;
139 UINT64 DayNo;
140 UINT64 DayRemainder;
141 time_t Year;
142 time_t YearNo;
143 UINT32 TotalDays;
144 UINT32 MonthNo;
145 INT64 Remainder;
146
147 if (timer == NULL) {
148 return NULL;
149 }
150
151 GmTime = malloc (sizeof (struct tm));
152 if (GmTime == NULL) {
153 return NULL;
154 }
155
156 ZeroMem ((VOID *)GmTime, (UINTN)sizeof (struct tm));
157
158 DayNo = (UINT64)DivS64x64Remainder (*timer, SECSPERDAY, &Remainder);
159 DayRemainder = (UINT64)Remainder;
160
161 DivS64x64Remainder (DayRemainder, SECSPERMIN, &Remainder);
162 GmTime->tm_sec = (int)Remainder;
163 DivS64x64Remainder (DayRemainder, SECSPERHOUR, &Remainder);
164 GmTime->tm_min = (int)DivS64x64Remainder (Remainder, SECSPERMIN, NULL);
165 GmTime->tm_hour = (int)DivS64x64Remainder (DayRemainder, SECSPERHOUR, NULL);
166 DivS64x64Remainder ((DayNo + 4), 7, &Remainder);
167 GmTime->tm_wday = (int)Remainder;
168
169 for (Year = 1970, YearNo = 0; DayNo > 0; Year++) {
170 TotalDays = (UINT32)(IsLeap (Year) ? 366 : 365);
171 if (DayNo >= TotalDays) {
172 DayNo = (UINT64)(DayNo - TotalDays);
173 YearNo++;
174 } else {
175 break;
176 }
177 }
178
179 GmTime->tm_year = (int)(YearNo + (1970 - 1900));
180 GmTime->tm_yday = (int)DayNo;
181
182 for (MonthNo = 12; MonthNo > 1; MonthNo--) {
183 if (DayNo >= CumulativeDays[IsLeap (Year)][MonthNo]) {
184 DayNo = (UINT64)(DayNo - (UINT32)(CumulativeDays[IsLeap (Year)][MonthNo]));
185 break;
186 }
187 }
188
189 GmTime->tm_mon = (int)MonthNo - 1;
190 GmTime->tm_mday = (int)DayNo + 1;
191
192 GmTime->tm_isdst = 0;
193 GmTime->tm_gmtoff = 0;
194 GmTime->tm_zone = NULL;
195
196 return GmTime;
197 }