/** Returns the current time and date information, and the time-keeping capabilities of the hardware platform. @param Time A pointer to storage to receive a snapshot of the current time. @param Capabilities An optional pointer to a buffer to receive the real time clock device's capabilities. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Time is NULL. @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. **/ EFI_STATUS EFIAPI LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { ASSERT (Time != NULL); // // For now, there is nothing that we can do besides returning a bogus time, // as Xen's timekeeping uses a shared info page which cannot be shared // between UEFI and the OS // EpochToEfiTime(1421770011, Time); return EFI_SUCCESS; }
/** Returns the current time and date information, and the time-keeping capabilities of the hardware platform. @param Time A pointer to storage to receive a snapshot of the current time. @param Capabilities An optional pointer to a buffer to receive the real time clock device's capabilities. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Time is NULL. @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. **/ EFI_STATUS EFIAPI LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { EFI_STATUS Status = EFI_SUCCESS; UINT32 RegVal; RegVal = MmioRead32 (mArmadaRtcBase + RTC_TIME_REG); // Convert from internal 32-bit time to UEFI time EpochToEfiTime (RegVal, Time); Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; Time->Daylight = 0; return Status; }
/** Returns the current wakeup alarm clock setting. @param Enabled Indicates if the alarm is currently enabled or disabled. @param Pending Indicates if the alarm signal is pending and requires acknowledgement. @param Time The current alarm setting. @retval EFI_SUCCESS The alarm settings were returned. @retval EFI_INVALID_PARAMETER Any parameter is NULL. @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. **/ EFI_STATUS EFIAPI LibGetWakeupTime ( OUT BOOLEAN *Enabled, OUT BOOLEAN *Pending, OUT EFI_TIME *Time ) { UINT32 WakeupSeconds; *Enabled = MmioRead32 (mArmadaRtcBase + RTC_IRQ_2_CONFIG_REG) & RTC_IRQ_ALARM_EN; *Pending = MmioRead32 (mArmadaRtcBase + RTC_IRQ_STATUS_REG) & RTC_IRQ_ALARM_MASK; // Ack pending alarm if (Pending) { MmioWrite32 (mArmadaRtcBase + RTC_IRQ_STATUS_REG, RTC_IRQ_ALARM_MASK); } WakeupSeconds = MmioRead32 (mArmadaRtcBase + RTC_ALARM_2_REG); EpochToEfiTime (WakeupSeconds, Time); return EFI_SUCCESS; }
/** Returns the current time and date information, and the time-keeping capabilities of the hardware platform. @param Time A pointer to storage to receive a snapshot of the current time. @param Capabilities An optional pointer to a buffer to receive the real time clock device's capabilities. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Time is NULL. @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. **/ EFI_STATUS EFIAPI LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { EFI_STATUS Status = EFI_SUCCESS; UINT64 Temp; UINT32 EpochSeconds; INT16 TimeZone = 0; UINT8 Daylight = 0; UINTN Size; // Ensure Time is a valid pointer if (Time == NULL) { return EFI_INVALID_PARAMETER; } ArmArchTimerReadReg(CntPct,&Temp); // UINT32 force convertion for PC-LINT EpochSeconds = mEpochDiff + Temp / (UINT32) PcdGet32(PcdArmArchTimerFreqInHz); // Get the current time zone information from non-volatile storage Size = sizeof (TimeZone); Status = mRT->GetVariable ( (CHAR16 *)mTimeZoneVariableName, &gEfiCallerIdGuid, NULL, &Size, (VOID *)&TimeZone ); if (EFI_ERROR (Status)) { ASSERT(Status != EFI_INVALID_PARAMETER); ASSERT(Status != EFI_BUFFER_TOO_SMALL); if (Status != EFI_NOT_FOUND) goto EXIT; // The time zone variable does not exist in non-volatile storage, so create it. Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; // Store it Status = mRT->SetVariable ( (CHAR16 *)mTimeZoneVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, Size, (VOID *)&(Time->TimeZone) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mTimeZoneVariableName, Status )); goto EXIT; } } else { // Got the time zone Time->TimeZone = TimeZone; // Check TimeZone bounds: -1440 to 1440 or 2047 if (((Time->TimeZone < -1440) || (Time->TimeZone > 1440)) && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) { Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; } // Adjust for the correct time zone if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { EpochSeconds += Time->TimeZone * SEC_PER_MIN; } } // Get the current daylight information from non-volatile storage Size = sizeof (Daylight); Status = mRT->GetVariable ( (CHAR16 *)mDaylightVariableName, &gEfiCallerIdGuid, NULL, &Size, (VOID *)&Daylight ); if (EFI_ERROR (Status)) { ASSERT(Status != EFI_INVALID_PARAMETER); ASSERT(Status != EFI_BUFFER_TOO_SMALL); if (Status != EFI_NOT_FOUND) goto EXIT; // The daylight variable does not exist in non-volatile storage, so create it. Time->Daylight = 0; // Store it Status = mRT->SetVariable ( (CHAR16 *)mDaylightVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, Size, (VOID *)&(Time->Daylight) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mDaylightVariableName, Status )); goto EXIT; } } else { // Got the daylight information Time->Daylight = Daylight; // Adjust for the correct period if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { // Convert to adjusted time, i.e. spring forwards one hour EpochSeconds += SEC_PER_HOUR; } } // Convert from internal 32-bit time to UEFI time EpochToEfiTime (EpochSeconds, Time); // Update the Capabilities info if (Capabilities != NULL) { Capabilities->Resolution = 1; // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000 Capabilities->Accuracy = PcdGet32 (PcdArmArchTimerFreqInHz); // FALSE: Setting the time does not clear the values below the resolution level Capabilities->SetsToZero = FALSE; } EXIT: return Status; }
/** Returns the current time and date information, and the time-keeping capabilities of the hardware platform. @param Time A pointer to storage to receive a snapshot of the current time. @param Capabilities An optional pointer to a buffer to receive the real time clock device's capabilities. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Time is NULL. @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. **/ EFI_STATUS EFIAPI LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { EFI_STATUS Status = EFI_SUCCESS; UINT32 EpochSeconds; INT16 TimeZone; UINT8 Daylight; UINTN Size; // Initialize the hardware if not already done if (!mPL031Initialized) { Status = InitializePL031 (); if (EFI_ERROR (Status)) { goto EXIT; } } // Snapshot the time as early in the function call as possible // On some platforms we may have access to a battery backed up hardware clock. // If such RTC exists try to use it first. Status = ArmPlatformSysConfigGet (SYS_CFG_RTC, &EpochSeconds); if (Status == EFI_UNSUPPORTED) { // Battery backed up hardware RTC does not exist, revert to PL031 EpochSeconds = MmioRead32 (mPL031RtcBase + PL031_RTC_DR_DATA_REGISTER); Status = EFI_SUCCESS; } else if (EFI_ERROR (Status)) { // Battery backed up hardware RTC exists but could not be read due to error. Abort. goto EXIT; } else { // Battery backed up hardware RTC exists and we read the time correctly from it. // Now sync the PL031 to the new time. MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds); } // Ensure Time is a valid pointer if (Time == NULL) { Status = EFI_INVALID_PARAMETER; goto EXIT; } // Get the current time zone information from non-volatile storage Size = sizeof (TimeZone); Status = mRT->GetVariable ( (CHAR16 *)mTimeZoneVariableName, &gEfiCallerIdGuid, NULL, &Size, (VOID *)&TimeZone ); if (EFI_ERROR (Status)) { ASSERT(Status != EFI_INVALID_PARAMETER); ASSERT(Status != EFI_BUFFER_TOO_SMALL); if (Status != EFI_NOT_FOUND) goto EXIT; // The time zone variable does not exist in non-volatile storage, so create it. Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; // Store it Status = mRT->SetVariable ( (CHAR16 *)mTimeZoneVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, Size, (VOID *)&(Time->TimeZone) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mTimeZoneVariableName, Status )); goto EXIT; } } else { // Got the time zone Time->TimeZone = TimeZone; // Check TimeZone bounds: -1440 to 1440 or 2047 if (((Time->TimeZone < -1440) || (Time->TimeZone > 1440)) && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) { Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; } // Adjust for the correct time zone if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { EpochSeconds += Time->TimeZone * SEC_PER_MIN; } } // Get the current daylight information from non-volatile storage Size = sizeof (Daylight); Status = mRT->GetVariable ( (CHAR16 *)mDaylightVariableName, &gEfiCallerIdGuid, NULL, &Size, (VOID *)&Daylight ); if (EFI_ERROR (Status)) { ASSERT(Status != EFI_INVALID_PARAMETER); ASSERT(Status != EFI_BUFFER_TOO_SMALL); if (Status != EFI_NOT_FOUND) goto EXIT; // The daylight variable does not exist in non-volatile storage, so create it. Time->Daylight = 0; // Store it Status = mRT->SetVariable ( (CHAR16 *)mDaylightVariableName, &gEfiCallerIdGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, Size, (VOID *)&(Time->Daylight) ); if (EFI_ERROR (Status)) { DEBUG (( EFI_D_ERROR, "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n", mDaylightVariableName, Status )); goto EXIT; } } else { // Got the daylight information Time->Daylight = Daylight; // Adjust for the correct period if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { // Convert to adjusted time, i.e. spring forwards one hour EpochSeconds += SEC_PER_HOUR; } } // Convert from internal 32-bit time to UEFI time EpochToEfiTime (EpochSeconds, Time); // Update the Capabilities info if (Capabilities != NULL) { // PL031 runs at frequency 1Hz Capabilities->Resolution = PL031_COUNTS_PER_SECOND; // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000 Capabilities->Accuracy = (UINT32)PcdGet32 (PcdPL031RtcPpmAccuracy); // FALSE: Setting the time does not clear the values below the resolution level Capabilities->SetsToZero = FALSE; } EXIT: return Status; }