Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/efi/libefi/time.c
34859 views
1
/*-
2
* Copyright (c) 1999, 2000
3
* Intel Corporation.
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* 3. All advertising materials mentioning features or use of this software
18
* must display the following acknowledgement:
19
*
20
* This product includes software developed by Intel Corporation and
21
* its contributors.
22
*
23
* 4. Neither the name of Intel Corporation or its contributors may be
24
* used to endorse or promote products derived from this software
25
* without specific prior written permission.
26
*
27
* THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
28
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
* ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
31
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37
* THE POSSIBILITY OF SUCH DAMAGE.
38
*
39
*/
40
41
#include <efi.h>
42
#include <efilib.h>
43
44
#include <time.h>
45
#include <sys/time.h>
46
47
/*
48
* Accurate only for the past couple of centuries;
49
* that will probably do.
50
*
51
* (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
52
*/
53
54
#define isleap(y) (((y) % 4) == 0 && \
55
(((y) % 100) != 0 || ((y) % 400) == 0))
56
#define SECSPERHOUR (60*60)
57
#define SECSPERDAY (24 * SECSPERHOUR)
58
59
/*
60
* These arrays give the cumulative number of days up to the first of the
61
* month number used as the index (1 -> 12) for regular and leap years.
62
* The value at index 13 is for the whole year.
63
*/
64
static const time_t CumulativeDays[2][14] = {
65
{0,
66
0,
67
31,
68
31 + 28,
69
31 + 28 + 31,
70
31 + 28 + 31 + 30,
71
31 + 28 + 31 + 30 + 31,
72
31 + 28 + 31 + 30 + 31 + 30,
73
31 + 28 + 31 + 30 + 31 + 30 + 31,
74
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
75
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
76
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
77
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
78
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
79
{0,
80
0,
81
31,
82
31 + 29,
83
31 + 29 + 31,
84
31 + 29 + 31 + 30,
85
31 + 29 + 31 + 30 + 31,
86
31 + 29 + 31 + 30 + 31 + 30,
87
31 + 29 + 31 + 30 + 31 + 30 + 31,
88
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
89
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
90
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
91
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
92
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
93
94
void
95
efi_time_init(void)
96
{
97
}
98
99
void
100
efi_time_fini(void)
101
{
102
}
103
104
void
105
to_efi_time(EFI_TIME *efi_time, time_t time)
106
{
107
int lyear, month;
108
time_t seconds;
109
110
if (time >= 0) {
111
efi_time->Year = 1970;
112
lyear = isleap(efi_time->Year);
113
month = 13;
114
seconds = CumulativeDays[lyear][month] * SECSPERDAY;
115
while (time > seconds) {
116
time -= seconds;
117
efi_time->Year++;
118
lyear = isleap(efi_time->Year);
119
seconds = CumulativeDays[lyear][month] * SECSPERDAY;
120
}
121
122
efi_time->Month = 0;
123
while (time >
124
CumulativeDays[lyear][month] * SECSPERDAY) {
125
efi_time->Month++;
126
}
127
128
month = efi_time->Month - 1;
129
time -= CumulativeDays[lyear][month] * SECSPERDAY;
130
131
for (efi_time->Day = 0; time > SECSPERDAY; efi_time->Day++)
132
time -= SECSPERDAY;
133
134
for (efi_time->Hour = 0; time > SECSPERHOUR; efi_time->Hour++)
135
time -= SECSPERHOUR;
136
137
for (efi_time->Minute = 0; time > 60; efi_time->Minute++)
138
time -= 60;
139
140
efi_time->Second = time;
141
efi_time->Nanosecond = 0;
142
efi_time->TimeZone = 0;
143
efi_time->Daylight = 0;
144
} else {
145
memset(efi_time, 0, sizeof(EFI_TIME));
146
}
147
}
148
149
time_t
150
from_efi_time(EFI_TIME *ETime)
151
{
152
time_t UTime;
153
int Year;
154
155
/*
156
* Do a santity check
157
*/
158
if (ETime->Year < 1998 || ETime->Year > 2099 ||
159
ETime->Month == 0 || ETime->Month > 12 ||
160
ETime->Day == 0 || ETime->Month > 31 ||
161
ETime->Hour > 23 || ETime->Minute > 59 ||
162
ETime->Second > 59 || ETime->TimeZone < -1440 ||
163
(ETime->TimeZone > 1440 && ETime->TimeZone != 2047)) {
164
return (0);
165
}
166
167
/*
168
* Years
169
*/
170
UTime = 0;
171
for (Year = 1970; Year != ETime->Year; ++Year) {
172
UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
173
}
174
175
/*
176
* UTime should now be set to 00:00:00 on Jan 1 of the file's year.
177
*
178
* Months
179
*/
180
UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] *
181
SECSPERDAY);
182
183
/*
184
* UTime should now be set to 00:00:00 on the first of the file's
185
* month and year.
186
*
187
* Days -- Don't count the file's day
188
*/
189
UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
190
191
/*
192
* Hours
193
*/
194
UTime += (ETime->Hour * SECSPERHOUR);
195
196
/*
197
* Minutes
198
*/
199
UTime += (ETime->Minute * 60);
200
201
/*
202
* Seconds
203
*/
204
UTime += ETime->Second;
205
206
/*
207
* EFI time is repored in local time. Adjust for any time zone
208
* offset to get true UT
209
*/
210
if (ETime->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
211
/*
212
* TimeZone is kept in minues...
213
*/
214
UTime += (ETime->TimeZone * 60);
215
}
216
217
return (UTime);
218
}
219
220
static int
221
EFI_GetTimeOfDay(OUT struct timeval *tp, OUT struct timezone *tzp)
222
{
223
EFI_TIME EfiTime;
224
EFI_TIME_CAPABILITIES Capabilities;
225
EFI_STATUS Status;
226
227
/*
228
* Get time from EFI
229
*/
230
231
Status = RS->GetTime(&EfiTime, &Capabilities);
232
if (EFI_ERROR(Status))
233
return (-1);
234
235
/*
236
* Convert to UNIX time (ie seconds since the epoch
237
*/
238
239
tp->tv_sec = from_efi_time(&EfiTime);
240
tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */
241
242
/*
243
* Do something with the timezone if needed
244
*/
245
246
if (tzp != NULL) {
247
if (EfiTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE)
248
tzp->tz_minuteswest = 0;
249
else
250
tzp->tz_minuteswest = EfiTime.TimeZone;
251
/*
252
* This isn't quit right since it doesn't deal with
253
* EFI_TIME_IN_DAYLIGHT
254
*/
255
tzp->tz_dsttime =
256
EfiTime.Daylight & EFI_TIME_ADJUST_DAYLIGHT ? 1 : 0;
257
}
258
259
return (0);
260
}
261
262
time_t
263
time(time_t *tloc)
264
{
265
struct timeval tv;
266
267
memset(&tv, 0, sizeof(tv));
268
EFI_GetTimeOfDay(&tv, NULL);
269
270
if (tloc)
271
*tloc = tv.tv_sec;
272
return (tv.tv_sec);
273
}
274
275
time_t
276
getsecs(void)
277
{
278
279
return (time(NULL));
280
}
281
282