EFI_STATUS RtcTimeFieldsValid ( IN EFI_TIME *Time ) /*++ Routine Description: Arguments: Returns: --*/ // TODO: Time - add argument and description to function comment // TODO: EFI_INVALID_PARAMETER - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { if (Time->Year < 1998 || Time->Year > 2099 || 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))) ) { return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/** Check the validity of all the fields of a data structure of type EFI_TIME @param[in] Time Pointer to a data structure of type EFI_TIME that defines a date and time @retval EFI_SUCCESS All date and time fields are valid @retval EFI_INVALID_PARAMETER At least one date or time field is not valid **/ EFI_STATUS RtcTimeFieldsValid ( IN EFI_TIME *Time ) { if ((Time->Year < 1998 ) || (Time->Year > 2099 ) || (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 ))) ) { return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
BOOLEAN TimeValid( IN EFI_TIME *Time ) { // Check the input parameters are within the range specified by UEFI if ((Time->Year < 2000) || (Time->Year > 2099) || (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))) ) { return FALSE; } return TRUE; }
/** 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; }