]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/RealTimeClockRuntimeDxe/RealTimeClock.c
EmulatorPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmulatorPkg / RealTimeClockRuntimeDxe / RealTimeClock.c
1 /*++
2 Emu RTC Architectural Protocol Driver as defined in PI
3
4 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9 #include <PiDxe.h>
10
11 #include <Library/BaseLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/UefiLib.h>
14 #include <Library/UefiDriverEntryPoint.h>
15 #include <Library/EmuThunkLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18
19 #include <Protocol/RealTimeClock.h>
20
21 BOOLEAN
22 DayValid (
23 IN EFI_TIME *Time
24 );
25
26 BOOLEAN
27 IsLeapYear (
28 IN EFI_TIME *Time
29 );
30
31 EFI_STATUS
32 RtcTimeFieldsValid (
33 IN EFI_TIME *Time
34 );
35
36 EFI_STATUS
37 EFIAPI
38 InitializeRealTimeClock (
39 IN EFI_HANDLE ImageHandle,
40 IN EFI_SYSTEM_TABLE *SystemTable
41 );
42
43 EFI_STATUS
44 EFIAPI
45 EmuGetTime (
46 OUT EFI_TIME * Time,
47 OUT EFI_TIME_CAPABILITIES * Capabilities OPTIONAL
48 )
49 /*++
50
51 Routine Description:
52 Service routine for RealTimeClockInstance->GetTime
53
54 Arguments:
55
56 Time - A pointer to storage that will receive a snapshot of the current time.
57
58 Capabilities - A pointer to storage that will receive the capabilities of the real time clock
59 in the platform. This includes the real time clock's resolution and accuracy.
60 All reported device capabilities are rounded up. This is an OPTIONAL argument.
61
62 Returns:
63
64 EFI_SUCEESS - The underlying GetSystemTime call occurred and returned
65 Note that in the NT32 emulation, the GetSystemTime call has no return value
66 thus you will always receive a EFI_SUCCESS on this.
67
68 **/
69 {
70
71 //
72 // Check parameter for null pointer
73 //
74 if (Time == NULL) {
75 return EFI_INVALID_PARAMETER;
76
77 }
78
79 gEmuThunk->GetTime (Time, Capabilities);
80
81 return EFI_SUCCESS;
82 }
83
84 EFI_STATUS
85 EFIAPI
86 EmuSetTime (
87 IN EFI_TIME *Time
88 )
89 /*++
90
91 Routine Description:
92 Service routine for RealTimeClockInstance->SetTime
93
94 Arguments:
95
96 Time - A pointer to storage containing the time and date information to
97 program into the real time clock.
98
99 Returns:
100
101 EFI_SUCEESS - The operation completed successfully.
102
103 EFI_INVALID_PARAMETER - One of the fields in Time is out of range.
104
105 EFI_DEVICE_ERROR - The operation could not be complete due to a device error.
106
107 **/
108 {
109 EFI_STATUS Status;
110
111 if (Time == NULL) {
112 return EFI_INVALID_PARAMETER;
113 }
114 //
115 // Make sure that the time fields are valid
116 //
117 Status = RtcTimeFieldsValid (Time);
118 if (EFI_ERROR (Status)) {
119 return Status;
120 }
121 return EFI_UNSUPPORTED;
122 }
123
124 EFI_STATUS
125 EFIAPI
126 EmuGetWakeupTime (
127 OUT BOOLEAN *Enabled,
128 OUT BOOLEAN *Pending,
129 OUT EFI_TIME *Time
130 )
131 /*++
132
133 Routine Description:
134 Service routine for RealTimeClockInstance->GetWakeupTime
135
136 Arguments:
137 This - Indicates the protocol instance structure.
138
139 Enabled - Indicates if the alarm is currently enabled or disabled.
140
141 Pending - Indicates if the alarm signal is pending and requires
142 acknowledgement.
143
144 Time - The current alarm setting.
145
146 Returns:
147
148 EFI_SUCEESS - The operation completed successfully.
149
150 EFI_DEVICE_ERROR - The operation could not be complete due to a device error.
151
152 EFI_UNSUPPORTED - The operation is not supported on this platform.
153
154 **/
155 {
156 return EFI_UNSUPPORTED;
157 }
158
159 EFI_STATUS
160 EFIAPI
161 EmuSetWakeupTime (
162 IN BOOLEAN Enable,
163 OUT EFI_TIME *Time
164 )
165 /*++
166
167 Routine Description:
168 Service routine for RealTimeClockInstance->SetWakeupTime
169
170 Arguments:
171
172 Enabled - Enable or disable the wakeup alarm.
173
174 Time - If enable is TRUE, the time to set the wakup alarm for.
175 If enable is FALSE, then this parameter is optional, and
176 may be NULL.
177
178 Returns:
179
180 EFI_SUCEESS - The operation completed successfully.
181
182 EFI_DEVICE_ERROR - The operation could not be complete due to a device error.
183
184 EFI_INVALID_PARAMETER - A field in Time is out of range.
185
186 EFI_UNSUPPORTED - The operation is not supported on this platform.
187
188 **/
189 {
190 return EFI_UNSUPPORTED;
191 }
192
193 EFI_STATUS
194 EFIAPI
195 InitializeRealTimeClock (
196 IN EFI_HANDLE ImageHandle,
197 IN EFI_SYSTEM_TABLE *SystemTable
198 )
199 /*++
200
201 Routine Description:
202 Install Real Time Clock Protocol
203
204 Arguments:
205 ImageHandle - Image Handle
206 SystemTable - Pointer to system table
207
208 Returns:
209
210 EFI_SUCEESS - Real Time Clock Services are installed into the Runtime Services Table
211
212 **/
213 {
214 EFI_STATUS Status;
215 EFI_HANDLE Handle;
216
217 SystemTable->RuntimeServices->GetTime = EmuGetTime;
218 SystemTable->RuntimeServices->SetTime = EmuSetTime;
219 SystemTable->RuntimeServices->GetWakeupTime = EmuGetWakeupTime;
220 SystemTable->RuntimeServices->SetWakeupTime = EmuSetWakeupTime;
221
222 Handle = NULL;
223 Status = gBS->InstallMultipleProtocolInterfaces (
224 &Handle,
225 &gEfiRealTimeClockArchProtocolGuid,
226 NULL,
227 NULL
228 );
229 return Status;
230 }
231
232 EFI_STATUS
233 RtcTimeFieldsValid (
234 IN EFI_TIME *Time
235 )
236 /*++
237
238 Routine Description:
239
240 Arguments:
241
242 Returns:
243 **/
244 {
245 if (Time->Year < 1998 ||
246 Time->Year > 2099 ||
247 Time->Month < 1 ||
248 Time->Month > 12 ||
249 (!DayValid (Time)) ||
250 Time->Hour > 23 ||
251 Time->Minute > 59 ||
252 Time->Second > 59 ||
253 Time->Nanosecond > 999999999 ||
254 (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
255 (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
256 ) {
257 return EFI_INVALID_PARAMETER;
258 }
259
260 return EFI_SUCCESS;
261 }
262
263 BOOLEAN
264 DayValid (
265 IN EFI_TIME *Time
266 )
267 {
268
269 STATIC const INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
270
271 if (Time->Day < 1 ||
272 Time->Day > DayOfMonth[Time->Month - 1] ||
273 (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
274 ) {
275 return FALSE;
276 }
277
278 return TRUE;
279 }
280
281 BOOLEAN
282 IsLeapYear (
283 IN EFI_TIME *Time
284 )
285 {
286 if (Time->Year % 4 == 0) {
287 if (Time->Year % 100 == 0) {
288 if (Time->Year % 400 == 0) {
289 return TRUE;
290 } else {
291 return FALSE;
292 }
293 } else {
294 return TRUE;
295 }
296 } else {
297 return FALSE;
298 }
299 }