diff options
Diffstat (limited to 'MdeModulePkg')
24 files changed, 1997 insertions, 50 deletions
diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c index 602bb36..df0765b 100644 --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c @@ -94,6 +94,7 @@ GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = { { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE, EFI_MEMORY_SP, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_HOT_PLUGGABLE, EFI_MEMORY_HOT_PLUGGABLE, TRUE },
{ 0, 0, FALSE }
};
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c index e957cb6..1b2b885 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c @@ -670,13 +670,16 @@ SmmEntryPoint ( IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext
)
{
- EFI_STATUS Status;
- EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
- BOOLEAN InLegacyBoot;
- BOOLEAN IsOverlapped;
- BOOLEAN IsOverUnderflow;
- VOID *CommunicationBuffer;
- UINTN BufferSize;
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER_V3 *CommunicateHeader;
+ EFI_SMM_COMMUNICATE_HEADER *LegacyCommunicateHeader;
+ BOOLEAN InLegacyBoot;
+ BOOLEAN IsOverlapped;
+ VOID *CommunicationBuffer;
+ UINTN BufferSize;
+ EFI_GUID *CommGuid;
+ VOID *CommData;
+ UINTN CommHeaderSize;
PERF_FUNCTION_BEGIN ();
@@ -730,10 +733,8 @@ SmmEntryPoint ( //
// Check for over or underflows
//
- IsOverUnderflow = EFI_ERROR (SafeUintnSub (BufferSize, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data), &BufferSize));
-
if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) ||
- IsOverlapped || IsOverUnderflow)
+ IsOverlapped || (BufferSize < sizeof (EFI_SMM_COMMUNICATE_HEADER)))
{
//
// If CommunicationBuffer is not in valid address scope,
@@ -744,25 +745,50 @@ SmmEntryPoint ( gSmmCorePrivate->CommunicationBuffer = NULL;
gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
} else {
- CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
- // BufferSize was updated by the SafeUintnSub() call above.
- Status = SmiManage (
- &CommunicateHeader->HeaderGuid,
- NULL,
- CommunicateHeader->Data,
- &BufferSize
- );
+ CommGuid = &((EFI_MM_COMMUNICATE_HEADER_V3 *)CommunicationBuffer)->HeaderGuid;
+ //
+ // Check if the signature matches EFI_MM_COMMUNICATE_HEADER_V3 definition
+ //
+ if (CompareGuid (CommGuid, &gEfiMmCommunicateHeaderV3Guid)) {
+ //
+ // If so, need to make sure the size is at least the size of the header
+ //
+ if (BufferSize < sizeof (EFI_MM_COMMUNICATE_HEADER_V3)) {
+ gSmmCorePrivate->CommunicationBuffer = NULL;
+ gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
+ goto AsyncSmi;
+ }
+
+ CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommunicationBuffer;
+ CommGuid = &CommunicateHeader->MessageGuid;
+ CommData = CommunicateHeader->MessageData;
+ CommHeaderSize = sizeof (EFI_MM_COMMUNICATE_HEADER_V3);
+ } else {
+ LegacyCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
+ CommGuid = &LegacyCommunicateHeader->HeaderGuid;
+ CommData = LegacyCommunicateHeader->Data;
+ CommHeaderSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
+ }
+
+ BufferSize -= CommHeaderSize;
+ Status = SmiManage (
+ CommGuid,
+ NULL,
+ CommData,
+ &BufferSize
+ );
//
// Update CommunicationBuffer, BufferSize and ReturnStatus
// Communicate service finished, reset the pointer to CommBuffer to NULL
//
- gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
+ gSmmCorePrivate->BufferSize = BufferSize + CommHeaderSize;
gSmmCorePrivate->CommunicationBuffer = NULL;
gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
}
}
}
+AsyncSmi:
//
// Process Asynchronous SMI sources
//
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf index 75a5934..22a1048 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf @@ -120,6 +120,7 @@ gSmiHandlerProfileGuid
gEdkiiEndOfS3ResumeGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
gEdkiiS3SmmInitDoneGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
+ gEfiMmCommunicateHeaderV3Guid ## CONSUMES ## GUID # Communicate header
[UserExtensions.TianoCore."ExtraFiles"]
PiSmmCoreExtra.uni
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c index fbba868..e801b75 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c @@ -11,6 +11,7 @@ #include <Protocol/SmmBase2.h>
#include <Protocol/SmmCommunication.h>
#include <Protocol/MmCommunication2.h>
+#include <Protocol/MmCommunication3.h>
#include <Protocol/SmmAccess2.h>
#include <Protocol/SmmConfiguration.h>
#include <Protocol/SmmControl2.h>
@@ -147,6 +148,37 @@ SmmCommunicationMmCommunicate2 ( );
/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_MM_COMMUNICATION3_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+ @param[in, out] CommBufferVirtual Virtual address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationMmCommunicate3 (
+ IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual
+ );
+
+/**
Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.
@param Event The Event that is being processed, not used.
@@ -276,6 +308,13 @@ EFI_MM_COMMUNICATION2_PROTOCOL mMmCommunication2 = { };
//
+// PI 1.9 MM Communication Protocol 3 instance
+//
+EFI_MM_COMMUNICATION3_PROTOCOL mMmCommunication3 = {
+ MmCommunicationMmCommunicate3
+};
+
+//
// SMM Core Private Data structure that contains the data shared between
// the SMM IPL and the SMM Core.
//
@@ -511,10 +550,12 @@ SmmCommunicationCommunicate ( IN OUT UINTN *CommSize OPTIONAL
)
{
- EFI_STATUS Status;
- EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
- BOOLEAN OldInSmm;
- UINTN TempCommSize;
+ EFI_STATUS Status;
+ EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *CommunicateHeaderV3 = NULL;
+ BOOLEAN OldInSmm;
+ UINTN TempCommSize;
+ UINTN CommHeaderSize;
//
// Check parameters
@@ -524,17 +565,28 @@ SmmCommunicationCommunicate ( }
CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommBuffer;
+ if (CompareGuid (&CommunicateHeader->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid)) {
+ CommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;
+ if (CommunicateHeaderV3->BufferSize < sizeof (EFI_MM_COMMUNICATE_HEADER_V3) + CommunicateHeaderV3->MessageSize) {
+ return EFI_INVALID_PARAMETER;
+ }
- if (CommSize == NULL) {
- TempCommSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;
+ TempCommSize = (UINTN)CommunicateHeaderV3->BufferSize;
+ CommHeaderSize = sizeof (EFI_MM_COMMUNICATE_HEADER_V3);
} else {
- TempCommSize = *CommSize;
- //
- // CommSize must hold HeaderGuid and MessageLength
- //
- if (TempCommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) {
- return EFI_INVALID_PARAMETER;
+ if (CommSize == NULL) {
+ TempCommSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;
+ } else {
+ TempCommSize = *CommSize;
+ //
+ // CommSize must hold HeaderGuid and MessageLength
+ //
+ if (TempCommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) {
+ return EFI_INVALID_PARAMETER;
+ }
}
+
+ CommHeaderSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
}
//
@@ -591,18 +643,22 @@ SmmCommunicationCommunicate ( //
// Before SetVirtualAddressMap(), we are in SMM or SMRAM is open and unlocked, call SmiManage() directly.
//
- TempCommSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
+ TempCommSize -= CommHeaderSize;
Status = gSmmCorePrivate->Smst->SmiManage (
&CommunicateHeader->HeaderGuid,
NULL,
CommunicateHeader->Data,
&TempCommSize
);
- TempCommSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
+ TempCommSize += CommHeaderSize;
if (CommSize != NULL) {
*CommSize = TempCommSize;
}
+ if (CommunicateHeaderV3 != NULL) {
+ CommunicateHeaderV3->BufferSize = TempCommSize;
+ }
+
//
// Restore original InSmm state
//
@@ -652,6 +708,46 @@ SmmCommunicationMmCommunicate2 ( }
/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_MM_COMMUNICATION3_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+ @param[in, out] CommBufferVirtual Virtual address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+ @param[out] CommSize The size of data being returned. Zero if the handler does not wish to
+ reply with any data. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationMmCommunicate3 (
+ IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual
+ )
+{
+ return SmmCommunicationCommunicate (
+ &mSmmCommunication,
+ CommBufferPhysical,
+ NULL
+ );
+}
+
+/**
Event notification that is fired when GUIDed Event Group is signaled.
@param Event The Event that is being processed, not used.
@@ -1878,6 +1974,8 @@ SmmIplEntry ( &mSmmCommunication,
&gEfiMmCommunication2ProtocolGuid,
&mMmCommunication2,
+ &gEfiMmCommunication3ProtocolGuid,
+ &mMmCommunication3,
NULL
);
ASSERT_EFI_ERROR (Status);
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf index ddeb39c..e983bb2 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf @@ -52,6 +52,7 @@ gEfiSmmBase2ProtocolGuid ## PRODUCES
gEfiSmmCommunicationProtocolGuid ## PRODUCES
gEfiMmCommunication2ProtocolGuid ## PRODUCES
+ gEfiMmCommunication3ProtocolGuid ## PRODUCES
gEfiSmmAccess2ProtocolGuid ## CONSUMES
## NOTIFY
## CONSUMES
@@ -80,6 +81,7 @@ gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gLoadFixedAddressConfigurationTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiMmCommunicateHeaderV3Guid ## SOMETIMES_CONSUMES ## UNDEFINED # MM communication v3
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h b/MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h new file mode 100644 index 0000000..0b8e2b6 --- /dev/null +++ b/MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h @@ -0,0 +1,31 @@ +/** @file
+ Arm FF-A ns common library Header file
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ Copyright (c), Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef ARM_FFA_RX_TX_BUFFER_INFO_H_
+#define ARM_FFA_RX_TX_BUFFER_INFO_H_
+
+/**
+ * Guid Hob Data for gArmFfaRxTxBufferInfoGuid Guid Hob.
+ */
+typedef struct ArmFfaRxTxBuffersInfo {
+ /// Tx Buffer Address.
+ VOID *TxBufferAddr;
+
+ /// Tx Buffer Size.
+ UINT64 TxBufferSize;
+
+ /// Rx Buffer Address.
+ VOID *RxBufferAddr;
+
+ /// Rx Buffer Size.
+ UINT64 RxBufferSize;
+} ARM_FFA_RX_TX_BUFFER_INFO;
+
+extern EFI_GUID gArmFfaRxTxBufferInfoGuid;
+
+#endif
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c new file mode 100644 index 0000000..8f66a4a --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c @@ -0,0 +1,800 @@ +/** @file
+ Arm Ffa library common code.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmSvcLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+#include <IndustryStandard/ArmFfaPartInfo.h>
+#include <IndustryStandard/ArmStdSmc.h>
+
+#include "ArmFfaCommon.h"
+
+BOOLEAN gFfaSupported;
+UINT16 gPartId;
+
+/**
+ Convert EFI_GUID to UUID format.
+ for example, If there is EFI_GUID named
+ "378daedc-f06b-4446-8314-40ab933c87a3",
+
+ EFI_GUID is saved in memory like:
+ dc ae 8d 37
+ 6b f0 46 44
+ 83 14 40 ab
+ 93 3c 87 a3
+
+ However, UUID should be saved like:
+ 37 8d ae dc
+ f0 6b 44 46
+ 83 14 40 ab
+ 93 3c 87 a3
+
+ FF-A and other software components (i.e. linux-kernel)
+ uses below format.
+
+ @param [in] Guid EFI_GUID
+ @param [out] Uuid Uuid
+
+**/
+STATIC
+VOID
+EFIAPI
+ConvertEfiGuidToUuid (
+ IN EFI_GUID *Guid,
+ OUT UINT64 *Uuid
+ )
+{
+ UINT32 *Data32;
+ UINT16 *Data16;
+
+ CopyGuid ((EFI_GUID *)Uuid, Guid);
+ Data32 = (UINT32 *)Uuid;
+ Data32[0] = SwapBytes32 (Data32[0]);
+ Data16 = (UINT16 *)&Data32[1];
+ Data16[0] = SwapBytes16 (Data16[0]);
+ Data16[1] = SwapBytes16 (Data16[1]);
+}
+
+/**
+ Convert EFI_STATUS to FFA return code.
+
+ @param [in] Status edk2 status code.
+
+ @retval ARM_FFA_RET_* return value correspond to EFI_STATUS.
+
+**/
+UINTN
+EFIAPI
+EfiStatusToFfaStatus (
+ IN EFI_STATUS Status
+ )
+{
+ switch (Status) {
+ case EFI_SUCCESS:
+ return ARM_FFA_RET_SUCCESS;
+ case EFI_INVALID_PARAMETER:
+ return ARM_FFA_RET_INVALID_PARAMETERS;
+ case EFI_OUT_OF_RESOURCES:
+ return ARM_FFA_RET_NO_MEMORY;
+ case EFI_NO_RESPONSE:
+ return ARM_FFA_RET_BUSY;
+ case EFI_INTERRUPT_PENDING:
+ return ARM_FFA_RET_INTERRUPTED;
+ case EFI_ACCESS_DENIED:
+ return ARM_FFA_RET_DENIED;
+ case EFI_ABORTED:
+ return ARM_FFA_RET_ABORTED;
+ case EFI_NOT_FOUND:
+ return ARM_FFA_RET_NODATA;
+ case EFI_NOT_READY:
+ return ARM_FFA_RET_NOT_READY;
+ default:
+ return ARM_FFA_RET_NOT_SUPPORTED;
+ }
+}
+
+/**
+ Convert FFA return code to EFI_STATUS.
+
+ @param [in] FfaStatus Ffa return Status
+
+ @retval EFI_STATUS return value correspond EFI_STATUS to FfaStatus
+
+**/
+EFI_STATUS
+EFIAPI
+FfaStatusToEfiStatus (
+ IN UINTN FfaStatus
+ )
+{
+ switch ((UINT32)FfaStatus) {
+ case ARM_FFA_RET_SUCCESS:
+ return EFI_SUCCESS;
+ case ARM_FFA_RET_INVALID_PARAMETERS:
+ return EFI_INVALID_PARAMETER;
+ case ARM_FFA_RET_NO_MEMORY:
+ return EFI_OUT_OF_RESOURCES;
+ case ARM_FFA_RET_BUSY:
+ return EFI_NO_RESPONSE;
+ case ARM_FFA_RET_INTERRUPTED:
+ return EFI_INTERRUPT_PENDING;
+ case ARM_FFA_RET_DENIED:
+ return EFI_ACCESS_DENIED;
+ case ARM_FFA_RET_ABORTED:
+ return EFI_ABORTED;
+ case ARM_FFA_RET_NODATA:
+ return EFI_NOT_FOUND;
+ case ARM_FFA_RET_NOT_READY:
+ return EFI_NOT_READY;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Convert FfArgs to EFI_STATUS.
+
+ @param [in] FfaArgs Ffa arguments
+
+ @retval EFI_STATUS return value correspond EFI_STATUS to FfaStatus
+
+**/
+EFI_STATUS
+EFIAPI
+FfaArgsToEfiStatus (
+ IN ARM_FFA_ARGS *FfaArgs
+ )
+{
+ UINT32 FfaStatus;
+
+ if (FfaArgs == NULL) {
+ FfaStatus = ARM_FFA_RET_INVALID_PARAMETERS;
+ } else if (IS_FID_FFA_ERROR (FfaArgs->Arg0)) {
+ /*
+ * In case of error, the Arg0 will be set to the fid FFA_ERROR.
+ * and Error code is set in Arg2.
+ */
+ FfaStatus = FfaArgs->Arg2;
+ } else if (FfaArgs->Arg0 == ARM_FFA_RET_NOT_SUPPORTED) {
+ /*
+ * If Some FF-A ABI doesn't support, it sets ARM_FFA_RET_NOT_SUPPORTED
+ * in Arg0 and other register has no meaning.
+ * In this case, set Arg2 as ARM_FFA_RET_NOT_SUPPORTED so that
+ * FfaStatusToEfiStatus (FfaARgs.Arg2) returns proper EFI_STATUS.
+ */
+ FfaStatus = ARM_FFA_RET_NOT_SUPPORTED;
+ } else if (FfaArgs->Arg0 == ARM_FID_FFA_INTERRUPT) {
+ FfaStatus = ARM_FFA_RET_INTERRUPTED;
+ } else {
+ FfaStatus = ARM_FFA_RET_SUCCESS;
+ }
+
+ return FfaStatusToEfiStatus (FfaStatus);
+}
+
+/**
+ Trigger FF-A ABI call according to PcdFfaLibConduitSmc.
+
+ @param [in, out] FfaArgs Ffa arguments
+
+**/
+VOID
+EFIAPI
+ArmCallFfa (
+ IN OUT ARM_FFA_ARGS *FfaArgs
+ )
+{
+ if (PcdGetBool (PcdFfaLibConduitSmc)) {
+ ArmCallSmc ((ARM_SMC_ARGS *)FfaArgs);
+ } else {
+ ArmCallSvc ((ARM_SVC_ARGS *)FfaArgs);
+ }
+}
+
+/**
+ Check FF-A support or not.
+
+ @retval TRUE Supported
+ @retval FALSE Not supported
+
+**/
+BOOLEAN
+EFIAPI
+IsFfaSupported (
+ IN VOID
+ )
+{
+ return gFfaSupported;
+}
+
+/**
+ Get FF-A version.
+
+ @param [in] RequestMajorVersion Minimal request major version
+ @param [in] RequestMinorVersion Minimal request minor version
+ @param [out] CurrentMajorVersion Current major version
+ @param [out] CurrentMinorVersion Current minor version
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetVersion (
+ IN UINT16 RequestMajorVersion,
+ IN UINT16 RequestMinorVersion,
+ OUT UINT16 *CurrentMajorVersion,
+ OUT UINT16 *CurrentMinorVersion
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_VERSION;
+ FfaArgs.Arg1 = ARM_FFA_CREATE_VERSION (
+ RequestMajorVersion,
+ RequestMinorVersion
+ );
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CurrentMajorVersion != NULL) {
+ *CurrentMajorVersion = ARM_FFA_MAJOR_VERSION_GET (FfaArgs.Arg0);
+ }
+
+ if (CurrentMinorVersion != NULL) {
+ *CurrentMinorVersion = ARM_FFA_MINOR_VERSION_GET (FfaArgs.Arg0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get FF-A features.
+
+ @param [in] Id Feature id or function id
+ @param [in] InputProperties Input properties according to Id
+ @param [out] Property1 First property.
+ @param [out] Property2 Second property.
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetFeatures (
+ IN UINT32 Id,
+ IN UINT32 InputProperties,
+ OUT UINTN *Property1,
+ OUT UINTN *Property2
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if ((Property1 == NULL) || (Property2 == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Property1 = 0x00;
+ *Property2 = 0x00;
+
+ switch (Id) {
+ case ARM_FID_FFA_RXTX_MAP_AARCH32:
+ case ARM_FID_FFA_RXTX_MAP_AARCH64:
+ if ((InputProperties != FFA_RXTX_MAP_INPUT_PROPERTY_DEFAULT)) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid Parameter for FunctionId: 0x%x", __func__, Id));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+ FfaArgs.Arg0 = ARM_FID_FFA_FEATURES;
+ FfaArgs.Arg1 = Id;
+ FfaArgs.Arg2 = InputProperties;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Id) {
+ case ARM_FID_FFA_RXTX_MAP_AARCH32:
+ case ARM_FID_FFA_RXTX_MAP_AARCH64:
+ case ARM_FFA_FEATURE_ID_NOTIFICATION_PENDING_INTERRUPT:
+ case ARM_FFA_FEATURE_ID_SCHEDULE_RECEIVER_INTERRUPT:
+ case ARM_FFA_FEATURE_ID_MANAGED_EXIT_INTERRUPT:
+ *Property1 = FfaArgs.Arg2;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Acquire ownership of the Rx buffer.
+
+ @param [in] PartId Partition Id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxAcquire (
+ IN UINT16 PartId
+ )
+{
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RX_ACQUIRE;
+ FfaArgs.Arg1 = PartId;
+
+ ArmCallFfa (&FfaArgs);
+
+ return FfaArgsToEfiStatus (&FfaArgs);
+}
+
+/**
+ Release ownership of the Rx buffer.
+
+ @param [in] PartId Partition Id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxRelease (
+ IN UINT16 PartId
+ )
+{
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RX_RELEASE;
+ FfaArgs.Arg1 = PartId;
+
+ ArmCallFfa (&FfaArgs);
+
+ return FfaArgsToEfiStatus (&FfaArgs);
+}
+
+/**
+ Get partition or VM id.
+
+ @param [out] PartId Partition id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibPartitionIdGet (
+ OUT UINT16 *PartId
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if (PartId == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_ID_GET;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get partition id. Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ *PartId = (FfaArgs.Arg2 >> ARM_FFA_DEST_EP_SHIFT) & ARM_FFA_PARTITION_ID_MASK;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get spmc or spmd partition id.
+
+ @param [out] SpmPartId spmc/spmd partition id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibSpmIdGet (
+ OUT UINT16 *SpmPartId
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if (SpmPartId == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_SPM_ID_GET;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get partition id. Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ *SpmPartId = (FfaArgs.Arg2 >> ARM_FFA_DEST_EP_SHIFT) & ARM_FFA_PARTITION_ID_MASK;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Partition info.
+ If This function is called to get partition descriptors
+ (Flags isn't set with FFA_PART_INFO_FLAG_TYPE_COUNT),
+ It should call ArmFfaLibRxRelease() to release RX buffer.
+
+ @param [in] ServiceGuid Service guid.
+ @param [in] Flags If this function called to get partition desc
+ and get successfully,
+ Caller should release RX buffer by calling
+ ArmFfaLibRxRelease
+ @param [out] Count Number of partition or partition descriptor
+ @param [out] Size Size of Partition Info structure in Rx Buffer
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibPartitionInfoGet (
+ IN EFI_GUID *ServiceGuid,
+ IN UINT32 Flags,
+ OUT UINT32 *Count,
+ OUT UINT32 *Size OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ UINT64 Uuid[2];
+ UINT32 *SmcUuid;
+
+ if (Count == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((((Flags >> FFA_PART_INFO_FLAG_TYPE_SHIFT) & FFA_PART_INFO_FLAG_TYPE_MASK) !=
+ FFA_PART_INFO_FLAG_TYPE_COUNT) && (Size == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ServiceGuid != NULL) {
+ ConvertEfiGuidToUuid (ServiceGuid, Uuid);
+ } else {
+ ZeroMem (Uuid, sizeof (Uuid));
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+ SmcUuid = (UINT32 *)Uuid;
+
+ FfaArgs.Arg0 = ARM_FID_FFA_PARTITION_INFO_GET;
+ FfaArgs.Arg1 = SmcUuid[0];
+ FfaArgs.Arg2 = SmcUuid[1];
+ FfaArgs.Arg3 = SmcUuid[2];
+ FfaArgs.Arg4 = SmcUuid[3];
+ FfaArgs.Arg5 = Flags;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get partition information of %g. Status: %r\n",
+ __func__,
+ (ServiceGuid != NULL) ? ServiceGuid : (EFI_GUID *)Uuid,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ *Count = FfaArgs.Arg2;
+ if (Size != NULL) {
+ *Size = FfaArgs.Arg3;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ *Count = 0;
+ if (Size != NULL) {
+ *Size = 0;
+ }
+
+ return Status;
+}
+
+/**
+ Restore the context which was interrupted with FFA_INTERRUPT (EFI_INTERRUPT_PENDING).
+
+ @param [in] PartId Partition id
+ @param [in] CpuNumber Cpu number in partition
+
+ @retval EFI_SUCCESS
+ @retval Other Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRun (
+ IN UINT16 PartId,
+ IN UINT16 CpuNumber
+ )
+{
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RUN;
+ FfaArgs.Arg1 = PACK_PARTITION_ID_INFO (PartId, CpuNumber);
+
+ ArmCallFfa (&FfaArgs);
+
+ return FfaArgsToEfiStatus (&FfaArgs);
+}
+
+/**
+ Send direct message request version 1.
+
+ @param [in] DestPartId Dest partition id
+ @param [in] Flags Message flags
+ @param [in, out] ImpDefArgs Implemented defined arguments and
+ Implemented defined return values
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibMsgSendDirectReq (
+ IN UINT16 DestPartId,
+ IN UINT32 Flags,
+ IN OUT DIRECT_MSG_ARGS *ImpDefArgs
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if ((DestPartId == gPartId) || (ImpDefArgs == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_MSG_SEND_DIRECT_REQ;
+ FfaArgs.Arg1 = PACK_PARTITION_ID_INFO (gPartId, DestPartId);
+ FfaArgs.Arg2 = Flags;
+ FfaArgs.Arg3 = ImpDefArgs->Arg0;
+ FfaArgs.Arg4 = ImpDefArgs->Arg1;
+ FfaArgs.Arg5 = ImpDefArgs->Arg2;
+ FfaArgs.Arg6 = ImpDefArgs->Arg3;
+ FfaArgs.Arg7 = ImpDefArgs->Arg4;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ImpDefArgs->Arg0 = FfaArgs.Arg3;
+ ImpDefArgs->Arg1 = FfaArgs.Arg4;
+ ImpDefArgs->Arg2 = FfaArgs.Arg5;
+ ImpDefArgs->Arg3 = FfaArgs.Arg6;
+ ImpDefArgs->Arg4 = FfaArgs.Arg7;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send direct message request version 2.
+
+ @param [in] DestPartId Dest partition id
+ @param [in] ServiceGuid Service guid
+ @param [in, out] ImpDefArgs Implemented defined arguments and
+ Implemented defined return values
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibMsgSendDirectReq2 (
+ IN UINT16 DestPartId,
+ IN EFI_GUID *ServiceGuid,
+ IN OUT DIRECT_MSG_ARGS *ImpDefArgs
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Uuid[2];
+ ARM_FFA_ARGS FfaArgs;
+
+ /*
+ * Direct message request 2 is only supported on AArch64.
+ */
+ if (sizeof (UINTN) != sizeof (UINT64)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((DestPartId == gPartId) || (ImpDefArgs == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ServiceGuid != NULL) {
+ ConvertEfiGuidToUuid (ServiceGuid, Uuid);
+ } else {
+ ZeroMem (Uuid, sizeof (Uuid));
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_MSG_SEND_DIRECT_REQ2;
+ FfaArgs.Arg1 = PACK_PARTITION_ID_INFO (gPartId, DestPartId);
+ FfaArgs.Arg2 = Uuid[0];
+ FfaArgs.Arg3 = Uuid[1];
+ FfaArgs.Arg4 = ImpDefArgs->Arg0;
+ FfaArgs.Arg5 = ImpDefArgs->Arg1;
+ FfaArgs.Arg6 = ImpDefArgs->Arg2;
+ FfaArgs.Arg7 = ImpDefArgs->Arg3;
+ FfaArgs.Arg8 = ImpDefArgs->Arg4;
+ FfaArgs.Arg9 = ImpDefArgs->Arg5;
+ FfaArgs.Arg10 = ImpDefArgs->Arg6;
+ FfaArgs.Arg11 = ImpDefArgs->Arg7;
+ FfaArgs.Arg12 = ImpDefArgs->Arg8;
+ FfaArgs.Arg13 = ImpDefArgs->Arg9;
+ FfaArgs.Arg14 = ImpDefArgs->Arg10;
+ FfaArgs.Arg15 = ImpDefArgs->Arg11;
+ FfaArgs.Arg16 = ImpDefArgs->Arg12;
+ FfaArgs.Arg17 = ImpDefArgs->Arg13;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ImpDefArgs->Arg0 = FfaArgs.Arg4;
+ ImpDefArgs->Arg1 = FfaArgs.Arg5;
+ ImpDefArgs->Arg2 = FfaArgs.Arg6;
+ ImpDefArgs->Arg3 = FfaArgs.Arg7;
+ ImpDefArgs->Arg4 = FfaArgs.Arg8;
+ ImpDefArgs->Arg5 = FfaArgs.Arg9;
+ ImpDefArgs->Arg6 = FfaArgs.Arg10;
+ ImpDefArgs->Arg7 = FfaArgs.Arg11;
+ ImpDefArgs->Arg8 = FfaArgs.Arg12;
+ ImpDefArgs->Arg9 = FfaArgs.Arg13;
+ ImpDefArgs->Arg10 = FfaArgs.Arg14;
+ ImpDefArgs->Arg11 = FfaArgs.Arg15;
+ ImpDefArgs->Arg12 = FfaArgs.Arg16;
+ ImpDefArgs->Arg13 = FfaArgs.Arg17;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Common ArmFfaLib init.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_UNSUPPORTED FF-A isn't supported
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibCommonInit (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT16 CurrentMajorVersion;
+ UINT16 CurrentMinorVersion;
+ ARM_FFA_ARGS FfaArgs;
+
+ gFfaSupported = FALSE;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_SMC_ARGS));
+ FfaArgs.Arg0 = SMCCC_VERSION;
+ ArmCallFfa (&FfaArgs);
+ if ((INT32)FfaArgs.Arg0 < 0) {
+ DEBUG ((DEBUG_ERROR, "%a: SMCCC_VERSION not supported\n", __func__));
+ return EFI_UNSUPPORTED;
+ }
+
+ // According to SMCCC Specification v1.6 G BET0
+ // Table F0-1: Changelog: Starting from SMCCC_VERSION v1.2, the interface
+ // - Permits calls to use R4–R7 as return register
+ // - Permits calls to use X4–X17 as return registers
+ // - Permits calls to use X8–X17 as argument registers
+ if ((INT32)FfaArgs.Arg0 < 0x10002) {
+ DEBUG ((DEBUG_ERROR, "%a: SMCCC_VERSION %x < 1.2\n", __func__, (UINT32)FfaArgs.Arg0));
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = ArmFfaLibGetVersion (
+ ARM_FFA_MAJOR_VERSION,
+ ARM_FFA_MINOR_VERSION,
+ &CurrentMajorVersion,
+ &CurrentMinorVersion
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = ArmFfaLibPartitionIdGet (&gPartId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gFfaSupported = TRUE;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h new file mode 100644 index 0000000..663d2d3 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h @@ -0,0 +1,86 @@ +/** @file
+ Arm FF-A ns common library Header file
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+ - spmc - Secure Partition Manager Core
+ - spmd - Secure Partition Manager Dispatcher
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#ifndef ARM_FFA_COMMON_LIB_H_
+#define ARM_FFA_COMMON_LIB_H_
+
+/**
+ * Arguments to call FF-A request via SMC/SVC.
+ */
+typedef struct ArmFfaArgs {
+ UINTN Arg0;
+ UINTN Arg1;
+ UINTN Arg2;
+ UINTN Arg3;
+ UINTN Arg4;
+ UINTN Arg5;
+ UINTN Arg6;
+ UINTN Arg7;
+ UINTN Arg8;
+ UINTN Arg9;
+ UINTN Arg10;
+ UINTN Arg11;
+ UINTN Arg12;
+ UINTN Arg13;
+ UINTN Arg14;
+ UINTN Arg15;
+ UINTN Arg16;
+ UINTN Arg17;
+} ARM_FFA_ARGS;
+
+extern BOOLEAN gFfaSupported;
+extern UINT16 gPartId;
+
+/**
+ Convert FfArgs to EFI_STATUS.
+
+ @param [in] FfaArgs Ffa arguments
+
+ @retval EFI_STATUS return value correspond EFI_STATUS to FfaStatus
+
+**/
+EFI_STATUS
+EFIAPI
+FfaArgsToEfiStatus (
+ IN ARM_FFA_ARGS *FfaArgs
+ );
+
+/**
+ Trigger FF-A ABI call according to PcdFfaLibConduitSmc.
+
+ @param [in out] FfaArgs Ffa arguments
+
+**/
+VOID
+EFIAPI
+ArmCallFfa (
+ IN OUT ARM_FFA_ARGS *FfaArgs
+ );
+
+/**
+ Common ArmFfaLib Constructor.
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibCommonInit (
+ IN VOID
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c new file mode 100644 index 0000000..8751f2f --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c @@ -0,0 +1,160 @@ +/** @file
+ Arm Ffa library code for Dxe Driver
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+
+#include <Guid/ArmFfaRxTxBufferInfo.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+STATIC EFI_EVENT mFfaExitBootServiceEvent;
+
+/**
+ Unmap RX/TX buffer on Exit Boot Service.
+
+ @param [in] Event Registered exit boot service event.
+ @param [in] Context Additional data.
+
+**/
+STATIC
+VOID
+EFIAPI
+ArmFfaLibExitBootServiceEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ ArmFfaLibRxTxUnmap ();
+}
+
+/**
+ ArmFfaLib Constructor.
+
+ @param [in] ImageHandle Image Handle
+ @param [in] SystemTable System Table
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval EFI_OUT_OF_RESOURCES Out of memory
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaDxeLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *RxTxBufferHob;
+ ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
+
+ Status = ArmFfaLibCommonInit ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ /*
+ * EFI_UNSUPPORTED return from ArmFfaLibCommonInit() means
+ * FF-A interface doesn't support.
+ * However, It doesn't make failure of loading driver/library instance
+ * (i.e) ArmPkg's MmCommunication Dxe/PEI Driver uses as well as SpmMm.
+ * So If FF-A is not supported the the MmCommunication Dxe/PEI falls
+ * back to SpmMm.
+ * For this case, return EFI_SUCCESS.
+ */
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+
+ if (PcdGetBool (PcdFfaExitBootEventRegistered)) {
+ return EFI_SUCCESS;
+ }
+
+ /*
+ * If PEIM uses ArmFfaPeiLib, the Rx/Tx buffers is already mapped in PEI phase.
+ * In this case, get Rx/Tx buffer info from Hob.
+ */
+ RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
+ if (RxTxBufferHob != NULL) {
+ BufferInfo = GET_GUID_HOB_DATA (RxTxBufferHob);
+ PcdSet64S (PcdFfaTxBuffer, (UINTN)BufferInfo->TxBufferAddr);
+ PcdSet64S (PcdFfaRxBuffer, (UINTN)BufferInfo->RxBufferAddr);
+ } else {
+ Status = ArmFfaLibRxTxMap ();
+
+ /*
+ * When first Dxe instance (library or driver) which uses ArmFfaLib loaded,
+ * It already maps Rx/Tx buffer.
+ * From Next Dxe instance which uses ArmFfaLib it doesn't need to map Rx/Tx
+ * buffer again but it uses the mapped one.
+ * ArmFfaLibRxTxMap() returns EFI_ALREADY_STARTED when the Rx/Tx buffers
+ * already maps.
+ */
+ if ((Status != EFI_SUCCESS) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to Map Rx/Tx buffer. Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+ }
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ ArmFfaLibExitBootServiceEvent,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &mFfaExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to register ExitBootService event. Status: %r\n",
+ __func__,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ PcdSetBoolS (PcdFfaExitBootEventRegistered, TRUE);
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ if (RxTxBufferHob != NULL) {
+ ArmFfaLibRxTxUnmap ();
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf new file mode 100644 index 0000000..361ebf6 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf @@ -0,0 +1,46 @@ +## @file
+# Provides FF-A ABI Library used in Dxe Driver.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmFfaDxeLib
+ FILE_GUID = e2a8e040-5346-11ef-8454-eff3c163f615
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmFfaLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ArmFfaDxeLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaRxTxMap.h
+ ArmFfaRxTxMap.c
+ ArmFfaDxeLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaRxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaExitBootEventRegistered
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
+ gEfiEventExitBootServicesGuid
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c new file mode 100644 index 0000000..e65a3d0 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c @@ -0,0 +1,100 @@ +/** @file
+ Arm Ffa library code for PEI Driver
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <Pi/PiPeiCis.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+
+#include <Guid/ArmFfaRxTxBufferInfo.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+/**
+ ArmFfaLib Constructor.
+
+ @param [in] FileHandle File Handle
+ @param [in] PeiServices Pei Service Table
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaPeiLibConstructor (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *RxTxBufferHob;
+ ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
+
+ Status = ArmFfaLibCommonInit ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ /*
+ * EFI_UNSUPPORTED return from ArmFfaLibCommonInit() means
+ * FF-A interface doesn't support.
+ * However, It doesn't make failure of loading driver/library instance
+ * (i.e) ArmPkg's MmCommunication Dxe/PEI Driver uses as well as SpmMm.
+ * So If FF-A is not supported the the MmCommunication Dxe/PEI falls
+ * back to SpmMm.
+ * For this case, return EFI_SUCCESS.
+
+ */
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+
+ RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
+ if (RxTxBufferHob == NULL) {
+ Status = ArmFfaLibRxTxMap ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BufferInfo = BuildGuidHob (
+ &gArmFfaRxTxBufferInfoGuid,
+ sizeof (ARM_FFA_RX_TX_BUFFER_INFO)
+ );
+ if (BufferInfo == NULL) {
+ ArmFfaLibRxTxUnmap ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BufferInfo->TxBufferAddr = (VOID *)(UINTN)PcdGet64 (PcdFfaTxBuffer);
+ BufferInfo->TxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ BufferInfo->RxBufferAddr = (VOID *)(UINTN)PcdGet64 (PcdFfaRxBuffer);
+ BufferInfo->RxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf new file mode 100644 index 0000000..e3b7dbd --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf @@ -0,0 +1,45 @@ +## @file
+# Provides FF-A ABI Library used in PEI Driver.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmFfaPeiLib
+ FILE_GUID = 6e21912a-5f50-11ef-a3ae-dfe665fd4fc0
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmFfaLib|PEIM
+ CONSTRUCTOR = ArmFfaPeiLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaRxTxMap.h
+ ArmFfaRxTxMap.c
+ ArmFfaPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaRxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaExitBootEventRegistered
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c new file mode 100644 index 0000000..37d3e80 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c @@ -0,0 +1,272 @@ +/** @file
+ Arm Ffa library common code.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+/**
+ Get mapped Rx/Tx buffers.
+
+ @param [out] TxBuffer Address of TxBuffer
+ @param [out] TxBufferSize Size of TxBuffer
+ @param [out] RxBuffer Address of RxBuffer
+ @param [out] RxBufferSize Size of RxBuffer
+
+ @retval EFI_SUCCESS
+ @retval Others Error.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetRxTxBuffers (
+ OUT VOID **TxBuffer OPTIONAL,
+ OUT UINT64 *TxBufferSize OPTIONAL,
+ OUT VOID **RxBuffer OPTIONAL,
+ OUT UINT64 *RxBufferSize OPTIONAL
+ )
+{
+ UINTN TxBufferAddr;
+ UINTN RxBufferAddr;
+
+ TxBufferAddr = (UINTN)PcdGet64 (PcdFfaTxBuffer);
+ RxBufferAddr = (UINTN)PcdGet64 (PcdFfaRxBuffer);
+
+ if ((TxBufferAddr == 0x00) || (RxBufferAddr == 0x00)) {
+ return EFI_NOT_READY;
+ }
+
+ if (TxBuffer != NULL) {
+ *TxBuffer = (VOID *)TxBufferAddr;
+ }
+
+ if (TxBufferSize != NULL) {
+ *TxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ }
+
+ if (RxBuffer != NULL) {
+ *RxBuffer = (VOID *)RxBufferAddr;
+ }
+
+ if (RxBufferSize != NULL) {
+ *RxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Mapping Rx/Tx buffers.
+ This function is only called in ArmFfaLibConstructor because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Rx/Tx buffer already mapped.
+ @retval EFI_OUT_OF_RESOURCE Out of memory
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxMap (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ UINTN Property1;
+ UINTN Property2;
+ UINTN MinSizeAndAlign;
+ UINTN MaxSize;
+ VOID *Buffers;
+ VOID *TxBuffer;
+ VOID *RxBuffer;
+ UINT64 BufferSize;
+
+ TxBuffer = (VOID *)(UINTN)PcdGet64 (PcdFfaTxBuffer);
+ RxBuffer = (VOID *)(UINTN)PcdGet64 (PcdFfaRxBuffer);
+ BufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+
+ /*
+ * If someone already mapped Rx/Tx Buffers, return EFI_ALREADY_STARTED.
+ * return EFI_ALREADY_STARTED.
+ */
+ if ((TxBuffer != NULL) && (RxBuffer != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = ArmFfaLibGetFeatures (
+ ARM_FID_FFA_RXTX_MAP,
+ FFA_RXTX_MAP_INPUT_PROPERTY_DEFAULT,
+ &Property1,
+ &Property2
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get RX/TX buffer property... Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ MinSizeAndAlign =
+ ((Property1 >>
+ ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_SHIFT) &
+ ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_MASK);
+
+ switch (MinSizeAndAlign) {
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_4K:
+ MinSizeAndAlign = SIZE_4KB;
+ break;
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_16K:
+ MinSizeAndAlign = SIZE_16KB;
+ break;
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_64K:
+ MinSizeAndAlign = SIZE_64KB;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Invalid MinSizeAndAlign: 0x%x\n", __func__, MinSizeAndAlign));
+ return EFI_UNSUPPORTED;
+ }
+
+ MaxSize =
+ (((Property1 >>
+ ARM_FFA_BUFFER_MAXSIZE_PAGE_COUNT_SHIFT) &
+ ARM_FFA_BUFFER_MAXSIZE_PAGE_COUNT_MASK));
+
+ MaxSize = ((MaxSize == 0) ? MAX_UINTN : (MaxSize * MinSizeAndAlign));
+
+ if ((MinSizeAndAlign > (PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE)) ||
+ (MaxSize < (PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE)))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Buffer is too small! MinSize: 0x%x, MaxSize: 0x%x, PageCount: %d\n",
+ __func__,
+ MinSizeAndAlign,
+ MaxSize,
+ PcdGet64 (PcdFfaTxRxPageCount)
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffers = AllocateAlignedPages ((PcdGet64 (PcdFfaTxRxPageCount) * 2), MinSizeAndAlign);
+ if (Buffers == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TxBuffer = Buffers;
+ RxBuffer = Buffers + BufferSize;
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RXTX_MAP;
+ FfaArgs.Arg1 = (UINTN)TxBuffer;
+ FfaArgs.Arg2 = (UINTN)RxBuffer;
+
+ /*
+ * PcdFfaTxRxPageCount sets with count of EFI_PAGE_SIZE granularity
+ * But, PageCounts for Tx/Rx buffer should set with
+ * count of Tx/Rx Buffer's MinSizeAndAlign. granularity.
+ */
+ FfaArgs.Arg3 = PcdGet64 (PcdFfaTxRxPageCount) / EFI_SIZE_TO_PAGES (MinSizeAndAlign);
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to map Rx/Tx buffer. Status: %r\n",
+ __func__,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ PcdSet64S (PcdFfaTxBuffer, (UINTN)TxBuffer);
+ PcdSet64S (PcdFfaRxBuffer, (UINTN)RxBuffer);
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ FreeAlignedPages (Buffers, (PcdGet64 (PcdFfaTxRxPageCount) * 2));
+ TxBuffer = NULL;
+ RxBuffer = NULL;
+
+ return Status;
+}
+
+/**
+ Unmap Rx/Tx buffer.
+ This function is only called in Exit boot service because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETERS Already unregistered
+ @retval EFI_UNSUPPORTED Not supported
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxUnmap (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ VOID *Buffers;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RXTX_UNMAP;
+ FfaArgs.Arg1 = (gPartId << ARM_FFA_SOURCE_EP_SHIFT);
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ /*
+ * Rx/Tx Buffer are allocated with continuous pages.
+ * and start address of these pages is set on PcdFfaTxBuffer.
+ * See ArmFfaLibRxTxMap().
+ */
+ Buffers = (VOID *)(UINTN)PcdGet64 (PcdFfaTxBuffer);
+ if (Buffers != NULL) {
+ FreeAlignedPages (Buffers, (PcdGet64 (PcdFfaTxRxPageCount) * 2));
+ }
+
+ PcdSet64S (PcdFfaTxBuffer, 0x00);
+ PcdSet64S (PcdFfaRxBuffer, 0x00);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h new file mode 100644 index 0000000..6c6bfaa --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h @@ -0,0 +1,54 @@ +/** @file
+ Arm FF-A ns common library Header file
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+ - spmc - Secure Partition Manager Core
+ - spmd - Secure Partition Manager Dispatcher
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#ifndef ARM_FFA_RX_TX_MAP_LIB_H_
+#define ARM_FFA_RX_TX_MAP_LIB_H_
+
+/**
+ Mapping Rx/Tx buffers.
+ This function is only called in ArmFfaLibConstructor because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Rx/Tx buffer already mapped in PEI phase
+ @retval EFI_OUT_OF_RESOURCE Out of memory
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxMap (
+ IN VOID
+ );
+
+/**
+ Unmap Rx/Tx buffer.
+ This function is only called in Exit boot service because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETERS Already unregistered
+ @retval EFI_UNSUPPORTED Not supported
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxUnmap (
+ IN VOID
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf new file mode 100644 index 0000000..395d1f0 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf @@ -0,0 +1,36 @@ +## @file
+# Provides FF-A ABI Library used in StandaloneMmCore.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ArmFfaStandaloneMmCoreLib
+ FILE_GUID = 80d2c4dc-5f0b-11ef-bc86-43b3fb486d6d
+ MODULE_TYPE = MM_CORE_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = ArmFfaLib
+ CONSTRUCTOR = ArmFfaStandaloneMmLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaStandaloneMmLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c new file mode 100644 index 0000000..2d7f834 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c @@ -0,0 +1,89 @@ +/** @file
+ Arm Ffa library code for StandaloneMmCore.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+#include "ArmFfaCommon.h"
+
+/**
+ Get mapped Rx/Tx buffers.
+
+ @param [out] TxBuffer Address of TxBuffer
+ @param [out] TxBufferSize Size of TxBuffer
+ @param [out] RxBuffer Address of RxBuffer
+ @param [out] RxBufferSize Size of RxBuffer
+
+ @retval EFI_SUCCESS
+ @retval Others Error.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetRxTxBuffers (
+ OUT VOID **TxBuffer,
+ OUT UINT64 *TxBufferSize,
+ OUT VOID **RxBuffer,
+ OUT UINT64 *RxBufferSize
+ )
+{
+ /*
+ * StandaloneMm doesn't use Rx/Tx buffer.
+ * So, return EFI_UNSUPPORTED.
+ */
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ ArmFfaLib Constructor.
+
+ @param [in] ImageHandle The firmware allocated handle for the EFI image
+ @param [in] MmSystemTable A pointer to the Management mode System Table
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaStandaloneMmLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ArmFfaLibCommonInit ();
+ if (Status == EFI_UNSUPPORTED) {
+ /*
+ * EFI_UNSUPPORTED means FF-A interface isn't available.
+ * However, for Standalone MM modules, FF-A availability is not required.
+ * i.e. Standalone MM could use SpmMm as a legitimate protocol.
+ * Thus, returning EFI_SUCCESS here to avoid the entrypoint to assert.
+ */
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed. Status = %r\n", __func__, Status));
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf new file mode 100644 index 0000000..44679c0 --- /dev/null +++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf @@ -0,0 +1,37 @@ +## @file
+# Provides FF-A ABI Library used in StandaloneMmCore.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ArmFfaStandaloneMmLib
+ FILE_GUID = e07db74e-6a95-11ef-97ea-c7a6149e81c9
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = ArmFfaLib
+ CONSTRUCTOR = ArmFfaStandaloneMmLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaStandaloneMmLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+
diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c index b752679..c2232e5 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/
#include "BootManager.h"
+#include <Protocol/LoadedImage.h>
UINT16 mKeyInput;
EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;
@@ -493,6 +494,9 @@ UpdateBootManager ( BOOLEAN IsLegacyOption;
BOOLEAN NeedEndOp;
UINTN MaxLen;
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
DeviceType = (UINT16)-1;
@@ -537,6 +541,25 @@ UpdateBootManager ( EndLabel->Number = LABEL_BOOT_OPTION_END;
mKeyInput = 0;
NeedEndOp = FALSE;
+
+ //
+ // Get UiApp FilePath
+ //
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+ ASSERT (DevicePath != NULL);
+
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ LoadedImage->FilePath
+ );
+
for (Index = 0; Index < BootOptionCount; Index++) {
//
// At this stage we are creating a menu entry, thus the Keys are reproduceable
@@ -551,6 +574,13 @@ UpdateBootManager ( }
//
+ // Don't display UiApp within the boot options
+ //
+ if (CompareMem (DevicePath, BootOption[Index].FilePath, GetDevicePathSize (DevicePath)) == 0) {
+ continue;
+ }
+
+ //
// Group the legacy boot option in the sub title created dynamically
//
IsLegacyOption = (BOOLEAN)(
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c index 58130d9..42dd8f8 100644 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c +++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c @@ -598,7 +598,7 @@ PrintHotKeyHelpString ( ColumnIndex = Index % 3;
if (ColumnIndex == 0) {
CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;
- ColumnIndexWidth = ColumnWidth - 1;
+ ColumnIndexWidth = LocalScreen.RightColumn - CurrentCol - 1;
} else if (ColumnIndex == 1) {
CurrentCol = LocalScreen.LeftColumn + ColumnWidth;
ColumnIndexWidth = ColumnWidth;
@@ -646,7 +646,7 @@ PrintHotKeyHelpString ( ColumnIndex = Index % 3;
if (ColumnIndex == 0) {
CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;
- ColumnIndexWidth = ColumnWidth - 1;
+ ColumnIndexWidth = LocalScreen.RightColumn - CurrentCol - 1;
ColumnIndex++;
PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);
}
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf index adda902..87ce20e 100644 --- a/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf +++ b/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf @@ -42,13 +42,13 @@ TimerLib
[Protocols]
- gEdkiiSmmExitBootServicesProtocolGuid ## CONSUMES ## NOTIFY
gEfiLoadedImageProtocolGuid ## CONSUMES
[Guids]
gEfiFirmwarePerformanceGuid ## SOMETIMES_PRODUCES # SmiHandlerRegister
gEdkiiSmmPerformanceMeasurementProtocolGuid ## PRODUCES # Install protocol
gZeroGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiEventExitBootServicesGuid ## CONSUMES ## NOTIFY
[FixedPcd]
gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index aa21365..3698caf 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -494,6 +494,9 @@ ## Include/Guid/DelayedDispatch.h
gEfiDelayedDispatchTableGuid = { 0x4b733449, 0x8eff, 0x488c, { 0x92, 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07 }}
+ ## Include/Guid/ArmFfaRxTxBufferInfo.h
+ gArmFfaRxTxBufferInfoGuid = { 0x96fd3d26, 0x6fb1, 0x11ef, { 0x8c, 0x11, 0xf3, 0xc9, 0xc5, 0x02, 0x31, 0xab } }
+
[Ppis]
## Include/Ppi/FirmwareVolumeShadowPpi.h
gEdkiiPeiFirmwareVolumeShadowPpiGuid = { 0x7dfe756c, 0xed8d, 0x4d77, {0x9e, 0xc4, 0x39, 0x9a, 0x8a, 0x81, 0x51, 0x16 } }
@@ -2281,6 +2284,12 @@ # @Prompt The value is use for Usb Network rate limiting supported.
gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingFactor|100|UINT32|0x10000028
+ ## Define the conduit to use in ArmFfalib.
+ # Default PcdFfaLibConduitSmc == TRUE, conduit = SMC
+ # If PcdFfaLibConduitSvc == FALSE, conduit = SVC
+ # @Prompt Conduit to use in ArmFfaLib.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc|TRUE|BOOLEAN|0x10000029
+
[PcdsPatchableInModule]
## Specify memory size with page number for PEI code when
# Loading Module at Fixed Address feature is enabled.
@@ -2359,5 +2368,21 @@ # @Prompt 64bit VPD base address.
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64|0x0|UINT64|0x00030006
+ ## This dynamic PCD holds the address of the FFA TX buffer.
+ # @Prompt FFA TX Buffer Address
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxBuffer|0x00|UINT64|0x00030009
+
+ ## This dynamic PCD holds the address of the FFA RX buffer.
+ # @Prompt FFA RX Buffer Address
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaRxBuffer|0x00|UINT64|0x0003000A
+
+ ## This dynamic PCD holds the number of pages for the FFA TX/RX buffer.
+ # @Prompt FFA TX/RX Buffer Page Count
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount|1|UINT64|0x0003000B
+
+ ## This dynamic PCD holds the information if the FFA exit boot event is registered.
+ # @Prompt FFA Exit Boot Event Registered
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaExitBootEventRegistered|FALSE|BOOLEAN|0x0003000C
+
[UserExtensions.TianoCore."ExtraFiles"]
MdeModulePkgExtra.uni
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 4b7f3e4..0c530c7 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -184,6 +184,8 @@ [LibraryClasses.ARM, LibraryClasses.AARCH64]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+ ArmSmcLib|MdePkg/Library/ArmSmcLib/ArmSmcLib.inf
+ ArmSvcLib|MdePkg/Library/ArmSvcLib/ArmSvcLib.inf
[LibraryClasses.EBC, LibraryClasses.RISCV64, LibraryClasses.LOONGARCH64]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
@@ -532,5 +534,11 @@ [Components.X64]
MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
+[Components.ARM, Components.AARCH64]
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf
+
[BuildOptions]
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c index a7b7dc7..056a4cb 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c @@ -2014,8 +2014,8 @@ FindTopMenu ( /**
Record the highlight menu and top of screen menu info.
- @param Highlight The menu opton which is highlight.
- @param TopOfScreen The menu opton which is at the top of the form.
+ @param Highlight The menu option which is highlight.
+ @param TopOfScreen The menu option which is at the top of the form.
@param SkipValue The skip line info for the top of screen menu.
**/
@@ -2095,9 +2095,9 @@ UpdateHighlightMenuInfo ( }
/**
- Update attribut for this menu.
+ Update attribute for this menu.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@param Highlight Whether this menu will be highlight.
**/
@@ -2130,7 +2130,7 @@ SetDisplayAttribute ( /**
Print string for this menu option.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@param Col The column that this string will be print at.
@param Row The row that this string will be print at.
@param String The string which need to print.
@@ -2176,7 +2176,7 @@ DisplayMenuString ( /**
Check whether this menu can has option string.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@retval TRUE This menu option can have option string.
@retval FALSE This menu option can't have option string.
@@ -2371,7 +2371,7 @@ FxConfirmPopup ( /**
Print string for this menu option.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@param SkipWidth The skip width between the left to the start of the prompt.
@param BeginCol The begin column for one menu.
@param SkipLine The skip line for this menu.
@@ -2904,9 +2904,9 @@ UiDisplayMenu ( case CfRefreshHighLight:
//
- // MenuOption: Last menu option that need to remove hilight
+ // MenuOption: Last menu option that need to remove highlight
// MenuOption is set to NULL in Repaint
- // NewPos: Current menu option that need to hilight
+ // NewPos: Current menu option that need to highlight
//
ControlFlag = CfUpdateHelpString;
@@ -2986,13 +2986,13 @@ UiDisplayMenu ( }
//
- // NewLine means only update highlight menu (remove old highlight and highlith
- // the new one), not need to full repain the form.
+ // NewLine means only update highlight menu (remove old highlight and highlight
+ // the new one), not need to full repaint the form.
//
if (Repaint || NewLine) {
if (IsListEmpty (&gMenuOption)) {
//
- // Don't print anything if no mwnu option.
+ // Don't print anything if no menu option.
//
StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
} else {
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h index 6e26704..a7b15a8 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h @@ -696,8 +696,8 @@ RefreshTimeOutProcess ( /**
Record the highlight menu and top of screen menu info.
- @param Highlight The menu opton which is highlight.
- @param TopOfScreen The menu opton which is at the top of the form.
+ @param Highlight The menu option which is highlight.
+ @param TopOfScreen The menu option which is at the top of the form.
@param SkipValue The skip line info for the top of screen menu.
**/
|