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