]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/boot/efi/libefi/time.c
Re-sync loader.mk and ficl.mk to where they should be
[FreeBSD/FreeBSD.git] / sys / boot / efi / libefi / time.c
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 <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include <efi.h>
45 #include <efilib.h>
46
47 #include <time.h>
48 #include <sys/time.h>
49
50 /*
51  * Accurate only for the past couple of centuries;
52  * that will probably do.
53  *
54  * (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
55  */
56
57 #define isleap(y)       (((y) % 4) == 0 && \
58                             (((y) % 100) != 0 || ((y) % 400) == 0))
59 #define SECSPERHOUR     (60*60)
60 #define SECSPERDAY      (24 * SECSPERHOUR)
61
62 /*
63  *  These arrays give the cumulative number of days up to the first of the
64  *  month number used as the index (1 -> 12) for regular and leap years.
65  *  The value at index 13 is for the whole year.
66  */
67 static const time_t CumulativeDays[2][14] = {
68         {0,
69         0,
70         31,
71         31 + 28,
72         31 + 28 + 31,
73         31 + 28 + 31 + 30,
74         31 + 28 + 31 + 30 + 31,
75         31 + 28 + 31 + 30 + 31 + 30,
76         31 + 28 + 31 + 30 + 31 + 30 + 31,
77         31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
78         31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
79         31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
80         31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
81         31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
82         {0,
83         0,
84         31,
85         31 + 29,
86         31 + 29 + 31,
87         31 + 29 + 31 + 30,
88         31 + 29 + 31 + 30 + 31,
89         31 + 29 + 31 + 30 + 31 + 30,
90         31 + 29 + 31 + 30 + 31 + 30 + 31,
91         31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
92         31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
93         31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
94         31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
95         31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
96
97 void
98 efi_time_init(void)
99 {
100 }
101
102 void
103 efi_time_fini(void)
104 {
105 }
106
107 void
108 to_efi_time(EFI_TIME *efi_time, time_t time)
109 {
110         int lyear, month;
111         time_t seconds;
112
113         if (time >= 0) {
114                 efi_time->Year = 1970;
115                 lyear = isleap(efi_time->Year);
116                 month = 13;
117                 seconds = CumulativeDays[lyear][month] * SECSPERDAY;
118                 while (time > seconds) {
119                         time -= seconds;
120                         efi_time->Year++;
121                         lyear = isleap(efi_time->Year);
122                         seconds = CumulativeDays[lyear][month] * SECSPERDAY;
123                 }
124
125                 efi_time->Month = 0;
126                 while (time >
127                     CumulativeDays[lyear][month] * SECSPERDAY) {
128                         efi_time->Month++;
129                 }
130
131                 month = efi_time->Month - 1;
132                 time -= CumulativeDays[lyear][month] * SECSPERDAY;
133
134                 for (efi_time->Day = 0; time > SECSPERDAY; efi_time->Day++)
135                         time -= SECSPERDAY;
136
137                 for (efi_time->Hour = 0; time > SECSPERHOUR; efi_time->Hour++)
138                         time -= SECSPERHOUR;
139
140                 for (efi_time->Minute = 0; time > 60; efi_time->Minute++)
141                         time -= 60;
142
143                 efi_time->Second = time;
144                 efi_time->Nanosecond = 0;
145                 efi_time->TimeZone = 0;
146                 efi_time->Daylight = 0;
147         } else {
148                 memset(efi_time, 0, sizeof(EFI_TIME));
149         }
150 }
151
152 time_t
153 from_efi_time(EFI_TIME *ETime)
154 {
155         time_t  UTime;
156         int     Year;
157
158         /*
159          *  Do a santity check
160          */
161         if (ETime->Year  <  1998 || ETime->Year   > 2099 ||
162             ETime->Month ==    0 || ETime->Month  >   12 ||
163             ETime->Day   ==    0 || ETime->Month  >   31 ||
164             ETime->Hour   >   23 || ETime->Minute >   59 ||
165             ETime->Second >   59 || ETime->TimeZone  < -1440 ||
166             (ETime->TimeZone >  1440 && ETime->TimeZone != 2047)) {
167                 return (0);
168         }
169
170         /*
171          * Years
172          */
173         UTime = 0;
174         for (Year = 1970; Year != ETime->Year; ++Year) {
175                 UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
176         }
177
178         /*
179          * UTime should now be set to 00:00:00 on Jan 1 of the file's year.
180          *
181          * Months  
182          */
183         UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] *
184             SECSPERDAY);
185
186         /*
187          * UTime should now be set to 00:00:00 on the first of the file's
188          * month and year.
189          *
190          * Days -- Don't count the file's day
191          */
192         UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
193
194         /*
195          * Hours
196          */
197         UTime += (ETime->Hour * SECSPERHOUR);
198
199         /*
200          * Minutes
201          */
202         UTime += (ETime->Minute * 60);
203
204         /*
205          * Seconds
206          */
207         UTime += ETime->Second;
208
209         /*
210          * EFI time is repored in local time.  Adjust for any time zone
211          * offset to get true UT
212          */
213         if (ETime->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
214                 /*
215                  * TimeZone is kept in minues...
216                  */
217                 UTime += (ETime->TimeZone * 60);
218         }
219
220         return (UTime);
221 }
222
223 static int
224 EFI_GetTimeOfDay(OUT struct timeval *tp, OUT struct timezone *tzp)
225 {
226         EFI_TIME                EfiTime;
227         EFI_TIME_CAPABILITIES   Capabilities;
228         EFI_STATUS              Status;
229
230         /*
231          *  Get time from EFI
232          */
233
234         Status = RS->GetTime(&EfiTime, &Capabilities);
235         if (EFI_ERROR(Status))
236                 return (-1);
237
238         /*
239          *  Convert to UNIX time (ie seconds since the epoch
240          */
241
242         tp->tv_sec  = from_efi_time(&EfiTime);
243         tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */
244
245         /*
246          * Do something with the timezone if needed
247          */
248
249         if (tzp != NULL) {
250                 if (EfiTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE)
251                         tzp->tz_minuteswest = 0;
252                 else
253                         tzp->tz_minuteswest = EfiTime.TimeZone;
254                 /*
255                  * This isn't quit right since it doesn't deal with
256                  * EFI_TIME_IN_DAYLIGHT
257                  */
258                 tzp->tz_dsttime =
259                         EfiTime.Daylight & EFI_TIME_ADJUST_DAYLIGHT ? 1 : 0;
260         }
261
262         return (0);
263 }
264
265 time_t
266 time(time_t *tloc)
267 {
268         struct timeval tv;
269
270         memset(&tv, 0, sizeof(tv));
271         EFI_GetTimeOfDay(&tv, NULL);
272
273         if (tloc)
274                 *tloc = tv.tv_sec;
275         return (tv.tv_sec);
276 }
277
278 time_t
279 getsecs(void)
280 {
281
282     return (time(NULL));
283 }