/** Sets the current local time and date information. @param Time A pointer to the current time. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER A time field is out of range. @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. **/ EFI_STATUS EFIAPI LibSetTime ( IN EFI_TIME *Time ) { EFI_STATUS Status = EFI_SUCCESS; UINT32 EpochSeconds; // Check the input parameters are within the range specified by UEFI if (!IsTimeValid (Time)) { return EFI_INVALID_PARAMETER; } // Convert time to raw seconds EpochSeconds = EfiTimeToEpoch (Time); // Issue delayed write to time register RtcDelayedWrite (RTC_TIME_REG, EpochSeconds); return Status; }
/** Sets the system wakeup alarm clock time. @param Enabled Enable or disable the wakeup alarm. @param Time If Enable is TRUE, the time to set the wakeup alarm for. @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If Enable is FALSE, then the wakeup alarm was disabled. @retval EFI_INVALID_PARAMETER A time field is out of range. @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. **/ EFI_STATUS EFIAPI LibSetWakeupTime ( IN BOOLEAN Enabled, OUT EFI_TIME *Time ) { UINT32 WakeupSeconds; // Convert time to raw seconds WakeupSeconds = EfiTimeToEpoch (Time); // Issue delayed write to alarm register RtcDelayedWrite (RTC_ALARM_2_REG, WakeupSeconds); if (Enabled) { MmioWrite32 (mArmadaRtcBase + RTC_IRQ_2_CONFIG_REG, RTC_IRQ_ALARM_EN); } else { MmioWrite32 (mArmadaRtcBase + RTC_IRQ_2_CONFIG_REG, 0); } return EFI_SUCCESS; }
/** Sets the current local time and date information. @param Time A pointer to the current time. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER A time field is out of range. @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. **/ EFI_STATUS EFIAPI LibSetTime ( IN EFI_TIME *Time ) { EFI_STATUS Status; UINTN EpochSeconds; UINTN Temp; // Check the input parameters are within the range specified by UEFI if ((Time->Year < 1900) || (Time->Year > 9999) || (Time->Month < 1 ) || (Time->Month > 12 ) || (!DayValid (Time) ) || (Time->Hour > 23 ) || (Time->Minute > 59 ) || (Time->Second > 59 ) || (Time->Nanosecond > 999999999) || (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) || (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) ) { Status = EFI_INVALID_PARAMETER; goto EXIT; } // Because the PL031 is a 32-bit counter counting seconds, // the maximum time span is just over 136 years. // Time is stored in Unix Epoch format, so it starts in 1970, // Therefore it can not exceed the year 2106. if ((Time->Year < 1970) || (Time->Year >= 2106)) { Status = EFI_UNSUPPORTED; goto EXIT; } EpochSeconds = EfiTimeToEpoch (Time); // Adjust for the correct time zone, i.e. convert to UTC time zone if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { EpochSeconds -= Time->TimeZone * SEC_PER_MIN; } // TODO: Automatic Daylight activation // Adjust for the correct period if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { // Convert to un-adjusted time, i.e. fall back one hour EpochSeconds -= SEC_PER_HOUR; } ArmArchTimerReadReg(CntPct,&Temp); // UINT32 force convertion for PC-LINT mEpochDiff = EpochSeconds - Temp / (UINT32) PcdGet32(PcdArmArchTimerFreqInHz); // The accesses to Variable Services can be very slow, because we may be writing to Flash. // Do this after having set the RTC. // Save the current time zone information into non-volatile storage Status = mRT->SetVariable ( (CHAR16 *)mTimeZoneVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (Time->TimeZone), (VOID *)&(Time->TimeZone) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mTimeZoneVariableName, Status )); goto EXIT; } // Save the current daylight information into non-volatile storage Status = mRT->SetVariable ( (CHAR16 *)mDaylightVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(Time->Daylight), (VOID *)&(Time->Daylight) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mDaylightVariableName, Status )); goto EXIT; } EXIT: return Status; }
/** Sets the current local time and date information. @param Time A pointer to the current time. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER A time field is out of range. @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. **/ EFI_STATUS EFIAPI LibSetTime ( IN EFI_TIME *Time ) { EFI_STATUS Status; UINTN EpochSeconds; // Check the input parameters are within the range specified by UEFI if ((Time->Year < 1900) || (Time->Year > 9999) || (Time->Month < 1 ) || (Time->Month > 12 ) || (!DayValid (Time) ) || (Time->Hour > 23 ) || (Time->Minute > 59 ) || (Time->Second > 59 ) || (Time->Nanosecond > 999999999) || (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) || (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) ) { Status = EFI_INVALID_PARAMETER; goto EXIT; } // Because the PL031 is a 32-bit counter counting seconds, // the maximum time span is just over 136 years. // Time is stored in Unix Epoch format, so it starts in 1970, // Therefore it can not exceed the year 2106. if ((Time->Year < 1970) || (Time->Year >= 2106)) { Status = EFI_UNSUPPORTED; goto EXIT; } // Initialize the hardware if not already done if (!mPL031Initialized) { Status = InitializePL031 (); if (EFI_ERROR (Status)) { goto EXIT; } } EpochSeconds = EfiTimeToEpoch (Time); // Adjust for the correct time zone, i.e. convert to UTC time zone if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { EpochSeconds -= Time->TimeZone * SEC_PER_MIN; } // TODO: Automatic Daylight activation // Adjust for the correct period if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { // Convert to un-adjusted time, i.e. fall back one hour EpochSeconds -= SEC_PER_HOUR; } // On some platforms we may have access to a battery backed up hardware clock. // // If such RTC exists then it must be updated first, before the PL031, // to minimise any time drift. This is important because the battery backed-up // RTC maintains the master time for the platform across reboots. // // If such RTC does not exist then the following function returns UNSUPPORTED. Status = ArmPlatformSysConfigSet (SYS_CFG_RTC, EpochSeconds); if ((EFI_ERROR (Status)) && (Status != EFI_UNSUPPORTED)){ // Any status message except SUCCESS and UNSUPPORTED indicates a hardware failure. goto EXIT; } // Set the PL031 MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds); // The accesses to Variable Services can be very slow, because we may be writing to Flash. // Do this after having set the RTC. // Save the current time zone information into non-volatile storage Status = mRT->SetVariable ( (CHAR16 *)mTimeZoneVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (Time->TimeZone), (VOID *)&(Time->TimeZone) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mTimeZoneVariableName, Status )); goto EXIT; } // Save the current daylight information into non-volatile storage Status = mRT->SetVariable ( (CHAR16 *)mDaylightVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(Time->Daylight), (VOID *)&(Time->Daylight) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mDaylightVariableName, Status )); goto EXIT; } EXIT: return Status; }