mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-30 09:04:07 +02:00
ArmPkg/MmCommunicationDxe: Mmcommunication via FF-A
Support Mmcommunication protocol via FF-A with StandaloneMm. Signed-off-by: Levi Yun <yeoreum.yun@arm.com>
This commit is contained in:
parent
1c963008e8
commit
9f9a3de9e4
@ -5,8 +5,8 @@
|
|||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <Library/ArmLib.h>
|
#include <Library/ArmLib.h>
|
||||||
|
#include <Library/ArmFfaLib.h>
|
||||||
#include <Library/ArmSmcLib.h>
|
#include <Library/ArmSmcLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
@ -19,9 +19,16 @@
|
|||||||
#include <Protocol/MmCommunication2.h>
|
#include <Protocol/MmCommunication2.h>
|
||||||
|
|
||||||
#include <IndustryStandard/ArmStdSmc.h>
|
#include <IndustryStandard/ArmStdSmc.h>
|
||||||
|
#include <IndustryStandard/ArmFfaSvc.h>
|
||||||
|
|
||||||
#include "MmCommunicate.h"
|
#include "MmCommunicate.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Partition ID if FF-A support is enabled
|
||||||
|
//
|
||||||
|
STATIC UINT16 mPartId;
|
||||||
|
STATIC UINT16 mStMmPartId;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Address, Length of the pre-allocated buffer for communication with the secure
|
// Address, Length of the pre-allocated buffer for communication with the secure
|
||||||
// world.
|
// world.
|
||||||
@ -36,6 +43,99 @@ STATIC EFI_EVENT mSetVirtualAddressMapEvent;
|
|||||||
//
|
//
|
||||||
STATIC EFI_HANDLE mMmCommunicateHandle;
|
STATIC EFI_HANDLE mMmCommunicateHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send mm communicate request via FF-A.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS
|
||||||
|
@retval Others Error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SendFfaMmCommunicate (
|
||||||
|
IN VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
DIRECT_MSG_ARGS CommunicateArgs;
|
||||||
|
|
||||||
|
ZeroMem (&CommunicateArgs, sizeof (DIRECT_MSG_ARGS));
|
||||||
|
|
||||||
|
CommunicateArgs.Arg0 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
|
||||||
|
|
||||||
|
Status = ArmFfaLibMsgSendDirectReq (
|
||||||
|
mStMmPartId,
|
||||||
|
0,
|
||||||
|
&CommunicateArgs
|
||||||
|
);
|
||||||
|
|
||||||
|
while (Status == EFI_INTERRUPT_PENDING) {
|
||||||
|
// We are assuming vCPU0 of the StMM SP since it is UP.
|
||||||
|
Status = ArmFfaLibRun (mStMmPartId, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send mm communicate request via SPM_MM.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS
|
||||||
|
@retval Others Error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SendSpmMmCommunicate (
|
||||||
|
IN VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
ARM_SMC_ARGS CommunicateSmcArgs;
|
||||||
|
|
||||||
|
ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
|
||||||
|
|
||||||
|
// SMC Function ID
|
||||||
|
CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
|
||||||
|
|
||||||
|
// Cookie
|
||||||
|
CommunicateSmcArgs.Arg1 = 0;
|
||||||
|
|
||||||
|
// comm_buffer_address (64-bit physical address)
|
||||||
|
CommunicateSmcArgs.Arg2 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
|
||||||
|
|
||||||
|
// comm_size_address (not used, indicated by setting to zero)
|
||||||
|
CommunicateSmcArgs.Arg3 = 0;
|
||||||
|
|
||||||
|
// Call the Standalone MM environment.
|
||||||
|
ArmCallSmc (&CommunicateSmcArgs);
|
||||||
|
|
||||||
|
switch (CommunicateSmcArgs.Arg0) {
|
||||||
|
case ARM_SMC_MM_RET_SUCCESS:
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
break;
|
||||||
|
case ARM_SMC_MM_RET_INVALID_PARAMS:
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
case ARM_SMC_MM_RET_DENIED:
|
||||||
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
break;
|
||||||
|
case ARM_SMC_MM_RET_NO_MEMORY:
|
||||||
|
// Unexpected error since the CommSize was checked for zero length
|
||||||
|
// prior to issuing the SMC
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
ASSERT (0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
ASSERT (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Communicates with a registered handler.
|
Communicates with a registered handler.
|
||||||
|
|
||||||
@ -76,15 +176,12 @@ MmCommunication2Communicate (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
|
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
|
||||||
ARM_SMC_ARGS CommunicateSmcArgs;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINTN BufferSize;
|
UINTN BufferSize;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
Status = EFI_ACCESS_DENIED;
|
Status = EFI_ACCESS_DENIED;
|
||||||
BufferSize = 0;
|
BufferSize = 0;
|
||||||
|
|
||||||
ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check parameters
|
// Check parameters
|
||||||
//
|
//
|
||||||
@ -139,26 +236,16 @@ MmCommunication2Communicate (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SMC Function ID
|
|
||||||
CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
|
|
||||||
|
|
||||||
// Cookie
|
|
||||||
CommunicateSmcArgs.Arg1 = 0;
|
|
||||||
|
|
||||||
// Copy Communication Payload
|
// Copy Communication Payload
|
||||||
CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBufferVirtual, BufferSize);
|
CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBufferVirtual, BufferSize);
|
||||||
|
|
||||||
// comm_buffer_address (64-bit physical address)
|
if (IsFfaSupported ()) {
|
||||||
CommunicateSmcArgs.Arg2 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
|
Status = SendFfaMmCommunicate ();
|
||||||
|
} else {
|
||||||
|
Status = SendSpmMmCommunicate ();
|
||||||
|
}
|
||||||
|
|
||||||
// comm_size_address (not used, indicated by setting to zero)
|
if (!EFI_ERROR (Status)) {
|
||||||
CommunicateSmcArgs.Arg3 = 0;
|
|
||||||
|
|
||||||
// Call the Standalone MM environment.
|
|
||||||
ArmCallSmc (&CommunicateSmcArgs);
|
|
||||||
|
|
||||||
switch (CommunicateSmcArgs.Arg0) {
|
|
||||||
case ARM_SMC_MM_RET_SUCCESS:
|
|
||||||
ZeroMem (CommBufferVirtual, BufferSize);
|
ZeroMem (CommBufferVirtual, BufferSize);
|
||||||
// On successful return, the size of data being returned is inferred from
|
// On successful return, the size of data being returned is inferred from
|
||||||
// MessageLength + Header.
|
// MessageLength + Header.
|
||||||
@ -166,33 +253,23 @@ MmCommunication2Communicate (
|
|||||||
BufferSize = CommunicateHeader->MessageLength +
|
BufferSize = CommunicateHeader->MessageLength +
|
||||||
sizeof (CommunicateHeader->HeaderGuid) +
|
sizeof (CommunicateHeader->HeaderGuid) +
|
||||||
sizeof (CommunicateHeader->MessageLength);
|
sizeof (CommunicateHeader->MessageLength);
|
||||||
|
if (BufferSize > mNsCommBuffMemRegion.Length) {
|
||||||
|
// Something bad has happened, we should have landed in ARM_SMC_MM_RET_NO_MEMORY
|
||||||
|
Status = EFI_BAD_BUFFER_SIZE;
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"%a Returned buffer exceeds communication buffer limit. Has: 0x%llx vs. max: 0x%llx!\n",
|
||||||
|
__func__,
|
||||||
|
BufferSize,
|
||||||
|
(UINTN)mNsCommBuffMemRegion.Length
|
||||||
|
));
|
||||||
|
} else {
|
||||||
CopyMem (
|
CopyMem (
|
||||||
CommBufferVirtual,
|
CommBufferVirtual,
|
||||||
(VOID *)mNsCommBuffMemRegion.VirtualBase,
|
(VOID *)mNsCommBuffMemRegion.VirtualBase,
|
||||||
BufferSize
|
BufferSize
|
||||||
);
|
);
|
||||||
Status = EFI_SUCCESS;
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case ARM_SMC_MM_RET_INVALID_PARAMS:
|
|
||||||
Status = EFI_INVALID_PARAMETER;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ARM_SMC_MM_RET_DENIED:
|
|
||||||
Status = EFI_ACCESS_DENIED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ARM_SMC_MM_RET_NO_MEMORY:
|
|
||||||
// Unexpected error since the CommSize was checked for zero length
|
|
||||||
// prior to issuing the SMC
|
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
|
||||||
ASSERT (0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Status = EFI_ACCESS_DENIED;
|
|
||||||
ASSERT (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
@ -243,9 +320,15 @@ NotifySetVirtualAddressMap (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check mm communication compatibility when use SPM_MM.
|
||||||
|
|
||||||
|
**/
|
||||||
STATIC
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
GetMmCompatibility (
|
GetMmCompatibility (
|
||||||
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
@ -257,6 +340,10 @@ GetMmCompatibility (
|
|||||||
|
|
||||||
ArmCallSmc (&MmVersionArgs);
|
ArmCallSmc (&MmVersionArgs);
|
||||||
|
|
||||||
|
if (MmVersionArgs.Arg0 == ARM_SMC_MM_RET_NOT_SUPPORTED) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
MmVersion = MmVersionArgs.Arg0;
|
MmVersion = MmVersionArgs.Arg0;
|
||||||
|
|
||||||
if ((MM_MAJOR_VER (MmVersion) == MM_CALLER_MAJOR_VER) &&
|
if ((MM_MAJOR_VER (MmVersion) == MM_CALLER_MAJOR_VER) &&
|
||||||
@ -284,6 +371,174 @@ GetMmCompatibility (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check mm communication compatibility when use FF-A.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
GetFfaCompatibility (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT16 CurrentMajorVersion;
|
||||||
|
UINT16 CurrentMinorVersion;
|
||||||
|
|
||||||
|
Status = ArmFfaLibGetVersion (
|
||||||
|
ARM_FFA_MAJOR_VERSION,
|
||||||
|
ARM_FFA_MINOR_VERSION,
|
||||||
|
&CurrentMajorVersion,
|
||||||
|
&CurrentMinorVersion
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Failed to get FF-A version. Status: %r\n", Status));
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ARM_FFA_MAJOR_VERSION != CurrentMajorVersion) ||
|
||||||
|
(ARM_FFA_MINOR_VERSION > CurrentMinorVersion))
|
||||||
|
{
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"Incompatible FF-A Versions for MM_COMM.\n" \
|
||||||
|
"Request Version: Major=0x%x, Minor=0x%x.\n" \
|
||||||
|
"Current Version: Major=0x%x, Minor>=0x%x.\n",
|
||||||
|
ARM_FFA_MAJOR_VERSION,
|
||||||
|
ARM_FFA_MINOR_VERSION,
|
||||||
|
CurrentMajorVersion,
|
||||||
|
CurrentMinorVersion
|
||||||
|
));
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"FF-A Version for MM_COMM: Major=0x%x, Minor=0x%x\n",
|
||||||
|
CurrentMajorVersion,
|
||||||
|
CurrentMinorVersion
|
||||||
|
));
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize communication via FF-A.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
InitializeFfaCommunication (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *TxBuffer;
|
||||||
|
UINT64 TxBufferSize;
|
||||||
|
VOID *RxBuffer;
|
||||||
|
UINT64 RxBufferSize;
|
||||||
|
EFI_FFA_PART_INFO_DESC *StmmPartInfo;
|
||||||
|
UINT32 Count;
|
||||||
|
UINT32 Size;
|
||||||
|
|
||||||
|
Status = ArmFfaLibPartitionIdGet (&mPartId);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"Failed to get partition id. Status: %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ArmFfaLibGetRxTxBuffers (
|
||||||
|
&TxBuffer,
|
||||||
|
&TxBufferSize,
|
||||||
|
&RxBuffer,
|
||||||
|
&RxBufferSize
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"Failed to get Rx/Tx Buffer. Status: %r\n",
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ArmFfaLibPartitionInfoGet (
|
||||||
|
&gEfiMmCommunication2ProtocolGuid,
|
||||||
|
FFA_PART_INFO_FLAG_TYPE_DESC,
|
||||||
|
&Count,
|
||||||
|
&Size
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"Failed to get Stmm(%g) partition Info. Status: %r\n",
|
||||||
|
&gEfiMmCommunication2ProtocolGuid,
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Count != 1) || (Size < sizeof (EFI_FFA_PART_INFO_DESC))) {
|
||||||
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_ERROR,
|
||||||
|
"Invalid partition Info(%g). Count: %d, Size: %d\n",
|
||||||
|
&gEfiMmCommunication2ProtocolGuid,
|
||||||
|
Count,
|
||||||
|
Size
|
||||||
|
));
|
||||||
|
goto ErrorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
StmmPartInfo = (EFI_FFA_PART_INFO_DESC *)RxBuffer;
|
||||||
|
|
||||||
|
if ((StmmPartInfo->PartitionProps & FFA_PART_PROP_RECV_DIRECT_REQ) == 0x00) {
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
DEBUG ((DEBUG_ERROR, "StandaloneMm doesn't receive DIRECT_MSG_REQ...\n"));
|
||||||
|
goto ErrorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
mStMmPartId = StmmPartInfo->PartitionId;
|
||||||
|
|
||||||
|
ErrorHandler:
|
||||||
|
ArmFfaLibRxRelease (mPartId);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize mm communication.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
InitializeCommunication (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (IsFfaSupported ()) {
|
||||||
|
Status = GetFfaCompatibility ();
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Status = InitializeFfaCommunication ();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Status = GetMmCompatibility ();
|
||||||
|
// No further initialisation required for SpmMM
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC EFI_GUID *CONST mGuidedEventGuid[] = {
|
STATIC EFI_GUID *CONST mGuidedEventGuid[] = {
|
||||||
&gEfiEndOfDxeEventGroupGuid,
|
&gEfiEndOfDxeEventGroupGuid,
|
||||||
&gEfiEventExitBootServicesGuid,
|
&gEfiEventExitBootServicesGuid,
|
||||||
@ -345,8 +600,8 @@ MmCommunication2Initialize (
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
|
||||||
// Check if we can make the MM call
|
// Initialize to make mm communication
|
||||||
Status = GetMmCompatibility ();
|
Status = InitializeCommunication ();
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
goto ReturnErrorStatus;
|
goto ReturnErrorStatus;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
ArmLib
|
ArmLib
|
||||||
|
ArmFfaLib
|
||||||
ArmSmcLib
|
ArmSmcLib
|
||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
DebugLib
|
DebugLib
|
||||||
|
Loading…
x
Reference in New Issue
Block a user