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