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 62time_t 63EfiTimeToUnixTime(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 168int 169EFI_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 210time_t 211time(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 221time_t 222getsecs(void) 223{ 224 return time(0); 225} 226