1139738Simp/*-
283364Sdfr * Copyright (c) 1999, 2000
383364Sdfr * Intel Corporation.
483364Sdfr * All rights reserved.
583364Sdfr *
683364Sdfr * Redistribution and use in source and binary forms, with or without
783364Sdfr * modification, are permitted provided that the following conditions
883364Sdfr * are met:
983364Sdfr *
1083364Sdfr * 1. Redistributions of source code must retain the above copyright
1183364Sdfr *    notice, this list of conditions and the following disclaimer.
1283364Sdfr *
1383364Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1483364Sdfr *    notice, this list of conditions and the following disclaimer in the
1583364Sdfr *    documentation and/or other materials provided with the distribution.
1683364Sdfr *
1783364Sdfr * 3. All advertising materials mentioning features or use of this software
1883364Sdfr *    must display the following acknowledgement:
1983364Sdfr *
2083364Sdfr *    This product includes software developed by Intel Corporation and
2183364Sdfr *    its contributors.
2283364Sdfr *
2383364Sdfr * 4. Neither the name of Intel Corporation or its contributors may be
2483364Sdfr *    used to endorse or promote products derived from this software
2583364Sdfr *    without specific prior written permission.
2683364Sdfr *
2783364Sdfr * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
2883364Sdfr * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2983364Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3083364Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
3183364Sdfr * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3283364Sdfr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3383364Sdfr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3483364Sdfr * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3583364Sdfr * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3683364Sdfr * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3783364Sdfr * THE POSSIBILITY OF SUCH DAMAGE.
3883364Sdfr */
3983364Sdfr
40113038Sobrien#include <sys/cdefs.h>
41113038Sobrien__FBSDID("$FreeBSD$");
4283364Sdfr
4383364Sdfr#include <time.h>
4483364Sdfr#include <sys/time.h>
4583666Sdfr#include <stand.h>
4683364Sdfr
4783666Sdfr#include "libski.h"
4883666Sdfr
4983364Sdfr/*
5083364Sdfr// Accurate only for the past couple of centuries;
5183364Sdfr// that will probably do.
5283364Sdfr//
5383364Sdfr// (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
5483364Sdfr*/
5583364Sdfr
5683364Sdfr#define isleap(y)	(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
5783364Sdfr#define SECSPERHOUR ( 60*60 )
5883364Sdfr#define SECSPERDAY	(24 * SECSPERHOUR)
5983364Sdfr
6083666Sdfrstruct ssc_time {
6183666Sdfr	int	Year;
6283666Sdfr	int	Month;
6383666Sdfr	int	Day;
6483666Sdfr	int	Hour;
6583666Sdfr	int	Minute;
6683666Sdfr	int	Second;
6783666Sdfr	int	Msec;
6883666Sdfr	int	Wday;
6983666Sdfr};
7083364Sdfr
7183364Sdfrtime_t
7283666SdfrEfiTimeToUnixTime(struct ssc_time *ETime)
7383666Sdfr{
7483666Sdfr    /*
7583666Sdfr    //  These arrays give the cumulative number of days up to the first of the
7683666Sdfr    //  month number used as the index (1 -> 12) for regular and leap years.
7783666Sdfr    //  The value at index 13 is for the whole year.
7883666Sdfr    */
7983666Sdfr    static time_t CumulativeDays[2][14] = {
8083666Sdfr    {0,
8183666Sdfr     0,
8283666Sdfr     31,
8383666Sdfr     31 + 28,
8483666Sdfr     31 + 28 + 31,
8583666Sdfr     31 + 28 + 31 + 30,
8683666Sdfr     31 + 28 + 31 + 30 + 31,
8783666Sdfr     31 + 28 + 31 + 30 + 31 + 30,
8883666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31,
8983666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
9083666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
9183666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
9283666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
9383666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
9483666Sdfr    {0,
9583666Sdfr     0,
9683666Sdfr     31,
9783666Sdfr     31 + 29,
9883666Sdfr     31 + 29 + 31,
9983666Sdfr     31 + 29 + 31 + 30,
10083666Sdfr     31 + 29 + 31 + 30 + 31,
10183666Sdfr     31 + 29 + 31 + 30 + 31 + 30,
10283666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31,
10383666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
10483666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
10583666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
10683666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
10783666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
10883666Sdfr
10983666Sdfr    time_t  UTime;
11083666Sdfr    int     Year;
11183666Sdfr
11283666Sdfr    ETime->Year += 1900;
11383666Sdfr
11483666Sdfr    /*
11583666Sdfr    //  Do a santity check
11683666Sdfr    */
11783666Sdfr    if ( ETime->Year  <  1998 || ETime->Year   > 2099 ||
11883666Sdfr    	 ETime->Month ==    0 || ETime->Month  >   12 ||
11983666Sdfr    	 ETime->Day   ==    0 || ETime->Month  >   31 ||
12083666Sdfr    	                         ETime->Hour   >   23 ||
12183666Sdfr    	                         ETime->Minute >   59 ||
12283666Sdfr    	                         ETime->Second >   59 ) {
12383666Sdfr    	return (0);
12483666Sdfr    }
12583666Sdfr
12683666Sdfr    /*
12783666Sdfr    // Years
12883666Sdfr    */
12983666Sdfr    UTime = 0;
13083666Sdfr    for (Year = 1970; Year != ETime->Year; ++Year) {
13183666Sdfr        UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
13283666Sdfr    }
13383666Sdfr
13483666Sdfr    /*
13583666Sdfr    // UTime should now be set to 00:00:00 on Jan 1 of the file's year.
13683666Sdfr    //
13783666Sdfr    // Months
13883666Sdfr    */
13983666Sdfr    UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY);
14083666Sdfr
14183666Sdfr    /*
14283666Sdfr    // UTime should now be set to 00:00:00 on the first of the file's month and year
14383666Sdfr    //
14483666Sdfr    // Days -- Don't count the file's day
14583666Sdfr    */
14683666Sdfr    UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
14783666Sdfr
14883666Sdfr    /*
14983666Sdfr    // Hours
15083666Sdfr    */
15183666Sdfr    UTime += (ETime->Hour * SECSPERHOUR);
15283666Sdfr
15383666Sdfr    /*
15483666Sdfr    // Minutes
15583666Sdfr    */
15683666Sdfr    UTime += (ETime->Minute * 60);
15783666Sdfr
15883666Sdfr    /*
15983666Sdfr    // Seconds
16083666Sdfr    */
16183666Sdfr    UTime += ETime->Second;
16283666Sdfr
16383666Sdfr    return UTime;
16483666Sdfr}
16583666Sdfr
16683666Sdfrtime_t
16783364Sdfrtime(time_t *tloc)
16883364Sdfr{
16983666Sdfr	struct ssc_time time;
17083666Sdfr
17183666Sdfr	ssc((u_int64_t) &time, 0, 0, 0, SSC_GET_RTC);
17283666Sdfr
17383666Sdfr	return *tloc = EfiTimeToUnixTime(&time);
17483364Sdfr}
175