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