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 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 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 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 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 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 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 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 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