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