diff options
author | Levi Yun <yeoreum.yun@arm.com> | 2024-08-20 22:49:53 +0100 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2025-01-17 14:55:42 +0000 |
commit | 1c963008e8d7ec8b676478ab42ff40b41cb32be0 (patch) | |
tree | 8292a01c1b69159db2640d3cf94ac5297e3bec9e /StandaloneMmPkg | |
parent | 4ca452cf911311ceceebf7d259b67ee797db4433 (diff) | |
download | edk2-1c963008e8d7ec8b676478ab42ff40b41cb32be0.tar.gz |
StandaloneMm/Library: Apply FF-A v1.2 in StandaloneMm
To support the service other than Mmcommunication service,
StandaloneMm should use FF-A v1.2 or later [0].
For this, StandaloneMm needs to change:
1. apply FF-A boot protocol
- FF-A uses its own boot protocol and it can deliver phit hob.
So, StandaloneMm should understand FF-A boot protocol and
get phit hob from it to initialize.
2. Use DIRECT_REQ2 / DIRECT_RESP2
- To support the other service via FF-A protocol
than MmCommunication,
StandaloneMm should use DIRECT_REQ2 / DIRECT_RESP2.
In case of service provided with MmCommunication protocol,
register x2/x3 value is set as gEfiMmCommunication2ProtocolGuid and
register x4 value is set with MmCommunication Buffer
(ServiceTypeMmCommunication).
In case of service with each speicifiation via FF-A,
register x2/x3 value is set as each service guid
and StandaloneMmCoreEntryPoint genreates Mm communication header
with passed arguments to dispatch this service
provided by StandaloneMm.
i.e) Tpm service, Firmware update service and etc.
(ServiceTypeMisc)
Link: https://developer.arm.com/documentation/den0077/latest/ [0]
Signed-off-by: Levi Yun <yeoreum.yun@arm.com>
Diffstat (limited to 'StandaloneMmPkg')
4 files changed, 694 insertions, 183 deletions
diff --git a/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h b/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h index d6e6a8137e..7d6a993039 100644 --- a/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h +++ b/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h @@ -16,51 +16,124 @@ @par Reference(s):
- Transfer List [https://github.com/FirmwareHandoff/firmware_handoff]
- Secure Partition Manager [https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager-mm.html].
- - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/j/?lang=en]
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
**/
#ifndef __STANDALONEMMCORE_ENTRY_POINT_H__
#define __STANDALONEMMCORE_ENTRY_POINT_H__
+#include <Library/ArmSvcLib.h>
+#include <Library/ArmFfaLib.h>
#include <Library/PeCoffLib.h>
#include <Library/FvLib.h>
#define CPU_INFO_FLAG_PRIMARY_CPU 0x00000001
/*
- * BOOT protocol used to boot StandaloneMm
+ * Communication ABI protocol to communicate between normal/secure partition.
*/
typedef enum {
- /// Unknown Boot protocol.
- BootProtocolUnknown,
+ /// Unknown Communication ABI protocol
+ CommProtocolUnknown,
- /// Boot information delivered via Transfer List
- /// with 32 bits register convention
- BootProtocolTl32,
+ /// Communicate via SPM_MM ABI protocol
+ CommProtocolSpmMm,
- /// Boot information delivered via Transfer List
- /// with 64 bits register convention
- BootProtocolTl64,
+ /// Communicate via FF-A ABI protocol
+ CommProtocolFfa,
+
+ CommProtocolMax,
+} COMM_PROTOCOL;
+
+/** When using FF-A ABI, there're ways to request service to StandaloneMm
+ - FF-A with MmCommunication protocol.
+ - FF-A service with each specification.
+ MmCommunication Protocol can use FFA_MSG_SEND_DIRECT_REQ or REQ2,
+ Other FF-A services should use FFA_MSG_SEND_DIRECT_REQ2.
+ In case of FF-A with MmCommunication protocol via FFA_MSG_SEND_DIRECT_REQ,
+ register x3 saves Communication Buffer with gEfiMmCommunication2ProtocolGuid.
+ In case of FF-A with MmCommunication protocol via FFA_MSG_SEND_DIRECT_REQ2,
+ register x2/x3 save gEfiMmCommunication2ProtocolGuid and
+ register x4 saves Communication Buffer with Service Guid.
+
+ Other FF-A services (ServiceTypeMisc) delivers register values according to
+ there own service specification.
+ That means it doesn't use MmCommunication Buffer with MmCommunication Header
+ format.
+ (i.e) Tpm service via FF-A or Firmware Update service via FF-A.
+ To support latter services by StandaloneMm, it defines SERVICE_TYPE_MISC.
+ So that StandaloneMmEntryPointCore.c generates MmCommunication Header
+ with delivered register values to dispatch service provided StandaloneMmCore.
+ So that service handler can get proper information from delivered register.
+
+ In case of SPM_MM Abi, it only supports MmCommunication service.
+ */
+typedef enum {
+ /// Unknown
+ ServiceTypeUnknown,
- BootProtocolMax,
-} BOOT_PROTOCOL;
+ /// MmCommunication services
+ ServiceTypeMmCommunication,
-/*
- * Communication ABI protocol to communicate between normal/secure partition.
+ /// Misc services
+ ServiceTypeMisc,
+
+ ServiceTypeMax,
+} SERVICE_TYPE;
+
+/** Direct message request/response version
*/
typedef enum {
- /// Unknown Communication ABI protocol
- AbiProtocolUnknown,
+ /// Direct message version 1. Use FFA_DIRECT_MSG_REQ/RESP
+ DirectMsgV1,
- /// Communicate via SPM_MM ABI protocol
- AbiProtocolSpmMm,
+ /// Direct message version 2. Use FFA_DIRECT_MSG_REQ2/RESP2
+ DirectMsgV2,
- /// Communicate via FF-A ABI protocol
- AbiProtocolFfa,
+ DirectMsgMax,
+} DIRECT_MSG_VERSION;
- AbiProtocolMax,
-} ABI_PROTOCOL;
+/** Service table entry to return service type matched with service guid
+ */
+typedef struct ServiceTableEntry {
+ /// Service Guid
+ EFI_GUID *ServiceGuid;
+
+ /// Service Type
+ SERVICE_TYPE ServiceType;
+} SERVICE_TABLE_ENTRY;
+
+/** Ffa Abi data used in FFA_MSG_SEND_DIRECT_RESP/RESP2.
+ */
+typedef struct FfaMsgInfo {
+ /// Source partition id
+ UINT16 SourcePartId;
+
+ /// Destination partition id
+ UINT16 DestPartId;
+
+ /// Direct Message version
+ DIRECT_MSG_VERSION DirectMsgVersion;
+
+ /// Service Type
+ SERVICE_TYPE ServiceType;
+} FFA_MSG_INFO;
+
+/** MmCommunication Header for Misc service.
+ Misc service doesn't use MmCommunication Buffer.
+ This structure is used to dispatch Misc services by StandaloneMm.
+ */
+typedef struct {
+ /// Service guid
+ EFI_GUID HeaderGuid;
+
+ /// Length of Message. In case of misc service, sizeof (EventSvcArgs)
+ UINTN MessageLength;
+
+ /// Delivered register values.
+ DIRECT_MSG_ARGS DirectMsgArgs;
+} MISC_MM_COMMUNICATE_BUFFER;
typedef struct {
UINT8 Type; /* type of the structure */
@@ -144,12 +217,19 @@ LocateStandaloneMmCorePeCoffData ( );
/**
- The entry point of Standalone MM Foundation.
-
- @param [in] Arg0 Boot information passed according to boot protocol.
- @param [in] Arg1 Boot information passed according to boot protocol.
- @param [in] Arg2 Boot information passed according to boot protocol.
- @param [in] Arg3 Boot information passed according to boot protocol.
+ The handoff between the SPMC to StandaloneMM depends on the
+ communication interface between the SPMC and StandaloneMM.
+ When SpmMM is used, the handoff is implemented using the
+ Firmware Handoff protocol. When FF-A is used the FF-A boot
+ protocol is used.
+
+ @param [in] Arg0 In case of FF-A, address of FF-A boot information
+ In case of SPM_MM, this parameter must be zero
+ @param [in] Arg1 In case of FF-A, this parameter must be zero
+ In case of SPM_MM, Signature and register convention version
+ @param [in] Arg2 Must be zero
+ @param [in] Arg3 In case of FF-A, this parameter must be zero
+ In case of SPM_MM, address of transfer list
**/
VOID
diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c index 73ce025c3e..77d102279b 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c @@ -10,9 +10,13 @@ with management services running from an isolated Secure Partitions
at S-EL0, and the communication protocol is the Management Mode(MM)
interface.
+ - FF-A - Firmware Framework for Arm A-profile
@par Reference(s):
- - Secure Partition Manager [https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager-mm.html].
+ - Secure Partition Manager
+ [https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager-mm.html]
+ - Arm Firmware Framework for Arm A-Profile
+ [https://developer.arm.com/documentation/den0077/latest]
**/
@@ -22,11 +26,11 @@ #include <PiPei.h>
#include <Guid/MmramMemoryReserve.h>
-#include <Guid/MmCoreData.h>
#include <Guid/MpInformation.h>
#include <Library/ArmLib.h>
#include <Library/ArmSvcLib.h>
+#include <Library/ArmFfaLib.h>
#include <Library/ArmTransferListLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
@@ -39,6 +43,7 @@ #include <IndustryStandard/ArmStdSmc.h>
#include <IndustryStandard/ArmMmSvc.h>
#include <IndustryStandard/ArmFfaSvc.h>
+#include <IndustryStandard/ArmFfaBootInfo.h>
#include <Protocol/PiMmCpuDriverEp.h>
@@ -46,42 +51,43 @@ extern EFI_MM_SYSTEM_TABLE gMmCoreMmst; VOID *gHobList = NULL;
-STATIC MP_INFORMATION_HOB_DATA *mMpInfo = NULL;
+STATIC MP_INFORMATION_HOB_DATA *mMpInfo = NULL;
+STATIC MISC_MM_COMMUNICATE_BUFFER *mMiscMmCommunicateBuffer = NULL;
/**
- Get ABI protocol.
+ Get communication ABI protocol.
- @retval AbiProtocolSpmMm SPM_MM ABI
- @retval AbiProtocolFfa FF-A ABI
- @retval AbiProtocolUnknown Invalid ABI.
+ @param [out] CommProtocol Communication protocol.
+
+ @retval EFI_SUCCESS
+ @retval EFI_UNSUPPORTED Not supported
**/
STATIC
-ABI_PROTOCOL
+EFI_STATUS
EFIAPI
-GetAbiProtocol (
- IN VOID
+GetCommProtocol (
+ OUT COMM_PROTOCOL *CommProtocol
)
{
+ EFI_STATUS Status;
UINT16 RequestMajorVersion;
UINT16 RequestMinorVersion;
UINT16 CurrentMajorVersion;
UINT16 CurrentMinorVersion;
ARM_SVC_ARGS SvcArgs;
- ABI_PROTOCOL AbiProtocol;
-
- ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));
- SvcArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32;
- SvcArgs.Arg1 = ((SPM_MAJOR_VERSION_FFA << 16) | (SPM_MINOR_VERSION_FFA));
- ArmCallSvc (&SvcArgs);
+ RequestMajorVersion = ARM_FFA_MAJOR_VERSION;
+ RequestMinorVersion = ARM_FFA_MINOR_VERSION;
- if (SvcArgs.Arg0 != ARM_FFA_SPM_RET_NOT_SUPPORTED) {
- AbiProtocol = AbiProtocolFfa;
- RequestMajorVersion = SPM_MAJOR_VERSION_FFA;
- RequestMinorVersion = SPM_MINOR_VERSION_FFA;
- CurrentMajorVersion = ((SvcArgs.Arg0 >> 16) & 0xffff);
- CurrentMinorVersion = (SvcArgs.Arg0 & 0xffff);
+ Status = ArmFfaLibGetVersion (
+ RequestMajorVersion,
+ RequestMinorVersion,
+ &CurrentMajorVersion,
+ &CurrentMinorVersion
+ );
+ if (!EFI_ERROR (Status)) {
+ *CommProtocol = CommProtocolFfa;
} else {
ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));
SvcArgs.Arg0 = ARM_FID_SPM_MM_VERSION_AARCH32;
@@ -89,10 +95,11 @@ GetAbiProtocol ( ArmCallSvc (&SvcArgs);
if (SvcArgs.Arg0 == ARM_SPM_MM_RET_NOT_SUPPORTED) {
- return AbiProtocolUnknown;
+ *CommProtocol = CommProtocolUnknown;
+ return EFI_UNSUPPORTED;
}
- AbiProtocol = AbiProtocolSpmMm;
+ *CommProtocol = CommProtocolSpmMm;
RequestMajorVersion = ARM_SPM_MM_SUPPORT_MAJOR_VERSION;
RequestMinorVersion = ARM_SPM_MM_SUPPORT_MINOR_VERSION;
CurrentMajorVersion =
@@ -116,53 +123,51 @@ GetAbiProtocol ( "Incompatible %s Versions.\n" \
"Request Version: Major=0x%x, Minor>=0x%x.\n" \
"Current Version: Major=0x%x, Minor=0x%x.\n",
- (AbiProtocol == AbiProtocolFfa) ? L"FF-A" : L"SPM_MM",
+ (*CommProtocol == CommProtocolFfa) ? L"FF-A" : L"SPM_MM",
RequestMajorVersion,
RequestMinorVersion,
CurrentMajorVersion,
CurrentMinorVersion
));
- AbiProtocol = AbiProtocolUnknown;
- } else {
- DEBUG ((
- DEBUG_INFO,
- "%s Version: Major=0x%x, Minor=0x%x\n",
- (AbiProtocol == AbiProtocolFfa) ? L"FF-A" : L"SPM_MM",
- CurrentMajorVersion,
- CurrentMinorVersion
- ));
+
+ return EFI_UNSUPPORTED;
}
- return AbiProtocol;
+ DEBUG ((
+ DEBUG_INFO,
+ "%s Version: Major=0x%x, Minor=0x%x\n",
+ (*CommProtocol == CommProtocolFfa) ? L"FF-A" : L"SPM_MM",
+ CurrentMajorVersion,
+ CurrentMinorVersion
+ ));
+
+ return EFI_SUCCESS;
}
/**
- Get Boot protocol.
+ Validate Boot information when using SpmMm.
+ It should use Transfer list according to firmware handoff specification.
- @param[in] Arg0 Arg0 passed from firmware
- @param[in] Arg1 Arg1 passed from firmware
- @param[in] Arg2 Arg2 passed from firmware
- @param[in] Arg3 Arg3 passed from firmware
+ @param [in] Arg0 Should be 0x00 because we don't use device tree
+ @param [in] Fields Signature and register convention version
+ @param [in] Arg2 Should be 0x00 because we don't use device tree
+ @param [in] TlhAddr Address of transfer list
- @retval BootProtocolTl64 64 bits register convention transfer list
- @retval BootProtocolTl32 32 bits register convention transfer list
- @retval BootProtocolUnknown Invalid Boot protocol
+ @retval EFI_SUCCESS Valid boot information
+ @retval EFI_INVALID_PARAMETER Invalid boot information
**/
STATIC
-BOOT_PROTOCOL
+EFI_STATUS
EFIAPI
-GetBootProtocol (
- IN UINTN Arg0,
- IN UINTN Arg1,
- IN UINTN Arg2,
- IN UINTN Arg3
+ValidateSpmMmBootInfo (
+ IN UINTN Arg0,
+ IN UINT64 Fields,
+ IN UINTN Arg2,
+ IN UINTN TlhAddr
)
{
- UINTN RegVersion;
- UINT64 Fields;
-
- Fields = Arg1;
+ UINT64 RegVersion;
/*
* The signature value in x1's [23:0] bits is the same regardless of
@@ -172,32 +177,105 @@ GetBootProtocol ( * Please see:
* https://github.com/FirmwareHandoff/firmware_handoff/blob/main/source/register_conventions.rst
*/
- if ((Fields & TRANSFER_LIST_SIGNATURE_MASK_32) == TRANSFER_LIST_SIGNATURE_32) {
- if ((Fields & TRANSFER_LIST_SIGNATURE_MASK_64) == TRANSFER_LIST_SIGNATURE_64) {
- RegVersion = (Fields >> REGISTER_CONVENTION_VERSION_SHIFT_64) &
- REGISTER_CONVENTION_VERSION_MASK;
+ if ((Fields & TRANSFER_LIST_SIGNATURE_MASK_64) == TRANSFER_LIST_SIGNATURE_64) {
+ RegVersion = (Fields >> REGISTER_CONVENTION_VERSION_SHIFT_64) &
+ REGISTER_CONVENTION_VERSION_MASK;
+ if ((RegVersion != 1) || (Arg2 != 0x00) || (TlhAddr == 0x00)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else if ((Fields & TRANSFER_LIST_SIGNATURE_MASK_32) == TRANSFER_LIST_SIGNATURE_32) {
+ RegVersion = (Fields >> REGISTER_CONVENTION_VERSION_SHIFT_32) &
+ REGISTER_CONVENTION_VERSION_MASK;
+ if ((RegVersion != 1) || (Arg0 != 0x00) || (TlhAddr == 0x00)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
- if ((RegVersion != 1) || (Arg2 != 0x00) || (Arg3 == 0x00)) {
- goto err_out;
- }
+ return EFI_SUCCESS;
+}
- return BootProtocolTl64;
- } else {
- RegVersion = (Fields >> REGISTER_CONVENTION_VERSION_SHIFT_32) &
- REGISTER_CONVENTION_VERSION_MASK;
+/**
+ Validate Boot information when using FF-A.
- if ((RegVersion != 1) || (Arg0 != 0x00) || (Arg3 == 0x00)) {
- goto err_out;
- }
+ @param [in] FfaBootInfoHeaderAddr Address of FF-A boot information
- return BootProtocolTl32;
- }
+ @retval EFI_SUCCESS Valid boot information
+ @retval EFI_INVALID_PARAMETER Invalid boot information
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ValidateFfaBootInfo (
+ IN UINTN FfaBootInfoHeaderAddr
+ )
+{
+ EFI_FFA_BOOT_INFO_HEADER *FfaBootInfoHeader;
+
+ FfaBootInfoHeader = (EFI_FFA_BOOT_INFO_HEADER *)FfaBootInfoHeaderAddr;
+ if (FfaBootInfoHeader == NULL) {
+ DEBUG ((DEBUG_ERROR, "Error: No FF-A boot information...\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((FfaBootInfoHeader->Magic != FFA_BOOT_INFO_SIGNATURE) ||
+ (ARM_FFA_MAJOR_VERSION_GET (FfaBootInfoHeader->Version) <
+ ARM_FFA_MAJOR_VERSION) ||
+ (ARM_FFA_MINOR_VERSION_GET (FfaBootInfoHeader->Version) <
+ ARM_FFA_MINOR_VERSION))
+ {
+ DEBUG ((DEBUG_ERROR, "Error: Invalid FF-A boot information...\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Validate Boot information.
+
+ @param [in] CommProtocol Communication ABI protocol
+ @param [in] Arg0 In case of FF-A, address of FF-A boot information
+ In case of SPM_MM, 0x00
+ @param [in] Arg1 In case of FF-A, 0x00
+ In case of SPM_MM, Signature and register convention version
+ @param [in] Arg2 should be 0x00
+ @param [in] Arg3 In case of FF-A, it's 0x00
+ In case of SPM_MM, address of transfer list
+
+ @retval EFI_SUCCESS Valid boot information
+ @retval EFI_INVALID_PARAMETER Invalid boot information
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ValidateBootInfo (
+ IN COMM_PROTOCOL CommProtocol,
+ IN UINTN Arg0,
+ IN UINTN Arg1,
+ IN UINTN Arg2,
+ IN UINTN Arg3
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_INVALID_PARAMETER;
+
+ if (CommProtocol == CommProtocolSpmMm) {
+ Status = ValidateSpmMmBootInfo (Arg0, Arg1, Arg2, Arg3);
+ } else if (CommProtocol == CommProtocolFfa) {
+ /*
+ * In case of FF-A, Arg0 is set as FFA_BOOT_INFO address.
+ */
+ Status = ValidateFfaBootInfo (Arg0);
}
-err_out:
- DEBUG ((DEBUG_ERROR, "Error: Failed to get boot protocol!\n"));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Error: Failed to validate boot information!\n"));
+ }
- return BootProtocolUnknown;
+ return Status;
}
/**
@@ -235,9 +313,147 @@ GetPhitHobFromTransferList ( }
/**
- Get logical Cpu Number.
+ Get PHIT hob information from FF-A boot information.
+
+ @param[in] FfaBootInfoHeaderAddr FF-A boot information header address
+
+ @retval NULL Failed to get PHIT hob
+ @retval Address PHIT hob address
+
+**/
+STATIC
+VOID *
+EFIAPI
+GetPhitHobFromFfaBootInfo (
+ IN UINTN FfaBootInfoHeaderAddr
+ )
+{
+ EFI_FFA_BOOT_INFO_HEADER *FfaBootInfoHeader;
+ EFI_FFA_BOOT_INFO_DESC *FfaBootInfoDesc;
+ UINT32 Idx;
+
+ FfaBootInfoHeader = (EFI_FFA_BOOT_INFO_HEADER *)FfaBootInfoHeaderAddr;
+
+ for (Idx = 0; Idx < FfaBootInfoHeader->CountBootInfoDesc; Idx++) {
+ FfaBootInfoDesc = (EFI_FFA_BOOT_INFO_DESC *)((FfaBootInfoHeaderAddr +
+ FfaBootInfoHeader->OffsetBootInfoDesc) +
+ (Idx * FfaBootInfoHeader->SizeBootInfoDesc));
+
+ if ((FFA_BOOT_INFO_TYPE (FfaBootInfoDesc->Type) != FFA_BOOT_INFO_TYPE_STD) ||
+ (FFA_BOOT_INFO_TYPE_ID (FfaBootInfoDesc->Type) != FFA_BOOT_INFO_TYPE_ID_HOB) ||
+ (FFA_BOOT_INFO_FLAG_CONTENT (FfaBootInfoDesc->Flags) != FFA_BOOT_INFO_FLAG_CONTENT_ADDR))
+ {
+ continue;
+ }
+
+ return (VOID *)(UINTN)FfaBootInfoDesc->Content;
+ }
+
+ DEBUG ((DEBUG_ERROR, "Error: No Phit hob is present in FfaBootInfo...\n"));
+
+ return NULL;
+}
+
+/**
+ Get PHIT Hob from Boot information.
+
+ @param [in] CommProtocol Communication ABI protocol
+ @param [in] Arg0 In case of FF-A, address of FF-A boot information
+ In case of SPM_MM, 0x00 because we don't use device tree.
+ @param [in] Arg1 In case of FF-A, 0x00
+ In case of SPM_MM, Signature and register convention version
+ @param [in] Arg2 Should be 0x00 because we don't use device tree.
+ @param [in] Arg3 In case of FF-A, it's 0x00
+ In case of SPM_MM, address of transfer list
- @param [in] AbiProtocol Abi Protocol.
+ @retval NULL Failed to get PHIT hob
+ @retval Address PHIT hob address
+
+**/
+STATIC
+VOID *
+EFIAPI
+GetPhitHobFromBootInfo (
+ IN COMM_PROTOCOL CommProtocol,
+ IN UINTN Arg0,
+ IN UINTN Arg1,
+ IN UINTN Arg2,
+ IN UINTN Arg3
+ )
+{
+ EFI_STATUS Status;
+ VOID *HobStart;
+
+ Status = ValidateBootInfo (CommProtocol, Arg0, Arg1, Arg2, Arg3);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ if (CommProtocol == CommProtocolFfa) {
+ HobStart = GetPhitHobFromFfaBootInfo (Arg0);
+ } else {
+ HobStart = GetPhitHobFromTransferList (Arg3);
+ }
+
+ return HobStart;
+}
+
+/**
+ Get service type.
+ When using FF-A ABI, there're ways to request service to StandaloneMm
+ - FF-A with MmCommunication protocol.
+ - FF-A service with each specification.
+ MmCommunication Protocol can use FFA_MSG_SEND_DIRECT_REQ or REQ2,
+ Other FF-A services should use FFA_MSG_SEND_DIRECT_REQ2.
+ In case of FF-A with MmCommunication protocol via FFA_MSG_SEND_DIRECT_REQ,
+ register x3 saves Communication Buffer with gEfiMmCommunication2ProtocolGuid.
+ In case of FF-A with MmCommunication protocol via FFA_MSG_SEND_DIRECT_REQ2,
+ register x2/x3 save gEfiMmCommunication2ProtocolGuid and
+ register x4 saves Communication Buffer with Service Guid.
+
+ Other FF-A services (ServiceTypeMisc) delivers register values according to
+ there own service specification.
+ That means it doesn't use MmCommunication Buffer with MmCommunication Header
+ format.
+ (i.e) Tpm service via FF-A or Firmware Update service via FF-A.
+ To support latter services by StandaloneMm, it defines SERVICE_TYPE_MISC.
+ So that StandaloneMmEntryPointCore.c generates MmCommunication Header
+ with delivered register values to dispatch service provided StandaloneMmCore.
+ So that service handler can get proper information from delivered register.
+
+ In case of SPM_MM Abi, it only supports MmCommunication service.
+
+
+ @param[in] ServiceGuid Service Guid
+
+ @retval ServiceTypeMmCommunication Mm communication service
+ @retval ServiceTypeMisc Service via implemented defined
+ register ABI.
+ This will generate internal
+ MmCommunication Header
+ to dispatch service implemented
+ in standaloneMm
+ @retval ServiceTypeUnknown Not supported service.
+
+**/
+STATIC
+SERVICE_TYPE
+EFIAPI
+GetServiceType (
+ IN EFI_GUID *ServiceGuid
+ )
+{
+ if (CompareGuid (ServiceGuid, &gEfiMmCommunication2ProtocolGuid)) {
+ return ServiceTypeMmCommunication;
+ }
+
+ return ServiceTypeMisc;
+}
+
+/**
+ Get logical Cpu Number based on MpInformation hob data.
+
+ @param [in] CommProtocol Abi Protocol.
@param [in] EventCompleteSvcArgs Pointer to the event completion arguments.
@retval CpuNumber Cpu Number
@@ -246,16 +462,21 @@ STATIC UINTN
EFIAPI
GetCpuNumber (
- IN ABI_PROTOCOL AbiProtocol,
- IN ARM_SVC_ARGS *EventCompleteSvcArgs
+ IN COMM_PROTOCOL CommProtocol,
+ IN ARM_SVC_ARGS *EventCompleteSvcArgs
)
{
UINTN Idx;
- if (AbiProtocol == AbiProtocolSpmMm) {
+ if (CommProtocol == CommProtocolSpmMm) {
Idx = EventCompleteSvcArgs->Arg3;
} else {
- Idx = EventCompleteSvcArgs->Arg6;
+ /*
+ * There's no way to find out CPU number in StandaloneMm via FF-A v1.2.
+ * Because StandaloneMm is S-EL0 partition, it couldn't read mpidr.
+ * Currently, StandaloneMm is UP migratable SP so, just return idx 0.
+ */
+ Idx = 0;
}
ASSERT (Idx < mMpInfo->NumberOfProcessors);
@@ -428,7 +649,7 @@ DumpPhitHob ( }
/**
- Convert EFI_STATUS to SPM_MM return code.
+ Convert EFI_STATUS to MM SPM return code.
@param [in] Status edk2 status code.
@@ -457,44 +678,57 @@ EfiStatusToSpmMmStatus ( }
/**
- Convert EFI_STATUS to FFA return code.
-
- @param [in] Status edk2 status code.
+ Set svc arguments to report initialization status of StandaloneMm.
- @retval ARM_FFA_SPM_RET_* return value correspond to EFI_STATUS.
+ @param[in] CommProtocol ABI Protocol.
+ @param[in] Status Result of initializing StandaloneMm.
+ @param[out] EventCompleteSvcArgs Args structure.
**/
STATIC
-UINTN
-EFIAPI
-EfiStatusToFfaStatus (
- IN EFI_STATUS Status
+VOID
+ReturnInitStatusToSpmc (
+ IN COMM_PROTOCOL CommProtocol,
+ IN EFI_STATUS Status,
+ OUT ARM_SVC_ARGS *EventCompleteSvcArgs
)
{
- switch (Status) {
- case EFI_SUCCESS:
- return ARM_FFA_SPM_RET_SUCCESS;
- case EFI_INVALID_PARAMETER:
- return ARM_FFA_SPM_RET_INVALID_PARAMETERS;
- case EFI_OUT_OF_RESOURCES:
- return ARM_FFA_SPM_RET_NO_MEMORY;
- case EFI_ALREADY_STARTED:
- return ARM_FFA_SPM_RET_BUSY;
- case EFI_INTERRUPT_PENDING:
- return ARM_FFA_SPM_RET_INTERRUPTED;
- case EFI_ACCESS_DENIED:
- return ARM_FFA_SPM_RET_DENIED;
- case EFI_ABORTED:
- return ARM_FFA_SPM_RET_ABORTED;
- default:
- return ARM_FFA_SPM_RET_NOT_SUPPORTED;
+ ZeroMem (EventCompleteSvcArgs, sizeof (ARM_SVC_ARGS));
+
+ if (CommProtocol == CommProtocolFfa) {
+ if (EFI_ERROR (Status)) {
+ EventCompleteSvcArgs->Arg0 = ARM_FID_FFA_ERROR;
+
+ /*
+ * In case SvcConduit, this must be zero.
+ */
+ EventCompleteSvcArgs->Arg1 = 0x00;
+ EventCompleteSvcArgs->Arg2 = EfiStatusToFfaStatus (Status);
+ } else {
+ /*
+ * For completion of initialization, It should use FFA_MSG_WAIT.
+ * See FF-A specification 5.5 Protocol for completing execution context
+ * initialization
+ */
+ EventCompleteSvcArgs->Arg0 = ARM_FID_FFA_WAIT;
+ }
+ } else if (CommProtocol == CommProtocolSpmMm) {
+ EventCompleteSvcArgs->Arg0 = ARM_FID_SPM_MM_SP_EVENT_COMPLETE;
+ EventCompleteSvcArgs->Arg1 = EfiStatusToSpmMmStatus (Status);
+ } else {
+ /*
+ * We don't know what communication abi protocol is using.
+ * Set Arg0 as MAX_UINTN to make SPMC know it's error situation.
+ */
+ EventCompleteSvcArgs->Arg0 = MAX_UINTN;
}
}
/**
Set Event Complete arguments to be returned via SVC call.
- @param[in] AbiProtocol ABI Protocol.
+ @param[in] CommProtocol Communication Protocol.
+ @param[in] CommData Communication Abi specific data.
@param[in] Status Result of StandaloneMm service.
@param[out] EventCompleteSvcArgs Args structure.
@@ -502,17 +736,50 @@ EfiStatusToFfaStatus ( STATIC
VOID
SetEventCompleteSvcArgs (
- IN ABI_PROTOCOL AbiProtocol,
+ IN COMM_PROTOCOL CommProtocol,
+ IN VOID *CommData,
IN EFI_STATUS Status,
OUT ARM_SVC_ARGS *EventCompleteSvcArgs
)
{
+ FFA_MSG_INFO *FfaMsgInfo;
+
ZeroMem (EventCompleteSvcArgs, sizeof (ARM_SVC_ARGS));
- if (AbiProtocol == AbiProtocolFfa) {
- EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP;
- EventCompleteSvcArgs->Arg3 = ARM_FID_SPM_MM_SP_EVENT_COMPLETE;
- EventCompleteSvcArgs->Arg4 = EfiStatusToFfaStatus (Status);
+ if (CommProtocol == CommProtocolFfa) {
+ FfaMsgInfo = CommData;
+
+ if (EFI_ERROR (Status)) {
+ EventCompleteSvcArgs->Arg0 = ARM_FID_FFA_ERROR;
+
+ /*
+ * StandaloneMm is secure instance. So set as 0x00.
+ */
+ EventCompleteSvcArgs->Arg1 = 0x00;
+ EventCompleteSvcArgs->Arg2 = EfiStatusToFfaStatus (Status);
+ } else {
+ if (FfaMsgInfo->DirectMsgVersion == DirectMsgV1) {
+ EventCompleteSvcArgs->Arg0 = ARM_FID_FFA_MSG_SEND_DIRECT_RESP;
+ EventCompleteSvcArgs->Arg3 = ARM_FID_SPM_MM_SP_EVENT_COMPLETE;
+ } else {
+ EventCompleteSvcArgs->Arg0 = ARM_FID_FFA_MSG_SEND_DIRECT_RESP2;
+
+ if (FfaMsgInfo->ServiceType == ServiceTypeMisc) {
+ EventCompleteSvcArgs->Arg4 = mMiscMmCommunicateBuffer->DirectMsgArgs.Arg0;
+ EventCompleteSvcArgs->Arg5 = mMiscMmCommunicateBuffer->DirectMsgArgs.Arg1;
+ EventCompleteSvcArgs->Arg6 = mMiscMmCommunicateBuffer->DirectMsgArgs.Arg2;
+ EventCompleteSvcArgs->Arg7 = mMiscMmCommunicateBuffer->DirectMsgArgs.Arg3;
+ }
+ }
+
+ /*
+ * Swap source & dest partition id.
+ */
+ EventCompleteSvcArgs->Arg1 = PACK_PARTITION_ID_INFO (
+ FfaMsgInfo->DestPartId,
+ FfaMsgInfo->SourcePartId
+ );
+ }
} else {
EventCompleteSvcArgs->Arg0 = ARM_FID_SPM_MM_SP_EVENT_COMPLETE;
EventCompleteSvcArgs->Arg1 = EfiStatusToSpmMmStatus (Status);
@@ -520,9 +787,86 @@ SetEventCompleteSvcArgs ( }
/**
- A loop to delegated events.
+ Wrap Misc service buffer with MmCommunication Header to
+ patch event handler via MmCommunication protocol.
- @param [in] AbiProtocol Abi Protocol.
+ @param[in] EventSvcArgs Passed arguments
+ @param[in] ServiceGuid Service Guid
+ @param[out] Buffer Misc service data
+ wrapped with MmCommunication Header.
+
+**/
+STATIC
+VOID
+InitializeMiscMmCommunicateBuffer (
+ IN ARM_SVC_ARGS *EventSvcArgs,
+ IN EFI_GUID *ServiceGuid,
+ OUT MISC_MM_COMMUNICATE_BUFFER *Buffer
+ )
+{
+ ZeroMem (Buffer, sizeof (MISC_MM_COMMUNICATE_BUFFER));
+
+ Buffer->MessageLength = sizeof (DIRECT_MSG_ARGS);
+ Buffer->DirectMsgArgs.Arg0 = EventSvcArgs->Arg4;
+ Buffer->DirectMsgArgs.Arg1 = EventSvcArgs->Arg5;
+ Buffer->DirectMsgArgs.Arg2 = EventSvcArgs->Arg6;
+ Buffer->DirectMsgArgs.Arg3 = EventSvcArgs->Arg7;
+ CopyGuid (&Buffer->HeaderGuid, ServiceGuid);
+}
+
+/**
+ Convert UUID to EFI_GUID 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.
+
+ To patch mm-service properly, the passed uuid should be converted to
+ EFI_GUID format.
+
+ @param [in] Uuid Uuid
+ @param [out] Guid EFI_GUID
+
+**/
+STATIC
+VOID
+EFIAPI
+ConvertUuidToEfiGuid (
+ IN UINT64 *Uuid,
+ OUT EFI_GUID *Guid
+ )
+{
+ UINT32 *Data32;
+ UINT16 *Data16;
+
+ Data32 = (UINT32 *)Uuid;
+ Data32[0] = SwapBytes32 (Data32[0]);
+ Data16 = (UINT16 *)&Data32[1];
+ Data16[0] = SwapBytes16 (Data16[0]);
+ Data16[1] = SwapBytes16 (Data16[1]);
+ CopyGuid (Guid, (EFI_GUID *)Uuid);
+}
+
+/**
+ A loop to delegate events from SPMC.
+ DelegatedEventLoop() calls ArmCallSvc() to exit to SPMC.
+ When an event is delegated to StandaloneMm the SPMC returns control
+ to StandaloneMm by returning from the SVC call.
+
+ @param [in] CommProtocol Abi Protocol.
@param [in] CpuDriverEntryPoint Entry point to handle request.
@param [in] EventCompleteSvcArgs Pointer to the event completion arguments.
@@ -531,17 +875,26 @@ STATIC VOID
EFIAPI
DelegatedEventLoop (
- IN ABI_PROTOCOL AbiProtocol,
+ IN COMM_PROTOCOL CommProtocol,
IN EDKII_PI_MM_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint,
IN ARM_SVC_ARGS *EventCompleteSvcArgs
)
{
- EFI_STATUS Status;
- UINTN CpuNumber;
- UINTN CommBufferAddr;
+ EFI_STATUS Status;
+ UINTN CpuNumber;
+ UINT64 Uuid[2];
+ VOID *CommData;
+ FFA_MSG_INFO FfaMsgInfo;
+ EFI_GUID ServiceGuid;
+ SERVICE_TYPE ServiceType;
+ UINTN CommBufferAddr;
+
+ CommData = NULL;
while (TRUE) {
+ // Exit to SPMC.
ArmCallSvc (EventCompleteSvcArgs);
+ // Enter from SPMC.
DEBUG ((DEBUG_INFO, "Received delegated event\n"));
DEBUG ((DEBUG_INFO, "X0 : 0x%x\n", (UINT32)EventCompleteSvcArgs->Arg0));
@@ -553,22 +906,70 @@ DelegatedEventLoop ( DEBUG ((DEBUG_INFO, "X6 : 0x%x\n", (UINT32)EventCompleteSvcArgs->Arg6));
DEBUG ((DEBUG_INFO, "X7 : 0x%x\n", (UINT32)EventCompleteSvcArgs->Arg7));
- CpuNumber = GetCpuNumber (AbiProtocol, EventCompleteSvcArgs);
+ CpuNumber = GetCpuNumber (CommProtocol, EventCompleteSvcArgs);
DEBUG ((DEBUG_INFO, "CpuNumber: %d\n", CpuNumber));
- if (AbiProtocol == AbiProtocolFfa) {
- if (EventCompleteSvcArgs->Arg0 != ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ) {
+ if (CommProtocol == CommProtocolFfa) {
+ /*
+ * Register Convention for FF-A
+ * Arg0: ARM_FID_FFA_MSG_SEND_DIRECT_REQ/REQ2
+ * Arg1: Sender and Receiver endpoint IDs.
+ * Arg2: Message Flags for ARM_FID_FFA_MSG_SEND_DIRECT_REQ
+ * Low 8 bytes of UUID for ARM_FID_FFA_MSG_SEND_DIRECT_REQ2
+ * Arg3: Implementation Defined for ARM_FID_FFA_MSG_SEND_DIRECT_REQ
+ * High 8 bytes of UUID for ARM_FID_FFA_MSG_SEND_DIRECT_REQ2
+ * Others: Implementation Defined.
+ *
+ * See Arm Firmware Framework for Arm A-Profile for detail.
+ */
+ FfaMsgInfo.SourcePartId = GET_SOURCE_PARTITION_ID (EventCompleteSvcArgs->Arg1);
+ FfaMsgInfo.DestPartId = GET_DEST_PARTITION_ID (EventCompleteSvcArgs->Arg1);
+ CommData = &FfaMsgInfo;
+
+ if (EventCompleteSvcArgs->Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ) {
+ FfaMsgInfo.DirectMsgVersion = DirectMsgV1;
+ ServiceType = ServiceTypeMmCommunication;
+ } else if (EventCompleteSvcArgs->Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ2) {
+ FfaMsgInfo.DirectMsgVersion = DirectMsgV2;
+ Uuid[0] = EventCompleteSvcArgs->Arg2;
+ Uuid[1] = EventCompleteSvcArgs->Arg3;
+ ConvertUuidToEfiGuid (Uuid, &ServiceGuid);
+ ServiceType = GetServiceType (&ServiceGuid);
+ } else {
Status = EFI_INVALID_PARAMETER;
DEBUG ((
DEBUG_ERROR,
"Error: Unrecognized FF-A Id: 0x%x\n",
EventCompleteSvcArgs->Arg0
));
- goto event_complete;
+ goto ExitHandler;
}
- CommBufferAddr = EventCompleteSvcArgs->Arg3;
- } else {
+ FfaMsgInfo.ServiceType = ServiceType;
+
+ if (ServiceType == ServiceTypeMmCommunication) {
+ if (FfaMsgInfo.DirectMsgVersion == DirectMsgV1) {
+ CommBufferAddr = EventCompleteSvcArgs->Arg3;
+ } else {
+ CommBufferAddr = EventCompleteSvcArgs->Arg4;
+ }
+ } else if (ServiceType == ServiceTypeMisc) {
+ /*
+ * In case of Misc service, generate mm communication header
+ * to dispatch service via StandaloneMmCore.
+ */
+ InitializeMiscMmCommunicateBuffer (
+ EventCompleteSvcArgs,
+ &ServiceGuid,
+ mMiscMmCommunicateBuffer
+ );
+ CommBufferAddr = (UINTN)mMiscMmCommunicateBuffer;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((DEBUG_ERROR, "Error: Invalid FF-A Service...\n"));
+ goto ExitHandler;
+ }
+ } else if (CommProtocol == CommProtocolSpmMm) {
/*
* Register Convention for SPM_MM
* Arg0: ARM_SMC_ID_MM_COMMUNICATE
@@ -585,13 +986,14 @@ DelegatedEventLoop ( "Error: Unrecognized SPM_MM Id: 0x%x\n",
EventCompleteSvcArgs->Arg0
));
- goto event_complete;
+ goto ExitHandler;
}
CommBufferAddr = EventCompleteSvcArgs->Arg1;
+ ServiceType = ServiceTypeMmCommunication;
}
- Status = CpuDriverEntryPoint (EventCompleteSvcArgs->Arg0, CpuNumber, CommBufferAddr);
+ Status = CpuDriverEntryPoint ((UINTN)ServiceType, CpuNumber, CommBufferAddr);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
@@ -601,22 +1003,30 @@ DelegatedEventLoop ( ));
}
-event_complete:
+ExitHandler:
SetEventCompleteSvcArgs (
- AbiProtocol,
+ CommProtocol,
+ CommData,
Status,
EventCompleteSvcArgs
);
- }
+ } // while
}
/**
- The entry point of Standalone MM Foundation.
-
- @param [in] Arg0 Boot information passed according to boot protocol.
- @param [in] Arg1 Boot information passed according to boot protocol.
- @param [in] Arg2 Boot information passed according to boot protocol.
- @param [in] Arg3 Boot information passed according to boot protocol.
+ The handoff between the SPMC to StandaloneMM depends on the
+ communication interface between the SPMC and StandaloneMM.
+ When SpmMM is used, the handoff is implemented using the
+ Firmware Handoff protocol. When FF-A is used the FF-A boot
+ protocol is used.
+
+ @param [in] Arg0 In case of FF-A, address of FF-A boot information
+ In case of SPM_MM, this parameter must be zero
+ @param [in] Arg1 In case of FF-A, this parameter must be zero
+ In case of SPM_MM, Signature and register convention version
+ @param [in] Arg2 Must be zero
+ @param [in] Arg3 In case of FF-A, this parameter must be zero
+ In case of SPM_MM, address of transfer list
**/
VOID
@@ -633,8 +1043,7 @@ _ModuleEntryPoint ( EFI_STATUS Status;
UINT32 SectionHeaderOffset;
UINT16 NumberOfSections;
- BOOT_PROTOCOL BootProtocol;
- ABI_PROTOCOL AbiProtocol;
+ COMM_PROTOCOL CommProtocol;
VOID *HobStart;
VOID *TeData;
UINTN TeDataSize;
@@ -648,22 +1057,12 @@ _ModuleEntryPoint ( CpuDriverEntryPoint = NULL;
- AbiProtocol = GetAbiProtocol ();
- if (AbiProtocol == AbiProtocolUnknown) {
- Status = EFI_UNSUPPORTED;
- goto finish;
- }
-
- /**
- * Check boot information
- */
- BootProtocol = GetBootProtocol (Arg0, Arg1, Arg2, Arg3);
- if (BootProtocol == BootProtocolUnknown) {
- Status = EFI_UNSUPPORTED;
+ Status = GetCommProtocol (&CommProtocol);
+ if (EFI_ERROR (Status)) {
goto finish;
}
- HobStart = GetPhitHobFromTransferList (Arg3);
+ HobStart = GetPhitHobFromBootInfo (CommProtocol, Arg0, Arg1, Arg2, Arg3);
if (HobStart == NULL) {
Status = EFI_UNSUPPORTED;
goto finish;
@@ -739,6 +1138,8 @@ _ModuleEntryPoint ( ASSERT_EFI_ERROR (Status);
}
+ // Set the gHobList to point to the HOB list passed by TF-A.
+ // This will be used by StandaloneMmCoreHobLib in early stage.
gHobList = HobStart;
//
@@ -746,9 +1147,14 @@ _ModuleEntryPoint ( //
ProcessModuleEntryPointList (HobStart);
- //
- // Find HobList to check gEfiHobList is installed.
- //
+ // ProcessModuleEntryPointList() copies the HOB List passed
+ // by TF-A, i.e. HobStart, in the ConfigurationTable[].
+ // Therefore, find the HobList in the ConfigurationTable[] by
+ // searching for the gEfiHobListGuid.
+ // Also update the gHobList to point to the HobList in the
+ // ConfigurationTable[] as the HobList passed by TF-A can
+ // be overwritten by StMM after StMM Core is initialised, i.e.
+ // after the MM Core entry point is called.
Status = EFI_NOT_FOUND;
ConfigurationTable = gMmCoreMmst.MmConfigurationTable;
for (Idx = 0; Idx < gMmCoreMmst.NumberOfTableEntries; Idx++) {
@@ -763,14 +1169,16 @@ _ModuleEntryPoint ( goto finish;
}
+ // Set the gHobList to point to the HOB list saved in ConfigurationTable[].
+ gHobList = ConfigurationTable[Idx].VendorTable;
+
//
// Find MpInformation Hob in HobList.
// It couldn't save address of mp information in gHobList
// because that memory area will be reused after StandaloneMm finishing
// initialization.
//
- HobStart = ConfigurationTable[Idx].VendorTable;
- GuidHob = GetNextGuidHob (&gMpInformationHobGuid, HobStart);
+ GuidHob = GetNextGuidHob (&gMpInformationHobGuid, gHobList);
if (GuidHob == NULL) {
Status = EFI_NOT_FOUND;
DEBUG ((DEBUG_ERROR, "Error: No MpInformation hob ...\n"));
@@ -800,7 +1208,24 @@ _ModuleEntryPoint ( CpuDriverEntryPoint
));
+ if (CommProtocol == CommProtocolFfa) {
+ Status = gMmCoreMmst.MmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (MISC_MM_COMMUNICATE_BUFFER),
+ (VOID **)&mMiscMmCommunicateBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Error: Failed to allocate misc mm communication buffer...\n"
+ ));
+ goto finish;
+ }
+ }
+
finish:
- SetEventCompleteSvcArgs (AbiProtocol, Status, &EventCompleteSvcArgs);
- DelegatedEventLoop (AbiProtocol, CpuDriverEntryPoint, &EventCompleteSvcArgs);
+ ReturnInitStatusToSpmc (CommProtocol, Status, &EventCompleteSvcArgs);
+
+ // Call DelegateEventLoop(), this function never returns.
+ DelegatedEventLoop (CommProtocol, CpuDriverEntryPoint, &EventCompleteSvcArgs);
}
diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf index 0507e9f035..80740245e9 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf @@ -44,6 +44,7 @@ StandaloneMmMmuLib
ArmSvcLib
ArmTransferListLib
+ ArmFfaLib
[Guids]
gMpInformationHobGuid
@@ -55,6 +56,7 @@ [Protocols.ARM, Protocols.AARCH64]
gEdkiiPiMmCpuDriverEpProtocolGuid
+ gEfiMmCommunication2ProtocolGuid
#
# This configuration fails for CLANGPDB, which does not support PIE in the GCC
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/StandaloneMmPkg.dsc index cf2075eaf3..91e24e6c04 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dsc +++ b/StandaloneMmPkg/StandaloneMmPkg.dsc @@ -75,6 +75,7 @@ [LibraryClasses.AARCH64, LibraryClasses.ARM]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf
+ ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
PeCoffExtraActionLib|StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
@@ -84,6 +85,9 @@ HobLib|StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
ArmFfaLib|ArmPkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf
+[LibraryClasses.AARCH64.MM_CORE_STANDALONE, LibraryClasses.ARM.MM_CORE_STANDALONE]
+ ArmFfaLib|ArmPkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf
+
[LibraryClasses.common.MM_STANDALONE]
MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
|