1139738Simp/*-
277943Sdfr * Copyright (c) 1999, 2000
377943Sdfr * Intel Corporation.
477943Sdfr * All rights reserved.
577943Sdfr *
677943Sdfr * Redistribution and use in source and binary forms, with or without
777943Sdfr * modification, are permitted provided that the following conditions
877943Sdfr * are met:
977943Sdfr *
1077943Sdfr * 1. Redistributions of source code must retain the above copyright
1177943Sdfr *    notice, this list of conditions and the following disclaimer.
1277943Sdfr *
1377943Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1477943Sdfr *    notice, this list of conditions and the following disclaimer in the
1577943Sdfr *    documentation and/or other materials provided with the distribution.
1677943Sdfr *
1777943Sdfr * 3. All advertising materials mentioning features or use of this software
1877943Sdfr *    must display the following acknowledgement:
1977943Sdfr *
2077943Sdfr *    This product includes software developed by Intel Corporation and
2177943Sdfr *    its contributors.
2277943Sdfr *
2377943Sdfr * 4. Neither the name of Intel Corporation or its contributors may be
2477943Sdfr *    used to endorse or promote products derived from this software
2577943Sdfr *    without specific prior written permission.
2677943Sdfr *
2777943Sdfr * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
2877943Sdfr * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2977943Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3077943Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
3177943Sdfr * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3277943Sdfr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3377943Sdfr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3477943Sdfr * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3577943Sdfr * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3677943Sdfr * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3777943Sdfr * THE POSSIBILITY OF SUCH DAMAGE.
3877943Sdfr *
3977943Sdfr */
4077943Sdfr
41113038Sobrien#include <sys/cdefs.h>
42113038Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/boot/efi/libefi/time.c 164010 2006-11-05 22:03:04Z marcel $");
4378328Sobrien
4477943Sdfr#include <efi.h>
4577943Sdfr#include <efilib.h>
4677943Sdfr
4777943Sdfr#include <time.h>
4877943Sdfr#include <sys/time.h>
4977943Sdfr
5078328Sobrien/*
5177943Sdfr// Accurate only for the past couple of centuries;
5277943Sdfr// that will probably do.
5377943Sdfr//
5477943Sdfr// (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
5578328Sobrien*/
5677943Sdfr
5777943Sdfr#define isleap(y)	(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
5877943Sdfr#define SECSPERHOUR ( 60*60 )
5977943Sdfr#define SECSPERDAY	(24 * SECSPERHOUR)
6077943Sdfr
6177943Sdfrtime_t
62164010Smarcelefi_time(EFI_TIME *ETime)
6377943Sdfr{
6478328Sobrien    /*
6577943Sdfr    //  These arrays give the cumulative number of days up to the first of the
6677943Sdfr    //  month number used as the index (1 -> 12) for regular and leap years.
6777943Sdfr    //  The value at index 13 is for the whole year.
6878328Sobrien    */
6977943Sdfr    static time_t CumulativeDays[2][14] = {
7077943Sdfr    {0,
7177943Sdfr     0,
7277943Sdfr     31,
7377943Sdfr     31 + 28,
7477943Sdfr     31 + 28 + 31,
7577943Sdfr     31 + 28 + 31 + 30,
7677943Sdfr     31 + 28 + 31 + 30 + 31,
7777943Sdfr     31 + 28 + 31 + 30 + 31 + 30,
7877943Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31,
7977943Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
8077943Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
8177943Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
8277943Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
8377943Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
8477943Sdfr    {0,
8577943Sdfr     0,
8677943Sdfr     31,
8777943Sdfr     31 + 29,
8877943Sdfr     31 + 29 + 31,
8977943Sdfr     31 + 29 + 31 + 30,
9077943Sdfr     31 + 29 + 31 + 30 + 31,
9177943Sdfr     31 + 29 + 31 + 30 + 31 + 30,
9277943Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31,
9377943Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
9477943Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
9577943Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
9677943Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
9777943Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
9877943Sdfr
9977943Sdfr    time_t  UTime;
10077943Sdfr    int     Year;
10177943Sdfr
10278328Sobrien    /*
10377943Sdfr    //  Do a santity check
10478328Sobrien    */
10577943Sdfr    if ( ETime->Year  <  1998 || ETime->Year   > 2099 ||
10677943Sdfr    	 ETime->Month ==    0 || ETime->Month  >   12 ||
10777943Sdfr    	 ETime->Day   ==    0 || ETime->Month  >   31 ||
10877943Sdfr    	                         ETime->Hour   >   23 ||
10977943Sdfr    	                         ETime->Minute >   59 ||
11077943Sdfr    	                         ETime->Second >   59 ||
11177943Sdfr    	 ETime->TimeZone  < -1440                     ||
11277943Sdfr    	 (ETime->TimeZone >  1440 && ETime->TimeZone != 2047) ) {
11377943Sdfr    	return (0);
11477943Sdfr    }
11577943Sdfr
11678328Sobrien    /*
11777943Sdfr    // Years
11878328Sobrien    */
11977943Sdfr    UTime = 0;
12077943Sdfr    for (Year = 1970; Year != ETime->Year; ++Year) {
12177943Sdfr        UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
12277943Sdfr    }
12377943Sdfr
12478328Sobrien    /*
12578328Sobrien    // UTime should now be set to 00:00:00 on Jan 1 of the file's year.
12677943Sdfr    //
12777943Sdfr    // Months
12878328Sobrien    */
12977943Sdfr    UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY);
13077943Sdfr
13178328Sobrien    /*
13277943Sdfr    // UTime should now be set to 00:00:00 on the first of the file's month and year
13377943Sdfr    //
13477943Sdfr    // Days -- Don't count the file's day
13578328Sobrien    */
13677943Sdfr    UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
13777943Sdfr
13878328Sobrien    /*
13977943Sdfr    // Hours
14078328Sobrien    */
14177943Sdfr    UTime += (ETime->Hour * SECSPERHOUR);
14277943Sdfr
14378328Sobrien    /*
14477943Sdfr    // Minutes
14578328Sobrien    */
14677943Sdfr    UTime += (ETime->Minute * 60);
14777943Sdfr
14878328Sobrien    /*
14977943Sdfr    // Seconds
15078328Sobrien    */
15177943Sdfr    UTime += ETime->Second;
15277943Sdfr
15378328Sobrien    /*
15477943Sdfr    //  EFI time is repored in local time.  Adjust for any time zone offset to
15577943Sdfr    //  get true UT
15678328Sobrien    */
15777943Sdfr    if ( ETime->TimeZone != EFI_UNSPECIFIED_TIMEZONE ) {
15878328Sobrien    	/*
15977943Sdfr    	//  TimeZone is kept in minues...
16078328Sobrien    	*/
16177943Sdfr    	UTime += (ETime->TimeZone * 60);
16277943Sdfr    }
16377943Sdfr
16477943Sdfr    return UTime;
16577943Sdfr}
16677943Sdfr
16777943Sdfrint
16877943SdfrEFI_GetTimeOfDay(
16977943Sdfr	OUT struct timeval *tp,
17077943Sdfr	OUT struct timezone *tzp
17177943Sdfr	)
17277943Sdfr{
173164010Smarcel	EFI_TIME		EfiTime;
17477943Sdfr	EFI_TIME_CAPABILITIES	Capabilities;
175164010Smarcel	EFI_STATUS		Status;
17677943Sdfr
17778328Sobrien	/*
17877943Sdfr	//  Get time from EFI
17978328Sobrien	*/
18077943Sdfr
181164010Smarcel	Status = RS->GetTime(&EfiTime, &Capabilities);
18277943Sdfr	if (EFI_ERROR(Status))
18377943Sdfr		return (-1);
18477943Sdfr
18578328Sobrien	/*
18677943Sdfr	//  Convert to UNIX time (ie seconds since the epoch
18778328Sobrien	*/
18877943Sdfr
189164010Smarcel	tp->tv_sec  = efi_time( &EfiTime );
19078328Sobrien	tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */
19177943Sdfr
19278328Sobrien	/*
19377943Sdfr	//  Do something with the timezone if needed
19478328Sobrien	*/
19577943Sdfr
19677943Sdfr	if (tzp) {
19777943Sdfr		tzp->tz_minuteswest =
19877943Sdfr			EfiTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE ? 0 : EfiTime.TimeZone;
19978328Sobrien		/*
20077943Sdfr		//  This isn't quit right since it doesn't deal with EFI_TIME_IN_DAYLIGHT
20178328Sobrien		*/
20277943Sdfr		tzp->tz_dsttime =
20377943Sdfr			EfiTime.Daylight & EFI_TIME_ADJUST_DAYLIGHT ? 1 : 0;
20477943Sdfr	}
20577943Sdfr
20677943Sdfr	return (0);
20777943Sdfr}
20877943Sdfr
20977943Sdfrtime_t
21077943Sdfrtime(time_t *tloc)
21177943Sdfr{
21277943Sdfr	struct timeval tv;
21377943Sdfr	EFI_GetTimeOfDay(&tv, 0);
21477943Sdfr
21577943Sdfr	if (tloc)
21677943Sdfr		*tloc = tv.tv_sec;
21777943Sdfr	return tv.tv_sec;
21877943Sdfr}
21983825Sdfr
22083825Sdfrtime_t
22183825Sdfrgetsecs()
22283825Sdfr{
22383825Sdfr    return time(0);
22483825Sdfr}
225