1/* $NetBSD: time.c,v 1.4 2016/08/04 18:07:43 scole 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#include <machine/efilib.h> 52 53/* 54// Accurate only for the past couple of centuries; 55// that will probably do. 56// 57// (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h) 58*/ 59 60#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 61#define SECSPERHOUR ( 60*60 ) 62#define SECSPERDAY (24 * SECSPERHOUR) 63 64time_t 65EfiTimeToUnixTime(EFI_TIME *ETime) 66{ 67 /* 68 // These arrays give the cumulative number of days up to the first of the 69 // month number used as the index (1 -> 12) for regular and leap years. 70 // The value at index 13 is for the whole year. 71 */ 72 static time_t CumulativeDays[2][14] = { 73 {0, 74 0, 75 31, 76 31 + 28, 77 31 + 28 + 31, 78 31 + 28 + 31 + 30, 79 31 + 28 + 31 + 30 + 31, 80 31 + 28 + 31 + 30 + 31 + 30, 81 31 + 28 + 31 + 30 + 31 + 30 + 31, 82 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, 83 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 84 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 85 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 86 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }, 87 {0, 88 0, 89 31, 90 31 + 29, 91 31 + 29 + 31, 92 31 + 29 + 31 + 30, 93 31 + 29 + 31 + 30 + 31, 94 31 + 29 + 31 + 30 + 31 + 30, 95 31 + 29 + 31 + 30 + 31 + 30 + 31, 96 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31, 97 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 98 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 99 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 100 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }}; 101 102 time_t UTime; 103 int Year; 104 105 /* 106 // Do a santity check 107 */ 108 if ( ETime->Year < 1998 || ETime->Year > 2099 || 109 ETime->Month == 0 || ETime->Month > 12 || 110 ETime->Day == 0 || ETime->Month > 31 || 111 ETime->Hour > 23 || 112 ETime->Minute > 59 || 113 ETime->Second > 59 || 114 ETime->TimeZone < -1440 || 115 (ETime->TimeZone > 1440 && ETime->TimeZone != 2047) ) { 116 return (0); 117 } 118 119 /* 120 // Years 121 */ 122 UTime = 0; 123 for (Year = 1970; Year != ETime->Year; ++Year) { 124 UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY); 125 } 126 127 /* 128 // UTime should now be set to 00:00:00 on Jan 1 of the file's year. 129 // 130 // Months 131 */ 132 UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY); 133 134 /* 135 // UTime should now be set to 00:00:00 on the first of the file's month and year 136 // 137 // Days -- Don't count the file's day 138 */ 139 UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY); 140 141 /* 142 // Hours 143 */ 144 UTime += (ETime->Hour * SECSPERHOUR); 145 146 /* 147 // Minutes 148 */ 149 UTime += (ETime->Minute * 60); 150 151 /* 152 // Seconds 153 */ 154 UTime += ETime->Second; 155 156 /* 157 // EFI time is repored in local time. Adjust for any time zone offset to 158 // get true UT 159 */ 160 if ( ETime->TimeZone != EFI_UNSPECIFIED_TIMEZONE ) { 161 /* 162 // TimeZone is kept in minues... 163 */ 164 UTime += (ETime->TimeZone * 60); 165 } 166 167 return UTime; 168} 169 170int 171EFI_GetTimeOfDay( 172 OUT struct timeval *tp, 173 OUT struct timezone *tzp 174 ) 175{ 176 EFI_TIME EfiTime; 177 EFI_TIME_CAPABILITIES Capabilities; 178 EFI_STATUS Status; 179 180 /* 181 // Get time from EFI 182 */ 183 184 Status = RS->GetTime( &EfiTime, &Capabilities ); 185 if (EFI_ERROR(Status)) 186 return (-1); 187 188 /* 189 // Convert to UNIX time (ie seconds since the epoch 190 */ 191 192 tp->tv_sec = EfiTimeToUnixTime( &EfiTime ); 193 tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */ 194 195 /* 196 // Do something with the timezone if needed 197 */ 198 199 if (tzp) { 200 tzp->tz_minuteswest = 201 EfiTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE ? 0 : EfiTime.TimeZone; 202 /* 203 // This isn't quit right since it doesn't deal with EFI_TIME_IN_DAYLIGHT 204 */ 205 tzp->tz_dsttime = 206 EfiTime.Daylight & EFI_TIME_ADJUST_DAYLIGHT ? 1 : 0; 207 } 208 209 return (0); 210} 211 212time_t 213time(time_t *tloc) 214{ 215 struct timeval tv; 216 EFI_GetTimeOfDay(&tv, 0); 217 218 if (tloc) 219 *tloc = tv.tv_sec; 220 return tv.tv_sec; 221} 222 223time_t 224getsecs(void) 225{ 226 return time(0); 227} 228