Currently this driver does not support runtime virtual calling.\r
\r
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
\r
**/\r
\r
-#include <Base.h>\r
#include <Uefi.h>\r
#include <PiDxe.h>\r
#include <Library/BaseLib.h>\r
#include <Library/IoLib.h>\r
#include <Library/RealTimeClockLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
#include <Library/ArmPlatformSysConfigLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+\r
#include <Protocol/RealTimeClock.h>\r
+\r
#include <Guid/GlobalVariable.h>\r
-#include <ArmPlatform.h>\r
+#include <Guid/EventGroup.h>\r
+\r
#include <Drivers/PL031RealTimeClock.h>\r
\r
-CHAR16 mTimeZoneVariableName[] = L"PL031_TimeZone";\r
-CHAR16 mDaylightVariableName[] = L"PL031_Daylight";\r
-BOOLEAN mPL031Initialized = FALSE;\r
+#include <ArmPlatform.h>\r
+\r
+STATIC CONST CHAR16 mTimeZoneVariableName[] = L"PL031RtcTimeZone";\r
+STATIC CONST CHAR16 mDaylightVariableName[] = L"PL031RtcDaylight";\r
+STATIC BOOLEAN mPL031Initialized = FALSE;\r
+STATIC EFI_EVENT mRtcVirtualAddrChangeEvent;\r
+STATIC UINTN mPL031RtcBase;\r
\r
EFI_STATUS\r
IdentifyPL031 (\r
EFI_STATUS Status;\r
\r
// Check if this is a PrimeCell Peripheral\r
- if( ( MmioRead8( PL031_RTC_PCELL_ID0 ) != 0x0D )\r
- || ( MmioRead8( PL031_RTC_PCELL_ID1 ) != 0xF0 )\r
- || ( MmioRead8( PL031_RTC_PCELL_ID2 ) != 0x05 )\r
- || ( MmioRead8( PL031_RTC_PCELL_ID3 ) != 0xB1 ) ) {\r
+ if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID0) != 0x0D)\r
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID1) != 0xF0)\r
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID2) != 0x05)\r
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID3) != 0xB1)) {\r
Status = EFI_NOT_FOUND;\r
goto EXIT;\r
}\r
\r
- // Check if this PrimeCell Peripheral is the SP805 Watchdog Timer\r
- if( ( MmioRead8( PL031_RTC_PERIPH_ID0 ) != 0x31 )\r
- || ( MmioRead8( PL031_RTC_PERIPH_ID1 ) != 0x10 )\r
- || (( MmioRead8( PL031_RTC_PERIPH_ID2 ) & 0xF) != 0x04 )\r
- || ( MmioRead8( PL031_RTC_PERIPH_ID3 ) != 0x00 ) ) {\r
+ // Check if this PrimeCell Peripheral is the PL031 Real Time Clock\r
+ if ( (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID0) != 0x31)\r
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID1) != 0x10)\r
+ || ((MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)\r
+ || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID3) != 0x00)) {\r
Status = EFI_NOT_FOUND;\r
goto EXIT;\r
}\r
}\r
\r
// Ensure interrupts are masked. We do not want RTC interrupts in UEFI\r
- if ( (MmioRead32( PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER ) & PL031_SET_IRQ_MASK) != PL031_SET_IRQ_MASK ) {\r
- MmioOr32( PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK);\r
+ if ((MmioRead32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER) & PL031_SET_IRQ_MASK) != PL031_SET_IRQ_MASK) {\r
+ MmioOr32 (mPL031RtcBase + PL031_RTC_IMSC_IRQ_MASK_SET_CLEAR_REGISTER, PL031_SET_IRQ_MASK);\r
}\r
\r
// Clear any existing interrupts\r
- if ( (MmioRead32( PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER ) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED ) {\r
- MmioOr32( PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);\r
+ if ((MmioRead32 (mPL031RtcBase + PL031_RTC_RIS_RAW_IRQ_STATUS_REGISTER) & PL031_IRQ_TRIGGERED) == PL031_IRQ_TRIGGERED) {\r
+ MmioOr32 (mPL031RtcBase + PL031_RTC_ICR_IRQ_CLEAR_REGISTER, PL031_CLEAR_IRQ);\r
}\r
\r
// Start the clock counter\r
- if ( (MmioRead32( PL031_RTC_CR_CONTROL_REGISTER ) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED ) {\r
- MmioOr32( PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);\r
+ if ((MmioRead32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER) & PL031_RTC_ENABLED) != PL031_RTC_ENABLED) {\r
+ MmioOr32 (mPL031RtcBase + PL031_RTC_CR_CONTROL_REGISTER, PL031_RTC_ENABLED);\r
}\r
\r
mPL031Initialized = TRUE;\r
UINTN ss;\r
UINTN J;\r
\r
- if( Time->Daylight == TRUE) {\r
-\r
- }\r
-\r
J = (EpochSeconds / 86400) + 2440588;\r
j = J + 32044;\r
g = j / 146097;\r
\r
JulianDate = Time->Day + ((153*m + 2)/5) + (365*y) + (y/4) - (y/100) + (y/400) - 32045;\r
\r
- ASSERT( JulianDate > EPOCH_JULIAN_DATE );\r
+ ASSERT (JulianDate >= EPOCH_JULIAN_DATE);\r
EpochDays = JulianDate - EPOCH_JULIAN_DATE;\r
\r
EpochSeconds = (EpochDays * SEC_PER_DAY) + ((UINTN)Time->Hour * SEC_PER_HOUR) + (Time->Minute * SEC_PER_MIN) + Time->Second;\r
if (Time->Day < 1 ||\r
Time->Day > DayOfMonth[Time->Month - 1] ||\r
(Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))\r
- ) {\r
+ ) {\r
return FALSE;\r
}\r
\r
Returns the current time and date information, and the time-keeping capabilities\r
of the hardware platform.\r
\r
- @param Time A pointer to storage to receive a snapshot of the current time.\r
- @param Capabilities An optional pointer to a buffer to receive the real time clock\r
- device's capabilities.\r
+ @param Time A pointer to storage to receive a snapshot of the current time.\r
+ @param Capabilities An optional pointer to a buffer to receive the real time clock\r
+ device's capabilities.\r
\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_INVALID_PARAMETER Time is NULL.\r
- @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Time is NULL.\r
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.\r
+ @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure.\r
\r
**/\r
EFI_STATUS\r
)\r
{\r
EFI_STATUS Status = EFI_SUCCESS;\r
- UINTN EpochSeconds;\r
- INT16 *TimeZone = 0;\r
- UINTN *Daylight = 0;\r
+ UINT32 EpochSeconds;\r
+ INT16 TimeZone;\r
+ UINT8 Daylight;\r
+ UINTN Size;\r
\r
// Initialize the hardware if not already done\r
- if( !mPL031Initialized ) {\r
- Status = InitializePL031();\r
+ if (!mPL031Initialized) {\r
+ Status = InitializePL031 ();\r
if (EFI_ERROR (Status)) {\r
goto EXIT;\r
}\r
Status = ArmPlatformSysConfigGet (SYS_CFG_RTC, &EpochSeconds);\r
if (Status == EFI_UNSUPPORTED) {\r
// Battery backed up hardware RTC does not exist, revert to PL031\r
- EpochSeconds = MmioRead32( PL031_RTC_DR_DATA_REGISTER );\r
+ EpochSeconds = MmioRead32 (mPL031RtcBase + PL031_RTC_DR_DATA_REGISTER);\r
Status = EFI_SUCCESS;\r
} else if (EFI_ERROR (Status)) {\r
// Battery backed up hardware RTC exists but could not be read due to error. Abort.\r
} else {\r
// Battery backed up hardware RTC exists and we read the time correctly from it.\r
// Now sync the PL031 to the new time.\r
- MmioWrite32( PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
+ MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
}\r
\r
// Ensure Time is a valid pointer\r
- if( Time == NULL ) {\r
+ if (Time == NULL) {\r
Status = EFI_INVALID_PARAMETER;\r
goto EXIT;\r
}\r
\r
// Get the current time zone information from non-volatile storage\r
- TimeZone = (INT16 *)GetVariable(mTimeZoneVariableName, &gEfiGlobalVariableGuid);\r
+ Size = sizeof (TimeZone);\r
+ Status = gRT->GetVariable (\r
+ (CHAR16 *)mTimeZoneVariableName,\r
+ &gEfiCallerIdGuid,\r
+ NULL,\r
+ &Size,\r
+ (VOID *)&TimeZone\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT(Status != EFI_INVALID_PARAMETER);\r
+ ASSERT(Status != EFI_BUFFER_TOO_SMALL);\r
+\r
+ if (Status != EFI_NOT_FOUND)\r
+ goto EXIT;\r
\r
- if( TimeZone == NULL ) {\r
// The time zone variable does not exist in non-volatile storage, so create it.\r
Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
// Store it\r
Status = gRT->SetVariable (\r
- mTimeZoneVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof(Time->TimeZone),\r
- &(Time->TimeZone)\r
- );\r
+ (CHAR16 *)mTimeZoneVariableName,\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ Size,\r
+ (VOID *)&(Time->TimeZone)\r
+ );\r
if (EFI_ERROR (Status)) {\r
- DEBUG((EFI_D_ERROR,"LibGetTime: ERROR: TimeZone\n"));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",\r
+ mTimeZoneVariableName,\r
+ Status\r
+ ));\r
goto EXIT;\r
}\r
} else {\r
// Got the time zone\r
- Time->TimeZone = *TimeZone;\r
- FreePool(TimeZone);\r
+ Time->TimeZone = TimeZone;\r
\r
// Check TimeZone bounds: -1440 to 1440 or 2047\r
- if( (( Time->TimeZone < -1440 ) || ( Time->TimeZone > 1440 ))\r
- && ( Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) ) {\r
+ if (((Time->TimeZone < -1440) || (Time->TimeZone > 1440))\r
+ && (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {\r
Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
}\r
\r
// Adjust for the correct time zone\r
- if( Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE ) {\r
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {\r
EpochSeconds += Time->TimeZone * SEC_PER_MIN;\r
}\r
}\r
\r
// Get the current daylight information from non-volatile storage\r
- Daylight = (UINTN *)GetVariable(mDaylightVariableName, &gEfiGlobalVariableGuid);\r
+ Size = sizeof (Daylight);\r
+ Status = gRT->GetVariable (\r
+ (CHAR16 *)mDaylightVariableName,\r
+ &gEfiCallerIdGuid,\r
+ NULL,\r
+ &Size,\r
+ (VOID *)&Daylight\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT(Status != EFI_INVALID_PARAMETER);\r
+ ASSERT(Status != EFI_BUFFER_TOO_SMALL);\r
+\r
+ if (Status != EFI_NOT_FOUND)\r
+ goto EXIT;\r
\r
- if( Daylight == NULL ) {\r
// The daylight variable does not exist in non-volatile storage, so create it.\r
Time->Daylight = 0;\r
// Store it\r
Status = gRT->SetVariable (\r
- mDaylightVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof(Time->Daylight),\r
- &(Time->Daylight)\r
- );\r
+ (CHAR16 *)mDaylightVariableName,\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ Size,\r
+ (VOID *)&(Time->Daylight)\r
+ );\r
if (EFI_ERROR (Status)) {\r
- DEBUG((EFI_D_ERROR,"LibGetTime: ERROR: Daylight\n"));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "LibGetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",\r
+ mDaylightVariableName,\r
+ Status\r
+ ));\r
goto EXIT;\r
}\r
} else {\r
// Got the daylight information\r
- Time->Daylight = *Daylight;\r
- FreePool(Daylight);\r
+ Time->Daylight = Daylight;\r
\r
// Adjust for the correct period\r
- if( (Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT ) {\r
+ if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {\r
// Convert to adjusted time, i.e. spring forwards one hour\r
EpochSeconds += SEC_PER_HOUR;\r
}\r
}\r
\r
// Convert from internal 32-bit time to UEFI time\r
- EpochToEfiTime( EpochSeconds, Time );\r
+ EpochToEfiTime (EpochSeconds, Time);\r
\r
// Update the Capabilities info\r
- if( Capabilities != NULL ) {\r
- Capabilities->Resolution = PL031_COUNTS_PER_SECOND; /* PL031 runs at frequency 1Hz */\r
- Capabilities->Accuracy = PL031_PPM_ACCURACY; /* Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000 */\r
- Capabilities->SetsToZero = FALSE; /* FALSE: Setting the time does not clear the values below the resolution level */\r
+ if (Capabilities != NULL) {\r
+ // PL031 runs at frequency 1Hz\r
+ Capabilities->Resolution = PL031_COUNTS_PER_SECOND;\r
+ // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000\r
+ Capabilities->Accuracy = (UINT32)PcdGet32 (PcdPL031RtcPpmAccuracy);\r
+ // FALSE: Setting the time does not clear the values below the resolution level\r
+ Capabilities->SetsToZero = FALSE;\r
}\r
\r
EXIT:\r
EFI_STATUS Status;\r
UINTN EpochSeconds;\r
\r
+ // Check the input parameters are within the range specified by UEFI\r
+ if ((Time->Year < 1900) ||\r
+ (Time->Year > 9999) ||\r
+ (Time->Month < 1 ) ||\r
+ (Time->Month > 12 ) ||\r
+ (!DayValid (Time) ) ||\r
+ (Time->Hour > 23 ) ||\r
+ (Time->Minute > 59 ) ||\r
+ (Time->Second > 59 ) ||\r
+ (Time->Nanosecond > 999999999) ||\r
+ (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||\r
+ (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))\r
+ ) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto EXIT;\r
+ }\r
+\r
// Because the PL031 is a 32-bit counter counting seconds,\r
// the maximum time span is just over 136 years.\r
// Time is stored in Unix Epoch format, so it starts in 1970,\r
// Therefore it can not exceed the year 2106.\r
- // This is not a problem for UEFI, as the current spec limits the years\r
- // to the range 1998 .. 2011\r
-\r
- // Check the input parameters' range.\r
- if ( ( Time->Year < 1998 ) ||\r
- ( Time->Year > 2099 ) ||\r
- ( Time->Month < 1 ) ||\r
- ( Time->Month > 12 ) ||\r
- (!DayValid (Time) ) ||\r
- ( Time->Hour > 23 ) ||\r
- ( Time->Minute > 59 ) ||\r
- ( Time->Second > 59 ) ||\r
- ( Time->Nanosecond > 999999999 ) ||\r
- ( !((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440))) ) ||\r
- ( Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)) )\r
- ) {\r
- Status = EFI_INVALID_PARAMETER;\r
+ if ((Time->Year < 1970) || (Time->Year >= 2106)) {\r
+ Status = EFI_UNSUPPORTED;\r
goto EXIT;\r
}\r
\r
// Initialize the hardware if not already done\r
- if( !mPL031Initialized ) {\r
- Status = InitializePL031();\r
+ if (!mPL031Initialized) {\r
+ Status = InitializePL031 ();\r
if (EFI_ERROR (Status)) {\r
goto EXIT;\r
}\r
}\r
\r
- EpochSeconds = EfiTimeToEpoch( Time );\r
+ EpochSeconds = EfiTimeToEpoch (Time);\r
\r
// Adjust for the correct time zone, i.e. convert to UTC time zone\r
- if( Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE ) {\r
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {\r
EpochSeconds -= Time->TimeZone * SEC_PER_MIN;\r
}\r
\r
// TODO: Automatic Daylight activation\r
\r
// Adjust for the correct period\r
- if( (Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT ) {\r
+ if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {\r
// Convert to un-adjusted time, i.e. fall back one hour\r
EpochSeconds -= SEC_PER_HOUR;\r
}\r
\r
\r
// Set the PL031\r
- MmioWrite32( PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
+ MmioWrite32 (mPL031RtcBase + PL031_RTC_LR_LOAD_REGISTER, EpochSeconds);\r
\r
// The accesses to Variable Services can be very slow, because we may be writing to Flash.\r
// Do this after having set the RTC.\r
\r
// Save the current time zone information into non-volatile storage\r
Status = gRT->SetVariable (\r
- mTimeZoneVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof(Time->TimeZone),\r
- &(Time->TimeZone)\r
- );\r
+ (CHAR16 *)mTimeZoneVariableName,\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (Time->TimeZone),\r
+ (VOID *)&(Time->TimeZone)\r
+ );\r
if (EFI_ERROR (Status)) {\r
- DEBUG((EFI_D_ERROR,"LibSetTime: ERROR: TimeZone\n"));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",\r
+ mTimeZoneVariableName,\r
+ Status\r
+ ));\r
goto EXIT;\r
}\r
\r
// Save the current daylight information into non-volatile storage\r
Status = gRT->SetVariable (\r
- mDaylightVariableName,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof(Time->Daylight),\r
- &(Time->Daylight)\r
- );\r
+ (CHAR16 *)mDaylightVariableName,\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof(Time->Daylight),\r
+ (VOID *)&(Time->Daylight)\r
+ );\r
if (EFI_ERROR (Status)) {\r
- DEBUG((EFI_D_ERROR,"LibSetTime: ERROR: Daylight\n"));\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "LibSetTime: Failed to save %s variable to non-volatile storage, Status = %r\n",\r
+ mDaylightVariableName,\r
+ Status\r
+ ));\r
goto EXIT;\r
}\r
\r
return EFI_UNSUPPORTED;\r
}\r
\r
+/**\r
+ Fixup internal data so that EFI can be call in virtual mode.\r
+ Call the passed in Child Notify event and convert any pointers in\r
+ lib to virtual mode.\r
\r
+ @param[in] Event The Event that is being processed\r
+ @param[in] Context Event Context\r
+**/\r
+VOID\r
+EFIAPI\r
+LibRtcVirtualNotifyEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Only needed if you are going to support the OS calling RTC functions in virtual mode.\r
+ // You will need to call EfiConvertPointer (). To convert any stored physical addresses\r
+ // to virtual address. After the OS transitions to calling in virtual mode, all future\r
+ // runtime calls will be made in virtual mode.\r
+ //\r
+ EfiConvertPointer (0x0, (VOID**)&mPL031RtcBase);\r
+ return;\r
+}\r
\r
/**\r
This is the declaration of an EFI image entry point. This can be the entry point to an application\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
\r
+ // Initialize RTC Base Address\r
+ mPL031RtcBase = PcdGet32 (PcdPL031RtcBase);\r
+\r
+ // Declare the controller as EFI_MEMORY_RUNTIME\r
+ Status = gDS->AddMemorySpace (\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ mPL031RtcBase, SIZE_4KB,\r
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gDS->SetMemorySpaceAttributes (mPL031RtcBase, SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
// Setup the setters and getters\r
gRT->GetTime = LibGetTime;\r
gRT->SetTime = LibSetTime;\r
&Handle,\r
&gEfiRealTimeClockArchProtocolGuid, NULL,\r
NULL\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Fixup internal data so that EFI can be call in virtual mode.\r
- Call the passed in Child Notify event and convert any pointers in\r
- lib to virtual mode.\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- @param[in] Event The Event that is being processed\r
- @param[in] Context Event Context\r
-**/\r
-VOID\r
-EFIAPI\r
-LibRtcVirtualNotifyEvent (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
//\r
- // Only needed if you are going to support the OS calling RTC functions in virtual mode.\r
- // You will need to call EfiConvertPointer (). To convert any stored physical addresses\r
- // to virtual address. After the OS transitions to calling in virtual mode, all future\r
- // runtime calls will be made in virtual mode.\r
+ // Register for the virtual address change event\r
//\r
- return;\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ LibRtcVirtualNotifyEvent,\r
+ NULL,\r
+ &gEfiEventVirtualAddressChangeGuid,\r
+ &mRtcVirtualAddrChangeEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
}\r