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