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