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