time.c revision 139738
118334Speter/*-
2169689Skan * Copyright (c) 1999, 2000
390075Sobrien * Intel Corporation.
418334Speter * All rights reserved.
590075Sobrien *
618334Speter * Redistribution and use in source and binary forms, with or without
790075Sobrien * modification, are permitted provided that the following conditions
890075Sobrien * are met:
990075Sobrien *
1090075Sobrien * 1. Redistributions of source code must retain the above copyright
1118334Speter *    notice, this list of conditions and the following disclaimer.
1290075Sobrien *
1390075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1490075Sobrien *    notice, this list of conditions and the following disclaimer in the
1590075Sobrien *    documentation and/or other materials provided with the distribution.
1618334Speter *
1718334Speter * 3. All advertising materials mentioning features or use of this software
1890075Sobrien *    must display the following acknowledgement:
19169689Skan *
20169689Skan *    This product includes software developed by Intel Corporation and
2118334Speter *    its contributors.
2290075Sobrien *
2390075Sobrien * 4. Neither the name of Intel Corporation or its contributors may be
2418334Speter *    used to endorse or promote products derived from this software
2550397Sobrien *    without specific prior written permission.
2652284Sobrien *
2752284Sobrien * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
2890075Sobrien * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29117395Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30169689Skan * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
31169689Skan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32169689Skan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3318334Speter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3490075Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3590075Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36169689Skan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3790075Sobrien * THE POSSIBILITY OF SUCH DAMAGE.
3890075Sobrien */
3918334Speter
40169689Skan#include <sys/cdefs.h>
41169689Skan__FBSDID("$FreeBSD: head/sys/boot/ia64/ski/time.c 139738 2005-01-05 22:16:58Z imp $");
42169689Skan
43169689Skan#include <time.h>
44169689Skan#include <sys/time.h>
45169689Skan#include <stand.h>
4690075Sobrien
47169689Skan#include "libski.h"
4890075Sobrien
4950397Sobrien/*
5050397Sobrien// Accurate only for the past couple of centuries;
5118334Speter// that will probably do.
5250397Sobrien//
5350397Sobrien// (#defines From FreeBSD 3.2 lib/libc/stdtime/tzfile.h)
5418334Speter*/
5590075Sobrien
5690075Sobrien#define isleap(y)	(((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
5790075Sobrien#define SECSPERHOUR ( 60*60 )
5850397Sobrien#define SECSPERDAY	(24 * SECSPERHOUR)
59169689Skan
6018334Speterstruct ssc_time {
6150397Sobrien	int	Year;
62169689Skan	int	Month;
6318334Speter	int	Day;
6450397Sobrien	int	Hour;
65169689Skan	int	Minute;
6618334Speter	int	Second;
6790075Sobrien	int	Msec;
68169689Skan	int	Wday;
6990075Sobrien};
7050397Sobrien
7150397Sobrientime_t
72169689SkanEfiTimeToUnixTime(struct ssc_time *ETime)
7318334Speter{
7450397Sobrien    /*
7550397Sobrien    //  These arrays give the cumulative number of days up to the first of the
7650397Sobrien    //  month number used as the index (1 -> 12) for regular and leap years.
7750397Sobrien    //  The value at index 13 is for the whole year.
7850397Sobrien    */
7950397Sobrien    static time_t CumulativeDays[2][14] = {
8050397Sobrien    {0,
8150397Sobrien     0,
8250397Sobrien     31,
8350397Sobrien     31 + 28,
84132718Skan     31 + 28 + 31,
8550397Sobrien     31 + 28 + 31 + 30,
8650397Sobrien     31 + 28 + 31 + 30 + 31,
8750397Sobrien     31 + 28 + 31 + 30 + 31 + 30,
8890075Sobrien     31 + 28 + 31 + 30 + 31 + 30 + 31,
8950397Sobrien     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
9050397Sobrien     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
91169689Skan     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
92169689Skan     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
9350397Sobrien     31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 },
9490075Sobrien    {0,
95169689Skan     0,
96169689Skan     31,
9750397Sobrien     31 + 29,
9850397Sobrien     31 + 29 + 31,
9950397Sobrien     31 + 29 + 31 + 30,
10090075Sobrien     31 + 29 + 31 + 30 + 31,
101169689Skan     31 + 29 + 31 + 30 + 31 + 30,
102169689Skan     31 + 29 + 31 + 30 + 31 + 30 + 31,
10350397Sobrien     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
10450397Sobrien     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
10550397Sobrien     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
10690075Sobrien     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
107169689Skan     31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 }};
108169689Skan
10950397Sobrien    time_t  UTime;
110132718Skan    int     Year;
111132718Skan
112132718Skan    ETime->Year += 1900;
113132718Skan
114132718Skan    /*
11590075Sobrien    //  Do a santity check
11690075Sobrien    */
11752284Sobrien    if ( ETime->Year  <  1998 || ETime->Year   > 2099 ||
118169689Skan    	 ETime->Month ==    0 || ETime->Month  >   12 ||
119169689Skan    	 ETime->Day   ==    0 || ETime->Month  >   31 ||
12052284Sobrien    	                         ETime->Hour   >   23 ||
121169689Skan    	                         ETime->Minute >   59 ||
122169689Skan    	                         ETime->Second >   59 ) {
12318334Speter    	return (0);
12452284Sobrien    }
125169689Skan
126169689Skan    /*
127169689Skan    // Years
128169689Skan    */
12918334Speter    UTime = 0;
13052284Sobrien    for (Year = 1970; Year != ETime->Year; ++Year) {
131169689Skan        UTime += (CumulativeDays[isleap(Year)][13] * SECSPERDAY);
13218334Speter    }
133169689Skan
134169689Skan    /*
135169689Skan    // UTime should now be set to 00:00:00 on Jan 1 of the file's year.
13652284Sobrien    //
13752284Sobrien    // Months
13890075Sobrien    */
13990075Sobrien    UTime += (CumulativeDays[isleap(ETime->Year)][ETime->Month] * SECSPERDAY);
14018334Speter
141169689Skan    /*
142169689Skan    // UTime should now be set to 00:00:00 on the first of the file's month and year
143169689Skan    //
144169689Skan    // Days -- Don't count the file's day
145169689Skan    */
146169689Skan    UTime += (((ETime->Day > 0) ? ETime->Day-1:0) * SECSPERDAY);
147169689Skan
148169689Skan    /*
149169689Skan    // Hours
150117395Skan    */
151117395Skan    UTime += (ETime->Hour * SECSPERHOUR);
152117395Skan
153117395Skan    /*
154117395Skan    // Minutes
155117395Skan    */
156117395Skan    UTime += (ETime->Minute * 60);
157117395Skan
158117395Skan    /*
159117395Skan    // Seconds
160132718Skan    */
161132718Skan    UTime += ETime->Second;
162132718Skan
163169689Skan    return UTime;
164169689Skan}
165169689Skan
166169689Skantime_t
167169689Skantime(time_t *tloc)
168169689Skan{
169169689Skan	struct ssc_time time;
170169689Skan
171169689Skan	ssc((u_int64_t) &time, 0, 0, 0, SSC_GET_RTC);
172169689Skan
17318334Speter	return *tloc = EfiTimeToUnixTime(&time);
17490075Sobrien}
17550397Sobrien