• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 *
3 *  Copyright (c) 2016, Hisilicon Limited. All rights reserved.
4 *  Copyright (c) 2016, Linaro Limited. All rights reserved.
5 *
6 *  This program and the accompanying materials
7 *  are licensed and made available under the terms and conditions of the BSD License
8 *  which accompanies this distribution.  The full text of the license may be found at
9 *  http://opensource.org/licenses/bsd-license.php
10 *
11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15 
16 #include <Uefi/UefiBaseType.h>
17 #include <Uefi/UefiSpec.h>
18 #include <Library/DebugLib.h>
19 #include <Library/EfiTimeBaseLib.h>
20 
21 // Define EPOCH (1970-JANUARY-01) in the Julian Date representation
22 #define EPOCH_JULIAN_DATE                               2440588
23 
24 BOOLEAN
25 EFIAPI
IsLeapYear(IN EFI_TIME * Time)26 IsLeapYear (
27   IN EFI_TIME *Time
28   )
29 {
30   if (Time->Year % 4 == 0) {
31     if (Time->Year % 100 == 0) {
32       if (Time->Year % 400 == 0) {
33         return TRUE;
34       } else {
35         return FALSE;
36       }
37     } else {
38       return TRUE;
39     }
40   } else {
41     return FALSE;
42   }
43 }
44 
45 BOOLEAN
46 EFIAPI
IsDayValid(IN EFI_TIME * Time)47 IsDayValid (
48   IN EFI_TIME *Time
49   )
50 {
51   INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
52 
53   if (Time->Day < 1 ||
54       Time->Day > DayOfMonth[Time->Month - 1] ||
55       (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
56      ) {
57     return FALSE;
58   }
59 
60   return TRUE;
61 }
62 
63 BOOLEAN
64 EFIAPI
IsTimeValid(IN EFI_TIME * Time)65 IsTimeValid(
66   IN EFI_TIME *Time
67   )
68 {
69   // Check the input parameters are within the range specified by UEFI
70   if ((Time->Year   < 2000) ||
71      (Time->Year   > 2099) ||
72      (Time->Month  < 1   ) ||
73      (Time->Month  > 12  ) ||
74      (!IsDayValid (Time)    ) ||
75      (Time->Hour   > 23  ) ||
76      (Time->Minute > 59  ) ||
77      (Time->Second > 59  ) ||
78      (Time->Nanosecond > 999999999) ||
79      (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||
80      (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
81   ) {
82     return FALSE;
83   }
84 
85   return TRUE;
86 }
87 
88 /**
89   Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
90  **/
91 VOID
EpochToEfiTime(IN UINTN EpochSeconds,OUT EFI_TIME * Time)92 EpochToEfiTime (
93   IN  UINTN     EpochSeconds,
94   OUT EFI_TIME  *Time
95   )
96 {
97   UINTN         a;
98   UINTN         b;
99   UINTN         c;
100   UINTN         d;
101   UINTN         g;
102   UINTN         j;
103   UINTN         m;
104   UINTN         y;
105   UINTN         da;
106   UINTN         db;
107   UINTN         dc;
108   UINTN         dg;
109   UINTN         hh;
110   UINTN         mm;
111   UINTN         ss;
112   UINTN         J;
113 
114   J  = (EpochSeconds / 86400) + 2440588;
115   j  = J + 32044;
116   g  = j / 146097;
117   dg = j % 146097;
118   c  = (((dg / 36524) + 1) * 3) / 4;
119   dc = dg - (c * 36524);
120   b  = dc / 1461;
121   db = dc % 1461;
122   a  = (((db / 365) + 1) * 3) / 4;
123   da = db - (a * 365);
124   y  = (g * 400) + (c * 100) + (b * 4) + a;
125   m  = (((da * 5) + 308) / 153) - 2;
126   d  = da - (((m + 4) * 153) / 5) + 122;
127 
128   Time->Year  = y - 4800 + ((m + 2) / 12);
129   Time->Month = ((m + 2) % 12) + 1;
130   Time->Day   = d + 1;
131 
132   ss = EpochSeconds % 60;
133   a  = (EpochSeconds - ss) / 60;
134   mm = a % 60;
135   b = (a - mm) / 60;
136   hh = b % 24;
137 
138   Time->Hour        = hh;
139   Time->Minute      = mm;
140   Time->Second      = ss;
141   Time->Nanosecond  = 0;
142 
143 }
144 
145 /**
146   Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC)
147  **/
148 UINTN
EfiTimeToEpoch(IN EFI_TIME * Time)149 EfiTimeToEpoch (
150   IN  EFI_TIME  *Time
151   )
152 {
153   UINTN a;
154   UINTN y;
155   UINTN m;
156   UINTN JulianDate;  // Absolute Julian Date representation of the supplied Time
157   UINTN EpochDays;   // Number of days elapsed since EPOCH_JULIAN_DAY
158   UINTN EpochSeconds;
159 
160   a = (14 - Time->Month) / 12 ;
161   y = Time->Year + 4800 - a;
162   m = Time->Month + (12*a) - 3;
163 
164   JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;
165 
166   ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
167   EpochDays = JulianDate - EPOCH_JULIAN_DATE;
168 
169   EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;
170 
171   return EpochSeconds;
172 }
173