]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/SysCall/RealTimeClock.c
1.Fix a icc build break
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / SysCall / RealTimeClock.c
1 /** @file
2 C Run-Time Libraries (CRT) Time Management Routines Wrapper Implementation
3 for OpenSSL-based Cryptographic Library (used in SMM).
4
5 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
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 <Library/BaseLib.h>
17 #include <Library/IoLib.h>
18 #include <OpenSslSupport.h>
19
20 #define PCAT_RTC_ADDRESS_REGISTER 0x70
21 #define PCAT_RTC_DATA_REGISTER 0x71
22
23 #define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
24 #define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
25 #define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
26 #define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
27 #define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
28 #define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
29 #define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
30 #define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
31 #define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
32 #define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
33 #define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
34 #define RTC_ADDRESS_REGISTER_B 11 // R/W
35 #define RTC_ADDRESS_REGISTER_C 12 // RO
36 #define RTC_ADDRESS_REGISTER_D 13 // RO
37 #define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
38
39 //
40 // Register A
41 //
42 typedef struct {
43 UINT8 RS : 4; // Rate Selection Bits
44 UINT8 DV : 3; // Divisor
45 UINT8 UIP : 1; // Update in progress
46 } RTC_REGISTER_A_BITS;
47
48 typedef union {
49 RTC_REGISTER_A_BITS Bits;
50 UINT8 Data;
51 } RTC_REGISTER_A;
52
53 //
54 // Register B
55 //
56 typedef struct {
57 UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled
58 UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode
59 UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format
60 UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output
61 UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled
62 UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled
63 UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled
64 UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited
65 } RTC_REGISTER_B_BITS;
66
67 typedef union {
68 RTC_REGISTER_B_BITS Bits;
69 UINT8 Data;
70 } RTC_REGISTER_B;
71
72 //
73 // -- Time Management Routines --
74 //
75
76 #define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
77 #define SECSPERHOUR (60 * 60)
78 #define SECSPERDAY (24 * SECSPERHOUR)
79
80 //
81 // The arrays give the cumulative number of days up to the first of the
82 // month number used as the index (1 -> 12) for regular and leap years.
83 // The value at index 13 is for the whole year.
84 //
85 UINTN CumulativeDays[2][14] = {
86 {
87 0,
88 0,
89 31,
90 31 + 28,
91 31 + 28 + 31,
92 31 + 28 + 31 + 30,
93 31 + 28 + 31 + 30 + 31,
94 31 + 28 + 31 + 30 + 31 + 30,
95 31 + 28 + 31 + 30 + 31 + 30 + 31,
96 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
97 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
98 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
99 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
100 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
101 },
102 {
103 0,
104 0,
105 31,
106 31 + 29,
107 31 + 29 + 31,
108 31 + 29 + 31 + 30,
109 31 + 29 + 31 + 30 + 31,
110 31 + 29 + 31 + 30 + 31 + 30,
111 31 + 29 + 31 + 30 + 31 + 30 + 31,
112 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
113 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
114 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
115 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
116 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
117 }
118 };
119
120 /**
121 Read RTC content through its registers.
122
123 @param Address Address offset of RTC. It is recommended to use macros such as
124 RTC_ADDRESS_SECONDS.
125
126 @return The data of UINT8 type read from RTC.
127 **/
128 UINT8
129 RtcRead (
130 IN UINT8 Address
131 )
132 {
133 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & BIT7)));
134 return IoRead8 (PCAT_RTC_DATA_REGISTER);
135 }
136
137 /* Get the system time as seconds elapsed since midnight, January 1, 1970. */
138 //INTN time(
139 // INTN *timer
140 // )
141 time_t time (time_t *timer)
142 {
143 UINT16 Year;
144 UINT8 Month;
145 UINT8 Day;
146 UINT8 Hour;
147 UINT8 Minute;
148 UINT8 Second;
149 UINT8 Century;
150 RTC_REGISTER_A RegisterA;
151 RTC_REGISTER_B RegisterB;
152 BOOLEAN IsPM;
153 UINT16 YearIndex;
154
155 RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
156 while (RegisterA.Bits.UIP == 1) {
157 CpuPause();
158 RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
159 }
160
161 Second = RtcRead (RTC_ADDRESS_SECONDS);
162 Minute = RtcRead (RTC_ADDRESS_MINUTES);
163 Hour = RtcRead (RTC_ADDRESS_HOURS);
164 Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
165 Month = RtcRead (RTC_ADDRESS_MONTH);
166 Year = RtcRead (RTC_ADDRESS_YEAR);
167 Century = RtcRead (RTC_ADDRESS_CENTURY);
168
169 RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
170
171 if ((Hour & BIT7) != 0) {
172 IsPM = TRUE;
173 } else {
174 IsPM = FALSE;
175 }
176 Hour = (UINT8) (Hour & 0x7f);
177
178 if (RegisterB.Bits.DM == 0) {
179 Year = BcdToDecimal8 ((UINT8) Year);
180 Month = BcdToDecimal8 (Month);
181 Day = BcdToDecimal8 (Day);
182 Hour = BcdToDecimal8 (Hour);
183 Minute = BcdToDecimal8 (Minute);
184 Second = BcdToDecimal8 (Second);
185 }
186 Century = BcdToDecimal8 (Century);
187
188 Year = (UINT16) (Century * 100 + Year);
189
190 //
191 // If time is in 12 hour format, convert it to 24 hour format
192 //
193 if (RegisterB.Bits.MIL == 0) {
194 if (IsPM && Hour < 12) {
195 Hour = (UINT8) (Hour + 12);
196 }
197 if (!IsPM && Hour == 12) {
198 Hour = 0;
199 }
200 }
201
202 //
203 // Years Handling
204 // UTime should now be set to 00:00:00 on Jan 1 of the current year.
205 //
206 for (YearIndex = 1970, *timer = 0; YearIndex != Year; YearIndex++) {
207 *timer = *timer + (time_t)(CumulativeDays[IsLeap(YearIndex)][13] * SECSPERDAY);
208 }
209
210 //
211 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
212 //
213 ASSERT (Month <= 12);
214 *timer = *timer +
215 (time_t)(CumulativeDays[IsLeap(Year)][Month] * SECSPERDAY) +
216 (time_t)((Day - 1) * SECSPERDAY) +
217 (time_t)(Hour * SECSPERHOUR) +
218 (time_t)(Minute * 60) +
219 (time_t)Second;
220
221 return *timer;
222 }