ArmPkg: Add ArmFfaLib used in Dxe driver
Add ArmFfaLib used in Dxe driver Signed-off-by: Levi Yun <yeoreum.yun@arm.com>
This commit is contained in:
parent
18948c4a6a
commit
5d1b38dd07
|
@ -70,6 +70,7 @@
|
||||||
ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
|
ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
|
||||||
ArmGicArchLib|ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
|
ArmGicArchLib|ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
|
||||||
ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf
|
ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf
|
||||||
|
ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
|
||||||
ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
|
ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
|
||||||
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
|
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
|
||||||
OpteeLib|ArmPkg/Library/OpteeLib/OpteeLib.inf
|
OpteeLib|ArmPkg/Library/OpteeLib/OpteeLib.inf
|
||||||
|
@ -87,6 +88,7 @@
|
||||||
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
|
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
|
||||||
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
|
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
|
||||||
ArmTransferListLib|ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
|
ArmTransferListLib|ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
|
||||||
|
ArmFfaLib|ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
|
||||||
|
|
||||||
ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
|
ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
|
||||||
|
|
||||||
|
@ -131,6 +133,7 @@
|
||||||
ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
|
ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
|
||||||
ArmPkg/Library/OpteeLib/OpteeLib.inf
|
ArmPkg/Library/OpteeLib/OpteeLib.inf
|
||||||
ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
|
ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
|
||||||
|
ArmPkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
|
||||||
|
|
||||||
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
|
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
Loading…
Reference in New Issue