diff options
author | Levi Yun <yeoreum.yun@arm.com> | 2024-08-05 17:39:27 +0100 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2025-01-17 14:55:42 +0000 |
commit | 5d1b38dd07c40868b4415bbf7424e23ef165667b (patch) | |
tree | c4c5ae6efc0651172d00fd587b42502ce4640816 /ArmPkg | |
parent | 18948c4a6a2a539d19b9c4fb081567c4d2eb4ab6 (diff) | |
download | edk2-5d1b38dd07c40868b4415bbf7424e23ef165667b.tar.gz |
ArmPkg: Add ArmFfaLib used in Dxe driver
Add ArmFfaLib used in Dxe driver
Signed-off-by: Levi Yun <yeoreum.yun@arm.com>
Diffstat (limited to 'ArmPkg')
-rw-r--r-- | ArmPkg/ArmPkg.dsc | 3 | ||||
-rw-r--r-- | ArmPkg/Library/ArmFfaLib/ArmFfaCommon.c | 760 | ||||
-rw-r--r-- | ArmPkg/Library/ArmFfaLib/ArmFfaCommon.h | 76 | ||||
-rw-r--r-- | ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.c | 158 | ||||
-rw-r--r-- | ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf | 46 | ||||
-rw-r--r-- | ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.c | 272 | ||||
-rw-r--r-- | ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.h | 71 |
7 files changed, 1386 insertions, 0 deletions
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index 85d3f49c18..8f64eb4c9b 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -70,6 +70,7 @@ ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
ArmGicArchLib|ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf
+ ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
OpteeLib|ArmPkg/Library/OpteeLib/OpteeLib.inf
@@ -87,6 +88,7 @@ ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
ArmTransferListLib|ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
+ ArmFfaLib|ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
@@ -131,6 +133,7 @@ ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
ArmPkg/Library/OpteeLib/OpteeLib.inf
ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
+ ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
diff --git a/ArmPkg/Library/ArmFfaLib/ArmFfaCommon.c b/ArmPkg/Library/ArmFfaLib/ArmFfaCommon.c new file mode 100644 index 0000000000..4a7c3fbd67 --- /dev/null +++ b/ArmPkg/Library/ArmFfaLib/ArmFfaCommon.c @@ -0,0 +1,760 @@ +/** @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 "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;
+
+ 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;
+
+ 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;
+
+ gFfaSupported = FALSE;
+
+ 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/ArmPkg/Library/ArmFfaLib/ArmFfaCommon.h b/ArmPkg/Library/ArmFfaLib/ArmFfaCommon.h new file mode 100644 index 0000000000..f87c7f3b04 --- /dev/null +++ b/ArmPkg/Library/ArmFfaLib/ArmFfaCommon.h @@ -0,0 +1,76 @@ +/** @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;
+} 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/ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.c b/ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.c new file mode 100644 index 0000000000..4d82844ee1 --- /dev/null +++ b/ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.c @@ -0,0 +1,158 @@ +/** @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 "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/ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf b/ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf new file mode 100644 index 0000000000..96525cfba3 --- /dev/null +++ b/ArmPkg/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
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdFfaLibConduitSmc
+ gArmTokenSpaceGuid.PcdFfaTxBuffer
+ gArmTokenSpaceGuid.PcdFfaRxBuffer
+ gArmTokenSpaceGuid.PcdFfaTxRxPageCount
+ gArmTokenSpaceGuid.PcdFfaExitBootEventRegistered
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
+ gEfiEventExitBootServicesGuid
diff --git a/ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.c b/ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.c new file mode 100644 index 0000000000..37d3e80c3c --- /dev/null +++ b/ArmPkg/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/ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.h b/ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.h new file mode 100644 index 0000000000..01db339108 --- /dev/null +++ b/ArmPkg/Library/ArmFfaLib/ArmFfaRxTxMap.h @@ -0,0 +1,71 @@ +/** @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_
+
+/**
+ * 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;
+
+/**
+ 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
|