1 /**@file
2
3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 RealTimeClock.c
15
16 Abstract:
17
18 NT Emulation Architectural Protocol Driver as defined in Tiano
19
20 **/
21
22 #include <Uefi.h>
23 #include <WinNtDxe.h>
24 #include <Protocol/RealTimeClock.h>
25 #include <Library/DebugLib.h>
26 #include <Library/UefiDriverEntryPoint.h>
27 #include <Library/WinNtLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29
30
31 BOOLEAN
32 DayValid (
33 IN EFI_TIME *Time
34 );
35
36 BOOLEAN
37 IsLeapYear (
38 IN EFI_TIME *Time
39 );
40
41 EFI_STATUS
42 RtcTimeFieldsValid (
43 IN EFI_TIME *Time
44 );
45
46 EFI_STATUS
47 EFIAPI
48 InitializeRealTimeClock (
49 IN EFI_HANDLE ImageHandle,
50 IN EFI_SYSTEM_TABLE *SystemTable
51 );
52
53 EFI_STATUS
54 EFIAPI
WinNtGetTime(OUT EFI_TIME * Time,OUT EFI_TIME_CAPABILITIES * Capabilities OPTIONAL)55 WinNtGetTime (
56 OUT EFI_TIME *Time,
57 OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
58 )
59 /*++
60
61 Routine Description:
62 Service routine for RealTimeClockInstance->GetTime
63
64 Arguments:
65
66 Time - A pointer to storage that will receive a snapshot of the current time.
67
68 Capabilities - A pointer to storage that will receive the capabilities of the real time clock
69 in the platform. This includes the real time clock's resolution and accuracy.
70 All reported device capabilities are rounded up. This is an OPTIONAL argument.
71
72 Returns:
73
74 EFI_SUCEESS - The underlying GetSystemTime call occurred and returned
75 Note that in the NT32 emulation, the GetSystemTime call has no return value
76 thus you will always receive a EFI_SUCCESS on this.
77
78 --*/
79 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
80 {
81 SYSTEMTIME SystemTime;
82 TIME_ZONE_INFORMATION TimeZone;
83
84 //
85 // Check parameter for null pointer
86 //
87 if (Time == NULL) {
88 return EFI_INVALID_PARAMETER;
89
90 }
91
92 gWinNt->GetLocalTime (&SystemTime);
93 gWinNt->GetTimeZoneInformation (&TimeZone);
94
95 Time->Year = (UINT16) SystemTime.wYear;
96 Time->Month = (UINT8) SystemTime.wMonth;
97 Time->Day = (UINT8) SystemTime.wDay;
98 Time->Hour = (UINT8) SystemTime.wHour;
99 Time->Minute = (UINT8) SystemTime.wMinute;
100 Time->Second = (UINT8) SystemTime.wSecond;
101 Time->Nanosecond = (UINT32) (SystemTime.wMilliseconds * 1000000);
102 Time->TimeZone = (INT16) TimeZone.Bias;
103
104 if (Capabilities != NULL) {
105 Capabilities->Resolution = 1;
106 Capabilities->Accuracy = 50000000;
107 Capabilities->SetsToZero = FALSE;
108 }
109
110 Time->Daylight = 0;
111 if (TimeZone.StandardDate.wMonth) {
112 Time->Daylight = (UINT8) TimeZone.StandardDate.wMonth;
113 }
114
115 return EFI_SUCCESS;
116 }
117
118 EFI_STATUS
119 EFIAPI
WinNtSetTime(IN EFI_TIME * Time)120 WinNtSetTime (
121 IN EFI_TIME *Time
122 )
123 /*++
124
125 Routine Description:
126 Service routine for RealTimeClockInstance->SetTime
127
128 Arguments:
129
130 Time - A pointer to storage containing the time and date information to
131 program into the real time clock.
132
133 Returns:
134
135 EFI_SUCEESS - The operation completed successfully.
136
137 EFI_INVALID_PARAMETER - One of the fields in Time is out of range.
138
139 EFI_DEVICE_ERROR - The operation could not be complete due to a device error.
140
141 --*/
142 // TODO: EFI_SUCCESS - add return value to function comment
143 {
144 TIME_ZONE_INFORMATION TimeZone;
145 EFI_STATUS Status;
146 SYSTEMTIME SystemTime;
147 BOOL Flag;
148
149 if (Time == NULL) {
150 return EFI_INVALID_PARAMETER;
151 }
152 //
153 // Make sure that the time fields are valid
154 //
155 Status = RtcTimeFieldsValid (Time);
156 if (EFI_ERROR (Status)) {
157 return Status;
158 }
159 //
160 // Set Daylight savings time information and Time Zone
161 //
162 gWinNt->GetTimeZoneInformation (&TimeZone);
163 TimeZone.StandardDate.wMonth = Time->Daylight;
164 TimeZone.Bias = Time->TimeZone;
165 Flag = gWinNt->SetTimeZoneInformation (&TimeZone);
166 if (!Flag) {
167 return EFI_DEVICE_ERROR;
168 }
169
170 SystemTime.wYear = Time->Year;
171 SystemTime.wMonth = Time->Month;
172 SystemTime.wDay = Time->Day;
173 SystemTime.wHour = Time->Hour;
174 SystemTime.wMinute = Time->Minute;
175 SystemTime.wSecond = Time->Second;
176 SystemTime.wMilliseconds = (INT16) (Time->Nanosecond / 1000000);
177
178 Flag = gWinNt->SetLocalTime (&SystemTime);
179
180 if (!Flag) {
181 return EFI_DEVICE_ERROR;
182 } else {
183 return EFI_SUCCESS;
184 }
185 }
186
187 EFI_STATUS
188 EFIAPI
WinNtGetWakeupTime(OUT BOOLEAN * Enabled,OUT BOOLEAN * Pending,OUT EFI_TIME * Time)189 WinNtGetWakeupTime (
190 OUT BOOLEAN *Enabled,
191 OUT BOOLEAN *Pending,
192 OUT EFI_TIME *Time
193 )
194 /*++
195
196 Routine Description:
197 Service routine for RealTimeClockInstance->GetWakeupTime
198
199 Arguments:
200 This - Indicates the protocol instance structure.
201
202 Enabled - Indicates if the alarm is currently enabled or disabled.
203
204 Pending - Indicates if the alarm signal is pending and requires
205 acknowledgement.
206
207 Time - The current alarm setting.
208
209 Returns:
210
211 EFI_SUCEESS - The operation completed successfully.
212
213 EFI_DEVICE_ERROR - The operation could not be complete due to a device error.
214
215 EFI_UNSUPPORTED - The operation is not supported on this platform.
216
217 --*/
218 {
219 return EFI_UNSUPPORTED;
220 }
221
222 EFI_STATUS
223 EFIAPI
WinNtSetWakeupTime(IN BOOLEAN Enable,OUT EFI_TIME * Time)224 WinNtSetWakeupTime (
225 IN BOOLEAN Enable,
226 OUT EFI_TIME *Time
227 )
228 /*++
229
230 Routine Description:
231 Service routine for RealTimeClockInstance->SetWakeupTime
232
233 Arguments:
234
235 Enabled - Enable or disable the wakeup alarm.
236
237 Time - If enable is TRUE, the time to set the wakup alarm for.
238 If enable is FALSE, then this parameter is optional, and
239 may be NULL.
240
241 Returns:
242
243 EFI_SUCEESS - The operation completed successfully.
244
245 EFI_DEVICE_ERROR - The operation could not be complete due to a device error.
246
247 EFI_INVALID_PARAMETER - A field in Time is out of range.
248
249 EFI_UNSUPPORTED - The operation is not supported on this platform.
250
251 --*/
252 {
253 return EFI_UNSUPPORTED;
254 }
255
256 EFI_STATUS
257 EFIAPI
InitializeRealTimeClock(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)258 InitializeRealTimeClock (
259 IN EFI_HANDLE ImageHandle,
260 IN EFI_SYSTEM_TABLE *SystemTable
261 )
262 /*++
263
264 Routine Description:
265 Install Real Time Clock Protocol
266
267 Arguments:
268 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
269
270 Returns:
271
272 EFI_SUCEESS - Real Time Clock Services are installed into the Runtime Services Table
273
274 --*/
275 // TODO: ImageHandle - add argument and description to function comment
276 // TODO: SystemTable - add argument and description to function comment
277 {
278 EFI_STATUS Status;
279 EFI_HANDLE Handle;
280
281
282 SystemTable->RuntimeServices->GetTime = WinNtGetTime;
283 SystemTable->RuntimeServices->SetTime = WinNtSetTime;
284 SystemTable->RuntimeServices->GetWakeupTime = WinNtGetWakeupTime;
285 SystemTable->RuntimeServices->SetWakeupTime = WinNtSetWakeupTime;
286
287 Handle = NULL;
288 Status = gBS->InstallMultipleProtocolInterfaces (
289 &Handle,
290 &gEfiRealTimeClockArchProtocolGuid,
291 NULL,
292 NULL
293 );
294 return Status;
295 }
296
297 EFI_STATUS
RtcTimeFieldsValid(IN EFI_TIME * Time)298 RtcTimeFieldsValid (
299 IN EFI_TIME *Time
300 )
301 /*++
302
303 Routine Description:
304
305 Arguments:
306
307 Returns:
308 --*/
309 // TODO: Time - add argument and description to function comment
310 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
311 // TODO: EFI_SUCCESS - add return value to function comment
312 {
313 if (Time->Year < 1998 ||
314 Time->Year > 2099 ||
315 Time->Month < 1 ||
316 Time->Month > 12 ||
317 (!DayValid (Time)) ||
318 Time->Hour > 23 ||
319 Time->Minute > 59 ||
320 Time->Second > 59 ||
321 Time->Nanosecond > 999999999 ||
322 (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
323 (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
324 ) {
325 return EFI_INVALID_PARAMETER;
326 }
327
328 return EFI_SUCCESS;
329 }
330
331 BOOLEAN
DayValid(IN EFI_TIME * Time)332 DayValid (
333 IN EFI_TIME *Time
334 )
335 /*++
336
337 Routine Description:
338
339 TODO: Add function description
340
341 Arguments:
342
343 Time - TODO: add argument description
344
345 Returns:
346
347 TODO: add return values
348
349 --*/
350 {
351
352 INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
353
354 if (Time->Day < 1 ||
355 Time->Day > DayOfMonth[Time->Month - 1] ||
356 (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
357 ) {
358 return FALSE;
359 }
360
361 return TRUE;
362 }
363
364 BOOLEAN
IsLeapYear(IN EFI_TIME * Time)365 IsLeapYear (
366 IN EFI_TIME *Time
367 )
368 /*++
369
370 Routine Description:
371
372 TODO: Add function description
373
374 Arguments:
375
376 Time - TODO: add argument description
377
378 Returns:
379
380 TODO: add return values
381
382 --*/
383 {
384 if (Time->Year % 4 == 0) {
385 if (Time->Year % 100 == 0) {
386 if (Time->Year % 400 == 0) {
387 return TRUE;
388 } else {
389 return FALSE;
390 }
391 } else {
392 return TRUE;
393 }
394 } else {
395 return FALSE;
396 }
397 }
398