Home | History | Annotate | Download | only in RealTimeClockRuntimeDxe
      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