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:
Levi Yun
2024-08-05 17:39:27 +01:00
committed by mergify[bot]
parent 18948c4a6a
commit 5d1b38dd07
7 changed files with 1386 additions and 0 deletions

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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