time.c revision 83666
183364Sdfr/*
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 */
4083364Sdfr
4183364Sdfr#ifndef lint
4283364Sdfrstatic const char rcsid[] =
4383364Sdfr  "$FreeBSD: head/sys/boot/ia64/ski/time.c 83666 2001-09-19 12:12:12Z dfr $";
4483364Sdfr#endif /* not lint */
4583364Sdfr
4683364Sdfr#include <time.h>
4783364Sdfr#include <sys/time.h>
4883666Sdfr#include <stand.h>
4983364Sdfr
5083666Sdfr#include "libski.h"
5183666Sdfr
5283364Sdfr/*
5383364Sdfr// Accurate only for the past couple of centuries;
5483364Sdfr// that will probably do.
5583364Sdfr//
5683364Sdfr// (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
5783364Sdfr*/
5883364Sdfr
5983364Sdfr#define isleap(y)	(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
6083364Sdfr#define SECSPERHOUR ( 60*60 )
6183364Sdfr#define SECSPERDAY	(24 * SECSPERHOUR)
6283364Sdfr
6383666Sdfrstruct ssc_time {
6483666Sdfr	int	Year;
6583666Sdfr	int	Month;
6683666Sdfr	int	Day;
6783666Sdfr	int	Hour;
6883666Sdfr	int	Minute;
6983666Sdfr	int	Second;
7083666Sdfr	int	Msec;
7183666Sdfr	int	Wday;
7283666Sdfr};
7383364Sdfr
7483364Sdfrtime_t
7583666SdfrEfiTimeToUnixTime(struct ssc_time *ETime)
7683666Sdfr{
7783666Sdfr    /*
7883666Sdfr    //  These arrays give the cumulative number of days up to the first of the
7983666Sdfr    //  month number used as the index (1 -> 12) for regular and leap years.
8083666Sdfr    //  The value at index 13 is for the whole year.
8183666Sdfr    */
8283666Sdfr    static time_t CumulativeDays[2][14] = {
8383666Sdfr    {0,
8483666Sdfr     0,
8583666Sdfr     31,
8683666Sdfr     31 + 28,
8783666Sdfr     31 + 28 + 31,
8883666Sdfr     31 + 28 + 31 + 30,
8983666Sdfr     31 + 28 + 31 + 30 + 31,
9083666Sdfr     31 + 28 + 31 + 30 + 31 + 30,
9183666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31,
9283666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
9383666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
9483666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
9583666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
9683666Sdfr     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
9783666Sdfr    {0,
9883666Sdfr     0,
9983666Sdfr     31,
10083666Sdfr     31 + 29,
10183666Sdfr     31 + 29 + 31,
10283666Sdfr     31 + 29 + 31 + 30,
10383666Sdfr     31 + 29 + 31 + 30 + 31,
10483666Sdfr     31 + 29 + 31 + 30 + 31 + 30,
10583666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31,
10683666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
10783666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
10883666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
10983666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
11083666Sdfr     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
11183666Sdfr
11283666Sdfr    time_t  UTime;
11383666Sdfr    int     Year;
11483666Sdfr
11583666Sdfr    ETime->Year += 1900;
11683666Sdfr
11783666Sdfr    /*
11883666Sdfr    //  Do a santity check
11983666Sdfr    */
12083666Sdfr    if ( ETime->Year  <  1998 || ETime->Year   > 2099 ||
12183666Sdfr    	 ETime->Month ==    0 || ETime->Month  >   12 ||
12283666Sdfr    	 ETime->Day   ==    0 || ETime->Month  >   31 ||
12383666Sdfr    	                         ETime->Hour   >   23 ||
12483666Sdfr    	                         ETime->Minute >   59 ||
12583666Sdfr    	                         ETime->Second >   59 ) {
12683666Sdfr    	return (0);
12783666Sdfr    }
12883666Sdfr
12983666Sdfr    /*
13083666Sdfr    // Years
13183666Sdfr    */
13283666Sdfr    UTime = 0;
13383666Sdfr    for (Year = 1970; Year != ETime->Year; ++Year) {
13483666Sdfr        UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
13583666Sdfr    }
13683666Sdfr
13783666Sdfr    /*
13883666Sdfr    // UTime should now be set to 00:00:00 on Jan 1 of the file's year.
13983666Sdfr    //
14083666Sdfr    // Months
14183666Sdfr    */
14283666Sdfr    UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY);
14383666Sdfr
14483666Sdfr    /*
14583666Sdfr    // UTime should now be set to 00:00:00 on the first of the file's month and year
14683666Sdfr    //
14783666Sdfr    // Days -- Don't count the file's day
14883666Sdfr    */
14983666Sdfr    UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
15083666Sdfr
15183666Sdfr    /*
15283666Sdfr    // Hours
15383666Sdfr    */
15483666Sdfr    UTime += (ETime->Hour * SECSPERHOUR);
15583666Sdfr
15683666Sdfr    /*
15783666Sdfr    // Minutes
15883666Sdfr    */
15983666Sdfr    UTime += (ETime->Minute * 60);
16083666Sdfr
16183666Sdfr    /*
16283666Sdfr    // Seconds
16383666Sdfr    */
16483666Sdfr    UTime += ETime->Second;
16583666Sdfr
16683666Sdfr    return UTime;
16783666Sdfr}
16883666Sdfr
16983666Sdfrtime_t
17083364Sdfrtime(time_t *tloc)
17183364Sdfr{
17283666Sdfr	struct ssc_time time;
17383666Sdfr
17483666Sdfr	ssc((u_int64_t) &time, 0, 0, 0, SSC_GET_RTC);
17583666Sdfr
17683666Sdfr	return *tloc = EfiTimeToUnixTime(&time);
17783364Sdfr}
178