From a776bbabd9e8f370feb089cdc016324b1d6a37c7 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 9 Aug 2021 17:19:46 +0200 Subject: StandaloneMmPkg: build for 32bit arm machines This change allows to build StandaloneMmPkg components for 32bit Arm StandaloneMm firmware. This change mainly moves AArch64/ source files to Arm/ side directory for several components: StandaloneMmCpu, StandaloneMmCoreEntryPoint and StandaloneMmMemLib. The source file is built for both 32b and 64b Arm targets. Signed-off-by: Etienne Carriere Reviewed-by: Ard Biesheuvel --- StandaloneMmPkg/Core/StandaloneMmCore.inf | 2 +- .../Drivers/StandaloneMmCpu/AArch64/EventHandle.c | 250 ------------- .../StandaloneMmCpu/AArch64/StandaloneMmCpu.c | 250 ------------- .../StandaloneMmCpu/AArch64/StandaloneMmCpu.h | 81 ---- .../StandaloneMmCpu/AArch64/StandaloneMmCpu.inf | 52 --- .../Drivers/StandaloneMmCpu/EventHandle.c | 251 +++++++++++++ .../Drivers/StandaloneMmCpu/StandaloneMmCpu.c | 250 +++++++++++++ .../Drivers/StandaloneMmCpu/StandaloneMmCpu.h | 81 ++++ .../Drivers/StandaloneMmCpu/StandaloneMmCpu.inf | 52 +++ .../Library/AArch64/StandaloneMmCoreEntryPoint.h | 216 ----------- .../Library/Arm/StandaloneMmCoreEntryPoint.h | 216 +++++++++++ .../AArch64/CreateHobList.c | 205 ---------- .../AArch64/SetPermissions.c | 322 ---------------- .../AArch64/StandaloneMmCoreEntryPoint.c | 413 --------------------- .../StandaloneMmCoreEntryPoint/Arm/CreateHobList.c | 205 ++++++++++ .../Arm/SetPermissions.c | 322 ++++++++++++++++ .../Arm/StandaloneMmCoreEntryPoint.c | 413 +++++++++++++++++++++ .../StandaloneMmCoreEntryPoint.inf | 14 +- .../AArch64/StandaloneMmCoreHobLib.c | 330 ---------------- .../AArch64/StandaloneMmCoreHobLibInternal.c | 58 --- .../Arm/StandaloneMmCoreHobLib.c | 330 ++++++++++++++++ .../Arm/StandaloneMmCoreHobLibInternal.c | 58 +++ .../StandaloneMmCoreHobLib.inf | 8 +- .../AArch64/StandaloneMmMemLibInternal.c | 70 ---- .../ArmStandaloneMmMemLibInternal.c | 77 ++++ .../StandaloneMmMemLib/StandaloneMmMemLib.inf | 6 +- .../VariableMmDependency/VariableMmDependency.inf | 2 +- StandaloneMmPkg/StandaloneMmPkg.dec | 6 +- StandaloneMmPkg/StandaloneMmPkg.dsc | 12 +- 29 files changed, 2282 insertions(+), 2270 deletions(-) delete mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c delete mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c delete mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h delete mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf create mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c create mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c create mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h create mode 100644 StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf delete mode 100644 StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h create mode 100644 StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h delete mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c delete mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c delete mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c create mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/CreateHobList.c create mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c create mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c delete mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c delete mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLibInternal.c create mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c create mode 100644 StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLibInternal.c delete mode 100644 StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c create mode 100644 StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c (limited to 'StandaloneMmPkg') diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.inf b/StandaloneMmPkg/Core/StandaloneMmCore.inf index 87bf6e9440..56042b7b39 100644 --- a/StandaloneMmPkg/Core/StandaloneMmCore.inf +++ b/StandaloneMmPkg/Core/StandaloneMmCore.inf @@ -17,7 +17,7 @@ PI_SPECIFICATION_VERSION = 0x00010032 ENTRY_POINT = StandaloneMmMain -# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# VALID_ARCHITECTURES = IA32 X64 AARCH64 ARM [Sources] StandaloneMmCore.c diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c b/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c deleted file mode 100644 index 63fbe26642..0000000000 --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c +++ /dev/null @@ -1,250 +0,0 @@ -/** @file - - Copyright (c) 2016 HP Development Company, L.P. - Copyright (c) 2016 - 2021, Arm Limited. All rights reserved. - - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include - - -#include -#include -#include -#include -#include - -#include // for EFI_SYSTEM_CONTEXT - -#include -#include - -#include -#include - -#include "StandaloneMmCpu.h" - -EFI_STATUS -EFIAPI -MmFoundationEntryRegister ( - IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This, - IN EFI_MM_ENTRY_POINT MmEntryPoint - ); - -// -// On ARM platforms every event is expected to have a GUID associated with -// it. It will be used by the MM Entry point to find the handler for the -// event. It will either be populated in a EFI_MM_COMMUNICATE_HEADER by the -// caller of the event (e.g. MM_COMMUNICATE SMC) or by the CPU driver -// (e.g. during an asynchronous event). In either case, this context is -// maintained in an array which has an entry for each CPU. The pointer to this -// array is held in PerCpuGuidedEventContext. Memory is allocated once the -// number of CPUs in the system are made known through the -// MP_INFORMATION_HOB_DATA. -// -EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext = NULL; - -// Descriptor with whereabouts of memory used for communication with the normal world -EFI_MMRAM_DESCRIPTOR mNsCommBuffer; - -MP_INFORMATION_HOB_DATA *mMpInformationHobData; - -EFI_MM_CONFIGURATION_PROTOCOL mMmConfig = { - 0, - MmFoundationEntryRegister -}; - -STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL; - -/** - The PI Standalone MM entry point for the TF-A CPU driver. - - @param [in] EventId The event Id. - @param [in] CpuNumber The CPU number. - @param [in] NsCommBufferAddr Address of the NS common buffer. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER A parameter was invalid. - @retval EFI_ACCESS_DENIED Access not permitted. - @retval EFI_OUT_OF_RESOURCES Out of resources. - @retval EFI_UNSUPPORTED Operation not supported. -**/ -EFI_STATUS -PiMmStandaloneArmTfCpuDriverEntry ( - IN UINTN EventId, - IN UINTN CpuNumber, - IN UINTN NsCommBufferAddr - ) -{ - EFI_MM_COMMUNICATE_HEADER *GuidedEventContext; - EFI_MM_ENTRY_CONTEXT MmEntryPointContext; - EFI_STATUS Status; - UINTN NsCommBufferSize; - - DEBUG ((DEBUG_INFO, "Received event - 0x%x on cpu %d\n", EventId, CpuNumber)); - - Status = EFI_SUCCESS; - // - // ARM TF passes SMC FID of the MM_COMMUNICATE interface as the Event ID upon - // receipt of a synchronous MM request. Use the Event ID to distinguish - // between synchronous and asynchronous events. - // - if ((ARM_SMC_ID_MM_COMMUNICATE_AARCH64 != EventId) && - (ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64 != EventId)) { - DEBUG ((DEBUG_INFO, "UnRecognized Event - 0x%x\n", EventId)); - return EFI_INVALID_PARAMETER; - } - - // Perform parameter validation of NsCommBufferAddr - if (NsCommBufferAddr == (UINTN)NULL) { - return EFI_INVALID_PARAMETER; - } - - if (NsCommBufferAddr < mNsCommBuffer.PhysicalStart) { - return EFI_ACCESS_DENIED; - } - - if ((NsCommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >= - (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)) { - return EFI_INVALID_PARAMETER; - } - - // Find out the size of the buffer passed - NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *) NsCommBufferAddr)->MessageLength + - sizeof (EFI_MM_COMMUNICATE_HEADER); - - // perform bounds check. - if (NsCommBufferAddr + NsCommBufferSize >= - mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize) { - return EFI_ACCESS_DENIED; - } - - GuidedEventContext = NULL; - // Now that the secure world can see the normal world buffer, allocate - // memory to copy the communication buffer to the secure world. - Status = mMmst->MmAllocatePool ( - EfiRuntimeServicesData, - NsCommBufferSize, - (VOID **) &GuidedEventContext - ); - - if (Status != EFI_SUCCESS) { - DEBUG ((DEBUG_INFO, "Mem alloc failed - 0x%x\n", EventId)); - return EFI_OUT_OF_RESOURCES; - } - - // X1 contains the VA of the normal world memory accessible from - // S-EL0 - CopyMem (GuidedEventContext, (CONST VOID *) NsCommBufferAddr, NsCommBufferSize); - - // Stash the pointer to the allocated Event Context for this CPU - PerCpuGuidedEventContext[CpuNumber] = GuidedEventContext; - - ZeroMem (&MmEntryPointContext, sizeof (EFI_MM_ENTRY_CONTEXT)); - - MmEntryPointContext.CurrentlyExecutingCpu = CpuNumber; - MmEntryPointContext.NumberOfCpus = mMpInformationHobData->NumberOfProcessors; - - // Populate the MM system table with MP and state information - mMmst->CurrentlyExecutingCpu = CpuNumber; - mMmst->NumberOfCpus = mMpInformationHobData->NumberOfProcessors; - mMmst->CpuSaveStateSize = 0; - mMmst->CpuSaveState = NULL; - - if (mMmEntryPoint == NULL) { - DEBUG ((DEBUG_INFO, "Mm Entry point Not Found\n")); - return EFI_UNSUPPORTED; - } - - mMmEntryPoint (&MmEntryPointContext); - - // Free the memory allocation done earlier and reset the per-cpu context - ASSERT (GuidedEventContext); - CopyMem ((VOID *)NsCommBufferAddr, (CONST VOID *) GuidedEventContext, NsCommBufferSize); - - Status = mMmst->MmFreePool ((VOID *) GuidedEventContext); - if (Status != EFI_SUCCESS) { - return EFI_OUT_OF_RESOURCES; - } - PerCpuGuidedEventContext[CpuNumber] = NULL; - - return Status; -} - -/** - Registers the MM foundation entry point. - - @param [in] This Pointer to the MM Configuration protocol. - @param [in] MmEntryPoint Function pointer to the MM Entry point. - - @retval EFI_SUCCESS Success. -**/ -EFI_STATUS -EFIAPI -MmFoundationEntryRegister ( - IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This, - IN EFI_MM_ENTRY_POINT MmEntryPoint - ) -{ - // store the entry point in a global - mMmEntryPoint = MmEntryPoint; - return EFI_SUCCESS; -} - -/** - This function is the main entry point for an MM handler dispatch - or communicate-based callback. - - @param DispatchHandle The unique handle assigned to this handler by - MmiHandlerRegister(). - @param Context Points to an optional handler context which was - specified when the handler was registered. - @param CommBuffer A pointer to a collection of data in memory that will - be conveyed from a non-MM environment into an - MM environment. - @param CommBufferSize The size of the CommBuffer. - - @return Status Code - -**/ -EFI_STATUS -EFIAPI -PiMmCpuTpFwRootMmiHandler ( - IN EFI_HANDLE DispatchHandle, - IN CONST VOID *Context, OPTIONAL - IN OUT VOID *CommBuffer, OPTIONAL - IN OUT UINTN *CommBufferSize OPTIONAL - ) -{ - EFI_STATUS Status; - UINTN CpuNumber; - - ASSERT (Context == NULL); - ASSERT (CommBuffer == NULL); - ASSERT (CommBufferSize == NULL); - - CpuNumber = mMmst->CurrentlyExecutingCpu; - if (PerCpuGuidedEventContext[CpuNumber] == NULL) { - return EFI_NOT_FOUND; - } - - DEBUG ((DEBUG_INFO, "CommBuffer - 0x%x, CommBufferSize - 0x%x\n", - PerCpuGuidedEventContext[CpuNumber], - PerCpuGuidedEventContext[CpuNumber]->MessageLength)); - - Status = mMmst->MmiManage ( - &PerCpuGuidedEventContext[CpuNumber]->HeaderGuid, - NULL, - PerCpuGuidedEventContext[CpuNumber]->Data, - &PerCpuGuidedEventContext[CpuNumber]->MessageLength - ); - - if (Status != EFI_SUCCESS) { - DEBUG ((DEBUG_WARN, "Unable to manage Guided Event - %d\n", Status)); - } - - return Status; -} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c b/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c deleted file mode 100644 index d4590bcd19..0000000000 --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c +++ /dev/null @@ -1,250 +0,0 @@ -/** @file - - Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
- Copyright (c) 2016 HP Development Company, L.P. - Copyright (c) 2016 - 2021, Arm Limited. All rights reserved. - - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include // for EFI_SYSTEM_CONTEXT - -#include -#include - - -#include "StandaloneMmCpu.h" - -// GUID to identify HOB with whereabouts of communication buffer with Normal -// World -extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid; - -// GUID to identify HOB where the entry point of this CPU driver will be -// populated to allow the entry point driver to invoke it upon receipt of an -// event -extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid; - -// -// Private copy of the MM system table for future use -// -EFI_MM_SYSTEM_TABLE *mMmst = NULL; - -// -// Globals used to initialize the protocol -// -STATIC EFI_HANDLE mMmCpuHandle = NULL; - -/** Returns the HOB data for the matching HOB GUID. - - @param [in] HobList Pointer to the HOB list. - @param [in] HobGuid The GUID for the HOB. - @param [out] HobData Pointer to the HOB data. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_NOT_FOUND Could not find HOB with matching GUID. -**/ -EFI_STATUS -GetGuidedHobData ( - IN VOID *HobList, - IN CONST EFI_GUID *HobGuid, - OUT VOID **HobData - ) -{ - EFI_HOB_GUID_TYPE *Hob; - - if ((HobList == NULL) || (HobGuid == NULL) || (HobData == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Hob = GetNextGuidHob (HobGuid, HobList); - if (Hob == NULL) { - return EFI_NOT_FOUND; - } - - *HobData = GET_GUID_HOB_DATA (Hob); - if (*HobData == NULL) { - return EFI_NOT_FOUND; - } - - return EFI_SUCCESS; -} - -/** Entry point for the Standalone MM CPU driver. - - @param [in] ImageHandle Unused. Not actual image handle. - @param [in] SystemTable Pointer to MM System table. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Out of resources. - @retval EFI_NOT_FOUND Failed to find the HOB for the CPU - driver endpoint descriptor. -**/ -EFI_STATUS -StandaloneMmCpuInitialize ( - IN EFI_HANDLE ImageHandle, // not actual imagehandle - IN EFI_MM_SYSTEM_TABLE *SystemTable // not actual systemtable - ) -{ - ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc; - EFI_CONFIGURATION_TABLE *ConfigurationTable; - MP_INFORMATION_HOB_DATA *MpInformationHobData; - EFI_MMRAM_DESCRIPTOR *NsCommBufMmramRange; - EFI_STATUS Status; - EFI_HANDLE DispatchHandle; - UINT32 MpInfoSize; - UINTN Index; - UINTN ArraySize; - VOID *HobStart; - - ASSERT (SystemTable != NULL); - mMmst = SystemTable; - - // publish the MM config protocol so the MM core can register its entry point - Status = mMmst->MmInstallProtocolInterface ( - &mMmCpuHandle, - &gEfiMmConfigurationProtocolGuid, - EFI_NATIVE_INTERFACE, - &mMmConfig - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // register the root MMI handler - Status = mMmst->MmiHandlerRegister ( - PiMmCpuTpFwRootMmiHandler, - NULL, - &DispatchHandle - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // Retrieve the Hoblist from the MMST to extract the details of the NS - // communication buffer that has been reserved by S-EL1/EL3 - ConfigurationTable = mMmst->MmConfigurationTable; - for (Index = 0; Index < mMmst->NumberOfTableEntries; Index++) { - if (CompareGuid (&gEfiHobListGuid, &(ConfigurationTable[Index].VendorGuid))) { - break; - } - } - - // Bail out if the Hoblist could not be found - if (Index >= mMmst->NumberOfTableEntries) { - DEBUG ((DEBUG_INFO, "Hoblist not found - 0x%x\n", Index)); - return EFI_OUT_OF_RESOURCES; - } - - HobStart = ConfigurationTable[Index].VendorTable; - - // - // Locate the HOB with the buffer to populate the entry point of this driver - // - Status = GetGuidedHobData ( - HobStart, - &gEfiArmTfCpuDriverEpDescriptorGuid, - (VOID **) &CpuDriverEntryPointDesc - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "ArmTfCpuDriverEpDesc HOB data extraction failed - 0x%x\n", Status)); - return Status; - } - - // Share the entry point of the CPU driver - DEBUG ((DEBUG_INFO, "Sharing Cpu Driver EP *0x%lx = 0x%lx\n", - (UINTN) CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr, - (UINTN) PiMmStandaloneArmTfCpuDriverEntry)); - *(CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr) = PiMmStandaloneArmTfCpuDriverEntry; - - // Find the descriptor that contains the whereabouts of the buffer for - // communication with the Normal world. - Status = GetGuidedHobData ( - HobStart, - &gEfiStandaloneMmNonSecureBufferGuid, - (VOID **) &NsCommBufMmramRange - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "NsCommBufMmramRange HOB data extraction failed - 0x%x\n", Status)); - return Status; - } - - DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalStart - 0x%lx\n", (UINTN) NsCommBufMmramRange->PhysicalStart)); - DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalSize - 0x%lx\n", (UINTN) NsCommBufMmramRange->PhysicalSize)); - - CopyMem (&mNsCommBuffer, NsCommBufMmramRange, sizeof(EFI_MMRAM_DESCRIPTOR)); - DEBUG ((DEBUG_INFO, "mNsCommBuffer: 0x%016lx - 0x%lx\n", mNsCommBuffer.CpuStart, mNsCommBuffer.PhysicalSize)); - - // - // Extract the MP information from the Hoblist - // - Status = GetGuidedHobData ( - HobStart, - &gMpInformationHobGuid, - (VOID **) &MpInformationHobData - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "MpInformationHob extraction failed - 0x%x\n", Status)); - return Status; - } - - // - // Allocate memory for the MP information and copy over the MP information - // passed by Trusted Firmware. Use the number of processors passed in the HOB - // to copy the processor information - // - MpInfoSize = sizeof (MP_INFORMATION_HOB_DATA) + - (sizeof (EFI_PROCESSOR_INFORMATION) * - MpInformationHobData->NumberOfProcessors); - Status = mMmst->MmAllocatePool ( - EfiRuntimeServicesData, - MpInfoSize, - (VOID **) &mMpInformationHobData - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "mMpInformationHobData mem alloc failed - 0x%x\n", Status)); - return Status; - } - - CopyMem (mMpInformationHobData, MpInformationHobData, MpInfoSize); - - // Print MP information - DEBUG ((DEBUG_INFO, "mMpInformationHobData: 0x%016lx - 0x%lx\n", - mMpInformationHobData->NumberOfProcessors, - mMpInformationHobData->NumberOfEnabledProcessors)); - for (Index = 0; Index < mMpInformationHobData->NumberOfProcessors; Index++) { - DEBUG ((DEBUG_INFO, "mMpInformationHobData[0x%lx]: %d, %d, %d\n", - mMpInformationHobData->ProcessorInfoBuffer[Index].ProcessorId, - mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Package, - mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Core, - mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Thread)); - } - - // - // Allocate memory for a table to hold pointers to a - // EFI_MM_COMMUNICATE_HEADER for each CPU - // - ArraySize = sizeof (EFI_MM_COMMUNICATE_HEADER *) * - mMpInformationHobData->NumberOfEnabledProcessors; - Status = mMmst->MmAllocatePool ( - EfiRuntimeServicesData, - ArraySize, - (VOID **) &PerCpuGuidedEventContext - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "PerCpuGuidedEventContext mem alloc failed - 0x%x\n", Status)); - return Status; - } - return Status; -} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h b/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h deleted file mode 100644 index 2c96439c15..0000000000 --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h +++ /dev/null @@ -1,81 +0,0 @@ -/** @file - Private header with declarations and definitions specific to the MM Standalone - CPU driver - - Copyright (c) 2017 - 2021, Arm Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef _ARM_TF_CPU_DRIVER_H_ -#define _ARM_TF_CPU_DRIVER_H_ - -#include -#include -#include -#include - -// -// CPU driver initialization specific declarations -// -extern EFI_MM_SYSTEM_TABLE *mMmst; - -// -// CPU State Save protocol specific declarations -// -extern EFI_MM_CPU_PROTOCOL mMmCpuState; - -// -// MM event handling specific declarations -// -extern EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext; -extern EFI_MMRAM_DESCRIPTOR mNsCommBuffer; -extern MP_INFORMATION_HOB_DATA *mMpInformationHobData; -extern EFI_MM_CONFIGURATION_PROTOCOL mMmConfig; - -/** - The PI Standalone MM entry point for the TF-A CPU driver. - - @param [in] EventId The event Id. - @param [in] CpuNumber The CPU number. - @param [in] NsCommBufferAddr Address of the NS common buffer. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER A parameter was invalid. - @retval EFI_ACCESS_DENIED Access not permitted. - @retval EFI_OUT_OF_RESOURCES Out of resources. - @retval EFI_UNSUPPORTED Operation not supported. -**/ -EFI_STATUS -PiMmStandaloneArmTfCpuDriverEntry ( - IN UINTN EventId, - IN UINTN CpuNumber, - IN UINTN NsCommBufferAddr - ); - -/** - This function is the main entry point for an MM handler dispatch - or communicate-based callback. - - @param DispatchHandle The unique handle assigned to this handler by - MmiHandlerRegister(). - @param Context Points to an optional handler context which was - specified when the handler was registered. - @param CommBuffer A pointer to a collection of data in memory that will - be conveyed from a non-MM environment into an - MM environment. - @param CommBufferSize The size of the CommBuffer. - - @return Status Code - -**/ -EFI_STATUS -EFIAPI -PiMmCpuTpFwRootMmiHandler ( - IN EFI_HANDLE DispatchHandle, - IN CONST VOID *Context, OPTIONAL - IN OUT VOID *CommBuffer, OPTIONAL - IN OUT UINTN *CommBufferSize OPTIONAL - ); - -#endif diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf b/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf deleted file mode 100644 index 1fcb17d89d..0000000000 --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf +++ /dev/null @@ -1,52 +0,0 @@ -## @file -# Standalone MM CPU driver for ARM Standard Platforms -# -# Copyright (c) 2009, Apple Inc. All rights reserved.
-# Copyright (c) 2016 HP Development Company, L.P. -# Copyright (c) 2017 - 2021, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001A - BASE_NAME = StandaloneMmCpu - FILE_GUID = 58F7A62B-6280-42A7-BC38-10535A64A92C - MODULE_TYPE = MM_STANDALONE - VERSION_STRING = 1.0 - PI_SPECIFICATION_VERSION = 0x00010032 - ENTRY_POINT = StandaloneMmCpuInitialize - -[Sources] - StandaloneMmCpu.c - StandaloneMmCpu.h - EventHandle.c - -[Packages] - ArmPkg/ArmPkg.dec - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - StandaloneMmPkg/StandaloneMmPkg.dec - -[LibraryClasses] - ArmLib - ArmSvcLib - BaseMemoryLib - DebugLib - HobLib - StandaloneMmDriverEntryPoint - -[Protocols] - gEfiMmConfigurationProtocolGuid # PROTOCOL ALWAYS_PRODUCED - gEfiMmCpuProtocolGuid # PROTOCOL ALWAYS_PRODUCED - -[Guids] - gEfiHobListGuid - gEfiMmPeiMmramMemoryReserveGuid - gZeroGuid - gMpInformationHobGuid - gEfiStandaloneMmNonSecureBufferGuid - gEfiArmTfCpuDriverEpDescriptorGuid - -[Depex] - TRUE diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c b/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c new file mode 100644 index 0000000000..165d696f99 --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c @@ -0,0 +1,251 @@ +/** @file + + Copyright (c) 2016 HP Development Company, L.P. + Copyright (c) 2016 - 2021, Arm Limited. All rights reserved. + Copyright (c) 2021, Linaro Limited + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + + +#include +#include +#include +#include +#include + +#include // for EFI_SYSTEM_CONTEXT + +#include +#include + +#include +#include + +#include "StandaloneMmCpu.h" + +EFI_STATUS +EFIAPI +MmFoundationEntryRegister ( + IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This, + IN EFI_MM_ENTRY_POINT MmEntryPoint + ); + +// +// On ARM platforms every event is expected to have a GUID associated with +// it. It will be used by the MM Entry point to find the handler for the +// event. It will either be populated in a EFI_MM_COMMUNICATE_HEADER by the +// caller of the event (e.g. MM_COMMUNICATE SMC) or by the CPU driver +// (e.g. during an asynchronous event). In either case, this context is +// maintained in an array which has an entry for each CPU. The pointer to this +// array is held in PerCpuGuidedEventContext. Memory is allocated once the +// number of CPUs in the system are made known through the +// MP_INFORMATION_HOB_DATA. +// +EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext = NULL; + +// Descriptor with whereabouts of memory used for communication with the normal world +EFI_MMRAM_DESCRIPTOR mNsCommBuffer; + +MP_INFORMATION_HOB_DATA *mMpInformationHobData; + +EFI_MM_CONFIGURATION_PROTOCOL mMmConfig = { + 0, + MmFoundationEntryRegister +}; + +STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL; + +/** + The PI Standalone MM entry point for the TF-A CPU driver. + + @param [in] EventId The event Id. + @param [in] CpuNumber The CPU number. + @param [in] NsCommBufferAddr Address of the NS common buffer. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_ACCESS_DENIED Access not permitted. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Operation not supported. +**/ +EFI_STATUS +PiMmStandaloneArmTfCpuDriverEntry ( + IN UINTN EventId, + IN UINTN CpuNumber, + IN UINTN NsCommBufferAddr + ) +{ + EFI_MM_COMMUNICATE_HEADER *GuidedEventContext; + EFI_MM_ENTRY_CONTEXT MmEntryPointContext; + EFI_STATUS Status; + UINTN NsCommBufferSize; + + DEBUG ((DEBUG_INFO, "Received event - 0x%x on cpu %d\n", EventId, CpuNumber)); + + Status = EFI_SUCCESS; + // + // ARM TF passes SMC FID of the MM_COMMUNICATE interface as the Event ID upon + // receipt of a synchronous MM request. Use the Event ID to distinguish + // between synchronous and asynchronous events. + // + if ((ARM_SMC_ID_MM_COMMUNICATE != EventId) && + (ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ != EventId)) { + DEBUG ((DEBUG_INFO, "UnRecognized Event - 0x%x\n", EventId)); + return EFI_INVALID_PARAMETER; + } + + // Perform parameter validation of NsCommBufferAddr + if (NsCommBufferAddr == (UINTN)NULL) { + return EFI_INVALID_PARAMETER; + } + + if (NsCommBufferAddr < mNsCommBuffer.PhysicalStart) { + return EFI_ACCESS_DENIED; + } + + if ((NsCommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >= + (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)) { + return EFI_INVALID_PARAMETER; + } + + // Find out the size of the buffer passed + NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *) NsCommBufferAddr)->MessageLength + + sizeof (EFI_MM_COMMUNICATE_HEADER); + + // perform bounds check. + if (NsCommBufferAddr + NsCommBufferSize >= + mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize) { + return EFI_ACCESS_DENIED; + } + + GuidedEventContext = NULL; + // Now that the secure world can see the normal world buffer, allocate + // memory to copy the communication buffer to the secure world. + Status = mMmst->MmAllocatePool ( + EfiRuntimeServicesData, + NsCommBufferSize, + (VOID **) &GuidedEventContext + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((DEBUG_INFO, "Mem alloc failed - 0x%x\n", EventId)); + return EFI_OUT_OF_RESOURCES; + } + + // X1 contains the VA of the normal world memory accessible from + // S-EL0 + CopyMem (GuidedEventContext, (CONST VOID *) NsCommBufferAddr, NsCommBufferSize); + + // Stash the pointer to the allocated Event Context for this CPU + PerCpuGuidedEventContext[CpuNumber] = GuidedEventContext; + + ZeroMem (&MmEntryPointContext, sizeof (EFI_MM_ENTRY_CONTEXT)); + + MmEntryPointContext.CurrentlyExecutingCpu = CpuNumber; + MmEntryPointContext.NumberOfCpus = mMpInformationHobData->NumberOfProcessors; + + // Populate the MM system table with MP and state information + mMmst->CurrentlyExecutingCpu = CpuNumber; + mMmst->NumberOfCpus = mMpInformationHobData->NumberOfProcessors; + mMmst->CpuSaveStateSize = 0; + mMmst->CpuSaveState = NULL; + + if (mMmEntryPoint == NULL) { + DEBUG ((DEBUG_INFO, "Mm Entry point Not Found\n")); + return EFI_UNSUPPORTED; + } + + mMmEntryPoint (&MmEntryPointContext); + + // Free the memory allocation done earlier and reset the per-cpu context + ASSERT (GuidedEventContext); + CopyMem ((VOID *)NsCommBufferAddr, (CONST VOID *) GuidedEventContext, NsCommBufferSize); + + Status = mMmst->MmFreePool ((VOID *) GuidedEventContext); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + PerCpuGuidedEventContext[CpuNumber] = NULL; + + return Status; +} + +/** + Registers the MM foundation entry point. + + @param [in] This Pointer to the MM Configuration protocol. + @param [in] MmEntryPoint Function pointer to the MM Entry point. + + @retval EFI_SUCCESS Success. +**/ +EFI_STATUS +EFIAPI +MmFoundationEntryRegister ( + IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This, + IN EFI_MM_ENTRY_POINT MmEntryPoint + ) +{ + // store the entry point in a global + mMmEntryPoint = MmEntryPoint; + return EFI_SUCCESS; +} + +/** + This function is the main entry point for an MM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by + MmiHandlerRegister(). + @param Context Points to an optional handler context which was + specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-MM environment into an + MM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +PiMmCpuTpFwRootMmiHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN CpuNumber; + + ASSERT (Context == NULL); + ASSERT (CommBuffer == NULL); + ASSERT (CommBufferSize == NULL); + + CpuNumber = mMmst->CurrentlyExecutingCpu; + if (PerCpuGuidedEventContext[CpuNumber] == NULL) { + return EFI_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "CommBuffer - 0x%x, CommBufferSize - 0x%x\n", + PerCpuGuidedEventContext[CpuNumber], + PerCpuGuidedEventContext[CpuNumber]->MessageLength)); + + Status = mMmst->MmiManage ( + &PerCpuGuidedEventContext[CpuNumber]->HeaderGuid, + NULL, + PerCpuGuidedEventContext[CpuNumber]->Data, + &PerCpuGuidedEventContext[CpuNumber]->MessageLength + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((DEBUG_WARN, "Unable to manage Guided Event - %d\n", Status)); + } + + return Status; +} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c new file mode 100644 index 0000000000..10097f792f --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c @@ -0,0 +1,250 @@ +/** @file + + Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Copyright (c) 2016 HP Development Company, L.P. + Copyright (c) 2016 - 2021, Arm Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for EFI_SYSTEM_CONTEXT + +#include +#include + + +#include "StandaloneMmCpu.h" + +// GUID to identify HOB with whereabouts of communication buffer with Normal +// World +extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid; + +// GUID to identify HOB where the entry point of this CPU driver will be +// populated to allow the entry point driver to invoke it upon receipt of an +// event +extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid; + +// +// Private copy of the MM system table for future use +// +EFI_MM_SYSTEM_TABLE *mMmst = NULL; + +// +// Globals used to initialize the protocol +// +STATIC EFI_HANDLE mMmCpuHandle = NULL; + +/** Returns the HOB data for the matching HOB GUID. + + @param [in] HobList Pointer to the HOB list. + @param [in] HobGuid The GUID for the HOB. + @param [out] HobData Pointer to the HOB data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Could not find HOB with matching GUID. +**/ +EFI_STATUS +GetGuidedHobData ( + IN VOID *HobList, + IN CONST EFI_GUID *HobGuid, + OUT VOID **HobData + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + if ((HobList == NULL) || (HobGuid == NULL) || (HobData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Hob = GetNextGuidHob (HobGuid, HobList); + if (Hob == NULL) { + return EFI_NOT_FOUND; + } + + *HobData = GET_GUID_HOB_DATA (Hob); + if (*HobData == NULL) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** Entry point for the Standalone MM CPU driver. + + @param [in] ImageHandle Unused. Not actual image handle. + @param [in] SystemTable Pointer to MM System table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_NOT_FOUND Failed to find the HOB for the CPU + driver endpoint descriptor. +**/ +EFI_STATUS +StandaloneMmCpuInitialize ( + IN EFI_HANDLE ImageHandle, // not actual imagehandle + IN EFI_MM_SYSTEM_TABLE *SystemTable // not actual systemtable + ) +{ + ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc; + EFI_CONFIGURATION_TABLE *ConfigurationTable; + MP_INFORMATION_HOB_DATA *MpInformationHobData; + EFI_MMRAM_DESCRIPTOR *NsCommBufMmramRange; + EFI_STATUS Status; + EFI_HANDLE DispatchHandle; + UINT32 MpInfoSize; + UINTN Index; + UINTN ArraySize; + VOID *HobStart; + + ASSERT (SystemTable != NULL); + mMmst = SystemTable; + + // publish the MM config protocol so the MM core can register its entry point + Status = mMmst->MmInstallProtocolInterface ( + &mMmCpuHandle, + &gEfiMmConfigurationProtocolGuid, + EFI_NATIVE_INTERFACE, + &mMmConfig + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // register the root MMI handler + Status = mMmst->MmiHandlerRegister ( + PiMmCpuTpFwRootMmiHandler, + NULL, + &DispatchHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Retrieve the Hoblist from the MMST to extract the details of the NS + // communication buffer that has been reserved by S-EL1/EL3 + ConfigurationTable = mMmst->MmConfigurationTable; + for (Index = 0; Index < mMmst->NumberOfTableEntries; Index++) { + if (CompareGuid (&gEfiHobListGuid, &(ConfigurationTable[Index].VendorGuid))) { + break; + } + } + + // Bail out if the Hoblist could not be found + if (Index >= mMmst->NumberOfTableEntries) { + DEBUG ((DEBUG_INFO, "Hoblist not found - 0x%x\n", Index)); + return EFI_OUT_OF_RESOURCES; + } + + HobStart = ConfigurationTable[Index].VendorTable; + + // + // Locate the HOB with the buffer to populate the entry point of this driver + // + Status = GetGuidedHobData ( + HobStart, + &gEfiArmTfCpuDriverEpDescriptorGuid, + (VOID **) &CpuDriverEntryPointDesc + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "ArmTfCpuDriverEpDesc HOB data extraction failed - 0x%x\n", Status)); + return Status; + } + + // Share the entry point of the CPU driver + DEBUG ((DEBUG_INFO, "Sharing Cpu Driver EP *0x%lx = 0x%lx\n", + (UINTN) CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr, + (UINTN) PiMmStandaloneArmTfCpuDriverEntry)); + *(CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr) = PiMmStandaloneArmTfCpuDriverEntry; + + // Find the descriptor that contains the whereabouts of the buffer for + // communication with the Normal world. + Status = GetGuidedHobData ( + HobStart, + &gEfiStandaloneMmNonSecureBufferGuid, + (VOID **) &NsCommBufMmramRange + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "NsCommBufMmramRange HOB data extraction failed - 0x%x\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalStart - 0x%lx\n", (UINTN) NsCommBufMmramRange->PhysicalStart)); + DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalSize - 0x%lx\n", (UINTN) NsCommBufMmramRange->PhysicalSize)); + + CopyMem (&mNsCommBuffer, NsCommBufMmramRange, sizeof(EFI_MMRAM_DESCRIPTOR)); + DEBUG ((DEBUG_INFO, "mNsCommBuffer: 0x%016lx - 0x%lx\n", mNsCommBuffer.CpuStart, mNsCommBuffer.PhysicalSize)); + + // + // Extract the MP information from the Hoblist + // + Status = GetGuidedHobData ( + HobStart, + &gMpInformationHobGuid, + (VOID **) &MpInformationHobData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "MpInformationHob extraction failed - 0x%x\n", Status)); + return Status; + } + + // + // Allocate memory for the MP information and copy over the MP information + // passed by Trusted Firmware. Use the number of processors passed in the HOB + // to copy the processor information + // + MpInfoSize = sizeof (MP_INFORMATION_HOB_DATA) + + (sizeof (EFI_PROCESSOR_INFORMATION) * + MpInformationHobData->NumberOfProcessors); + Status = mMmst->MmAllocatePool ( + EfiRuntimeServicesData, + MpInfoSize, + (VOID **) &mMpInformationHobData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "mMpInformationHobData mem alloc failed - 0x%x\n", Status)); + return Status; + } + + CopyMem (mMpInformationHobData, MpInformationHobData, MpInfoSize); + + // Print MP information + DEBUG ((DEBUG_INFO, "mMpInformationHobData: 0x%016lx - 0x%lx\n", + mMpInformationHobData->NumberOfProcessors, + mMpInformationHobData->NumberOfEnabledProcessors)); + for (Index = 0; Index < mMpInformationHobData->NumberOfProcessors; Index++) { + DEBUG ((DEBUG_INFO, "mMpInformationHobData[0x%lx]: %d, %d, %d\n", + mMpInformationHobData->ProcessorInfoBuffer[Index].ProcessorId, + mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Package, + mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Core, + mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Thread)); + } + + // + // Allocate memory for a table to hold pointers to a + // EFI_MM_COMMUNICATE_HEADER for each CPU + // + ArraySize = sizeof (EFI_MM_COMMUNICATE_HEADER *) * + mMpInformationHobData->NumberOfEnabledProcessors; + Status = mMmst->MmAllocatePool ( + EfiRuntimeServicesData, + ArraySize, + (VOID **) &PerCpuGuidedEventContext + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "PerCpuGuidedEventContext mem alloc failed - 0x%x\n", Status)); + return Status; + } + return Status; +} diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h new file mode 100644 index 0000000000..2c96439c15 --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h @@ -0,0 +1,81 @@ +/** @file + Private header with declarations and definitions specific to the MM Standalone + CPU driver + + Copyright (c) 2017 - 2021, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ARM_TF_CPU_DRIVER_H_ +#define _ARM_TF_CPU_DRIVER_H_ + +#include +#include +#include +#include + +// +// CPU driver initialization specific declarations +// +extern EFI_MM_SYSTEM_TABLE *mMmst; + +// +// CPU State Save protocol specific declarations +// +extern EFI_MM_CPU_PROTOCOL mMmCpuState; + +// +// MM event handling specific declarations +// +extern EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext; +extern EFI_MMRAM_DESCRIPTOR mNsCommBuffer; +extern MP_INFORMATION_HOB_DATA *mMpInformationHobData; +extern EFI_MM_CONFIGURATION_PROTOCOL mMmConfig; + +/** + The PI Standalone MM entry point for the TF-A CPU driver. + + @param [in] EventId The event Id. + @param [in] CpuNumber The CPU number. + @param [in] NsCommBufferAddr Address of the NS common buffer. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_ACCESS_DENIED Access not permitted. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Operation not supported. +**/ +EFI_STATUS +PiMmStandaloneArmTfCpuDriverEntry ( + IN UINTN EventId, + IN UINTN CpuNumber, + IN UINTN NsCommBufferAddr + ); + +/** + This function is the main entry point for an MM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by + MmiHandlerRegister(). + @param Context Points to an optional handler context which was + specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-MM environment into an + MM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +PiMmCpuTpFwRootMmiHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +#endif diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf new file mode 100644 index 0000000000..1fcb17d89d --- /dev/null +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf @@ -0,0 +1,52 @@ +## @file +# Standalone MM CPU driver for ARM Standard Platforms +# +# Copyright (c) 2009, Apple Inc. All rights reserved.
+# Copyright (c) 2016 HP Development Company, L.P. +# Copyright (c) 2017 - 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = StandaloneMmCpu + FILE_GUID = 58F7A62B-6280-42A7-BC38-10535A64A92C + MODULE_TYPE = MM_STANDALONE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010032 + ENTRY_POINT = StandaloneMmCpuInitialize + +[Sources] + StandaloneMmCpu.c + StandaloneMmCpu.h + EventHandle.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + ArmLib + ArmSvcLib + BaseMemoryLib + DebugLib + HobLib + StandaloneMmDriverEntryPoint + +[Protocols] + gEfiMmConfigurationProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiMmCpuProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Guids] + gEfiHobListGuid + gEfiMmPeiMmramMemoryReserveGuid + gZeroGuid + gMpInformationHobGuid + gEfiStandaloneMmNonSecureBufferGuid + gEfiArmTfCpuDriverEpDescriptorGuid + +[Depex] + TRUE diff --git a/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h b/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h deleted file mode 100644 index c44f7066c6..0000000000 --- a/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h +++ /dev/null @@ -1,216 +0,0 @@ -/** @file - Entry point to the Standalone MM Foundation when initialized during the SEC - phase on ARM platforms - -Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef __STANDALONEMMCORE_ENTRY_POINT_H__ -#define __STANDALONEMMCORE_ENTRY_POINT_H__ - -#include -#include - -#define CPU_INFO_FLAG_PRIMARY_CPU 0x00000001 - -typedef struct { - UINT8 Type; /* type of the structure */ - UINT8 Version; /* version of this structure */ - UINT16 Size; /* size of this structure in bytes */ - UINT32 Attr; /* attributes: unused bits SBZ */ -} EFI_PARAM_HEADER; - -typedef struct { - UINT64 Mpidr; - UINT32 LinearId; - UINT32 Flags; -} EFI_SECURE_PARTITION_CPU_INFO; - -typedef struct { - EFI_PARAM_HEADER Header; - UINT64 SpMemBase; - UINT64 SpMemLimit; - UINT64 SpImageBase; - UINT64 SpStackBase; - UINT64 SpHeapBase; - UINT64 SpNsCommBufBase; - UINT64 SpSharedBufBase; - UINT64 SpImageSize; - UINT64 SpPcpuStackSize; - UINT64 SpHeapSize; - UINT64 SpNsCommBufSize; - UINT64 SpPcpuSharedBufSize; - UINT32 NumSpMemRegions; - UINT32 NumCpus; - EFI_SECURE_PARTITION_CPU_INFO *CpuInfo; -} EFI_SECURE_PARTITION_BOOT_INFO; - -typedef -EFI_STATUS -(*PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT) ( - IN UINTN EventId, - IN UINTN CpuNumber, - IN UINTN NsCommBufferAddr - ); - -typedef struct { - PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *ArmTfCpuDriverEpPtr; -} ARM_TF_CPU_DRIVER_EP_DESCRIPTOR; - -typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length - ); - -/** - Privileged firmware assigns RO & Executable attributes to all memory occupied - by the Boot Firmware Volume. This function sets the correct permissions of - sections in the Standalone MM Core module to be able to access RO and RW data - and make further progress in the boot process. - - @param [in] ImageContext Pointer to PE/COFF image context - @param [in] ImageBase Base of image in memory - @param [in] SectionHeaderOffset Offset of PE/COFF image section header - @param [in] NumberOfSections Number of Sections - @param [in] TextUpdater Function to change code permissions - @param [in] ReadOnlyUpdater Function to change RO permissions - @param [in] ReadWriteUpdater Function to change RW permissions - -**/ -EFI_STATUS -EFIAPI -UpdateMmFoundationPeCoffPermissions ( - IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, - IN EFI_PHYSICAL_ADDRESS ImageBase, - IN UINT32 SectionHeaderOffset, - IN CONST UINT16 NumberOfSections, - IN REGION_PERMISSION_UPDATE_FUNC TextUpdater, - IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater, - IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater - ); - - -/** - Privileged firmware assigns RO & Executable attributes to all memory occupied - by the Boot Firmware Volume. This function locates the section information of - the Standalone MM Core module to be able to change permissions of the - individual sections later in the boot process. - - @param [in] TeData Pointer to PE/COFF image data - @param [in, out] ImageContext Pointer to PE/COFF image context - @param [out] ImageBase Pointer to ImageBase variable - @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header - @param [in, out] NumberOfSections Number of Sections - -**/ -EFI_STATUS -EFIAPI -GetStandaloneMmCorePeCoffSections ( - IN VOID *TeData, - IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, - OUT EFI_PHYSICAL_ADDRESS *ImageBase, - IN OUT UINT32 *SectionHeaderOffset, - IN OUT UINT16 *NumberOfSections - ); - - -/** - Privileged firmware assigns RO & Executable attributes to all memory occupied - by the Boot Firmware Volume. This function locates the Standalone MM Core - module PE/COFF image in the BFV and returns this information. - - @param [in] BfvAddress Base Address of Boot Firmware Volume - @param [in, out] TeData Pointer to address for allocating memory - for PE/COFF image data - @param [in, out] TeDataSize Pointer to size of PE/COFF image data - -**/ -EFI_STATUS -EFIAPI -LocateStandaloneMmCorePeCoffData ( - IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress, - IN OUT VOID **TeData, - IN OUT UINTN *TeDataSize - ); - - -/** - Use the boot information passed by privileged firmware to populate a HOB list - suitable for consumption by the MM Core and drivers. - - @param [in, out] CpuDriverEntryPoint Address of MM CPU driver entrypoint - @param [in] PayloadBootInfo Boot information passed by privileged - firmware - -**/ -VOID * -EFIAPI -CreateHobListFromBootInfo ( - IN OUT PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *CpuDriverEntryPoint, - IN EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo - ); - - -/** - The entry point of Standalone MM Foundation. - - @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP. - @param [in] SharedBufSize Size of the shared buffer. - @param [in] cookie1 Cookie 1 - @param [in] cookie2 Cookie 2 - -**/ -VOID -EFIAPI -_ModuleEntryPoint ( - IN VOID *SharedBufAddress, - IN UINT64 SharedBufSize, - IN UINT64 cookie1, - IN UINT64 cookie2 - ); - - -/** - Auto generated function that calls the library constructors for all of the module's dependent libraries. - - This function must be called by _ModuleEntryPoint(). - This function calls the set of library constructors for the set of library instances - that a module depends on. This includes library instances that a module depends on - directly and library instances that a module depends on indirectly through other - libraries. This function is auto generated by build tools and those build tools are - responsible for collecting the set of library instances, determine which ones have - constructors, and calling the library constructors in the proper order based upon - each of the library instances own dependencies. - - @param ImageHandle The image handle of the DXE Core. - @param SystemTable A pointer to the EFI System Table. - -**/ -VOID -EFIAPI -ProcessLibraryConstructorList ( - IN EFI_HANDLE ImageHandle, - IN EFI_MM_SYSTEM_TABLE *MmSystemTable - ); - - -/** - Auto generated function that calls a set of module entry points. - - This function must be called by _ModuleEntryPoint(). - This function calls the set of module entry points. - This function is auto generated by build tools and those build tools are responsible - for collecting the module entry points and calling them in a specified order. - - @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase. - -**/ -VOID -EFIAPI -ProcessModuleEntryPointList ( - IN VOID *HobStart - ); - -#endif diff --git a/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h b/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h new file mode 100644 index 0000000000..c44f7066c6 --- /dev/null +++ b/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h @@ -0,0 +1,216 @@ +/** @file + Entry point to the Standalone MM Foundation when initialized during the SEC + phase on ARM platforms + +Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __STANDALONEMMCORE_ENTRY_POINT_H__ +#define __STANDALONEMMCORE_ENTRY_POINT_H__ + +#include +#include + +#define CPU_INFO_FLAG_PRIMARY_CPU 0x00000001 + +typedef struct { + UINT8 Type; /* type of the structure */ + UINT8 Version; /* version of this structure */ + UINT16 Size; /* size of this structure in bytes */ + UINT32 Attr; /* attributes: unused bits SBZ */ +} EFI_PARAM_HEADER; + +typedef struct { + UINT64 Mpidr; + UINT32 LinearId; + UINT32 Flags; +} EFI_SECURE_PARTITION_CPU_INFO; + +typedef struct { + EFI_PARAM_HEADER Header; + UINT64 SpMemBase; + UINT64 SpMemLimit; + UINT64 SpImageBase; + UINT64 SpStackBase; + UINT64 SpHeapBase; + UINT64 SpNsCommBufBase; + UINT64 SpSharedBufBase; + UINT64 SpImageSize; + UINT64 SpPcpuStackSize; + UINT64 SpHeapSize; + UINT64 SpNsCommBufSize; + UINT64 SpPcpuSharedBufSize; + UINT32 NumSpMemRegions; + UINT32 NumCpus; + EFI_SECURE_PARTITION_CPU_INFO *CpuInfo; +} EFI_SECURE_PARTITION_BOOT_INFO; + +typedef +EFI_STATUS +(*PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT) ( + IN UINTN EventId, + IN UINTN CpuNumber, + IN UINTN NsCommBufferAddr + ); + +typedef struct { + PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *ArmTfCpuDriverEpPtr; +} ARM_TF_CPU_DRIVER_EP_DESCRIPTOR; + +typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Privileged firmware assigns RO & Executable attributes to all memory occupied + by the Boot Firmware Volume. This function sets the correct permissions of + sections in the Standalone MM Core module to be able to access RO and RW data + and make further progress in the boot process. + + @param [in] ImageContext Pointer to PE/COFF image context + @param [in] ImageBase Base of image in memory + @param [in] SectionHeaderOffset Offset of PE/COFF image section header + @param [in] NumberOfSections Number of Sections + @param [in] TextUpdater Function to change code permissions + @param [in] ReadOnlyUpdater Function to change RO permissions + @param [in] ReadWriteUpdater Function to change RW permissions + +**/ +EFI_STATUS +EFIAPI +UpdateMmFoundationPeCoffPermissions ( + IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT32 SectionHeaderOffset, + IN CONST UINT16 NumberOfSections, + IN REGION_PERMISSION_UPDATE_FUNC TextUpdater, + IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater, + IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater + ); + + +/** + Privileged firmware assigns RO & Executable attributes to all memory occupied + by the Boot Firmware Volume. This function locates the section information of + the Standalone MM Core module to be able to change permissions of the + individual sections later in the boot process. + + @param [in] TeData Pointer to PE/COFF image data + @param [in, out] ImageContext Pointer to PE/COFF image context + @param [out] ImageBase Pointer to ImageBase variable + @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header + @param [in, out] NumberOfSections Number of Sections + +**/ +EFI_STATUS +EFIAPI +GetStandaloneMmCorePeCoffSections ( + IN VOID *TeData, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_PHYSICAL_ADDRESS *ImageBase, + IN OUT UINT32 *SectionHeaderOffset, + IN OUT UINT16 *NumberOfSections + ); + + +/** + Privileged firmware assigns RO & Executable attributes to all memory occupied + by the Boot Firmware Volume. This function locates the Standalone MM Core + module PE/COFF image in the BFV and returns this information. + + @param [in] BfvAddress Base Address of Boot Firmware Volume + @param [in, out] TeData Pointer to address for allocating memory + for PE/COFF image data + @param [in, out] TeDataSize Pointer to size of PE/COFF image data + +**/ +EFI_STATUS +EFIAPI +LocateStandaloneMmCorePeCoffData ( + IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress, + IN OUT VOID **TeData, + IN OUT UINTN *TeDataSize + ); + + +/** + Use the boot information passed by privileged firmware to populate a HOB list + suitable for consumption by the MM Core and drivers. + + @param [in, out] CpuDriverEntryPoint Address of MM CPU driver entrypoint + @param [in] PayloadBootInfo Boot information passed by privileged + firmware + +**/ +VOID * +EFIAPI +CreateHobListFromBootInfo ( + IN OUT PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *CpuDriverEntryPoint, + IN EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo + ); + + +/** + The entry point of Standalone MM Foundation. + + @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP. + @param [in] SharedBufSize Size of the shared buffer. + @param [in] cookie1 Cookie 1 + @param [in] cookie2 Cookie 2 + +**/ +VOID +EFIAPI +_ModuleEntryPoint ( + IN VOID *SharedBufAddress, + IN UINT64 SharedBufSize, + IN UINT64 cookie1, + IN UINT64 cookie2 + ); + + +/** + Auto generated function that calls the library constructors for all of the module's dependent libraries. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of library constructors for the set of library instances + that a module depends on. This includes library instances that a module depends on + directly and library instances that a module depends on indirectly through other + libraries. This function is auto generated by build tools and those build tools are + responsible for collecting the set of library instances, determine which ones have + constructors, and calling the library constructors in the proper order based upon + each of the library instances own dependencies. + + @param ImageHandle The image handle of the DXE Core. + @param SystemTable A pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ); + + +/** + Auto generated function that calls a set of module entry points. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of module entry points. + This function is auto generated by build tools and those build tools are responsible + for collecting the module entry points and calling them in a specified order. + + @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase. + +**/ +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN VOID *HobStart + ); + +#endif diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c deleted file mode 100644 index 4d4cf3d5ff..0000000000 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c +++ /dev/null @@ -1,205 +0,0 @@ -/** @file - Creates HOB during Standalone MM Foundation entry point - on ARM platforms. - -Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -extern EFI_HOB_HANDOFF_INFO_TABLE* -HobConstructor ( - IN VOID *EfiMemoryBegin, - IN UINTN EfiMemoryLength, - IN VOID *EfiFreeMemoryBottom, - IN VOID *EfiFreeMemoryTop - ); - -// GUID to identify HOB with whereabouts of communication buffer with Normal -// World -extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid; - -// GUID to identify HOB where the entry point of the CPU driver will be -// populated to allow this entry point driver to invoke it upon receipt of an -// event -extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid; - -/** - Use the boot information passed by privileged firmware to populate a HOB list - suitable for consumption by the MM Core and drivers. - - @param [in, out] CpuDriverEntryPoint Address of MM CPU driver entrypoint - @param [in] PayloadBootInfo Boot information passed by privileged - firmware - -**/ -VOID * -CreateHobListFromBootInfo ( - IN OUT PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *CpuDriverEntryPoint, - IN EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo -) -{ - EFI_HOB_HANDOFF_INFO_TABLE *HobStart; - EFI_RESOURCE_ATTRIBUTE_TYPE Attributes; - UINT32 Index; - UINT32 BufferSize; - UINT32 Flags; - EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHob; - EFI_MMRAM_DESCRIPTOR *MmramRanges; - EFI_MMRAM_DESCRIPTOR *NsCommBufMmramRange; - MP_INFORMATION_HOB_DATA *MpInformationHobData; - EFI_PROCESSOR_INFORMATION *ProcInfoBuffer; - EFI_SECURE_PARTITION_CPU_INFO *CpuInfo; - ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc; - - // Create a hoblist with a PHIT and EOH - HobStart = HobConstructor ( - (VOID *) (UINTN) PayloadBootInfo->SpMemBase, - (UINTN) PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase, - (VOID *) (UINTN) PayloadBootInfo->SpHeapBase, - (VOID *) (UINTN) (PayloadBootInfo->SpHeapBase + PayloadBootInfo->SpHeapSize) - ); - - // Check that the Hoblist starts at the bottom of the Heap - ASSERT (HobStart == (VOID *) (UINTN) PayloadBootInfo->SpHeapBase); - - // Build a Boot Firmware Volume HOB - BuildFvHob (PayloadBootInfo->SpImageBase, PayloadBootInfo->SpImageSize); - - // Build a resource descriptor Hob that describes the available physical - // memory range - Attributes = ( - EFI_RESOURCE_ATTRIBUTE_PRESENT | - EFI_RESOURCE_ATTRIBUTE_INITIALIZED | - EFI_RESOURCE_ATTRIBUTE_TESTED | - EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | - EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | - EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | - EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE - ); - - BuildResourceDescriptorHob ( - EFI_RESOURCE_SYSTEM_MEMORY, - Attributes, - (UINTN) PayloadBootInfo->SpMemBase, - PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase - ); - - // Find the size of the GUIDed HOB with MP information - BufferSize = sizeof (MP_INFORMATION_HOB_DATA); - BufferSize += sizeof (EFI_PROCESSOR_INFORMATION) * PayloadBootInfo->NumCpus; - - // Create a Guided MP information HOB to enable the ARM TF CPU driver to - // perform per-cpu allocations. - MpInformationHobData = BuildGuidHob (&gMpInformationHobGuid, BufferSize); - - // Populate the MP information HOB with the topology information passed by - // privileged firmware - MpInformationHobData->NumberOfProcessors = PayloadBootInfo->NumCpus; - MpInformationHobData->NumberOfEnabledProcessors = PayloadBootInfo->NumCpus; - ProcInfoBuffer = MpInformationHobData->ProcessorInfoBuffer; - CpuInfo = PayloadBootInfo->CpuInfo; - - for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) { - ProcInfoBuffer[Index].ProcessorId = CpuInfo[Index].Mpidr; - ProcInfoBuffer[Index].Location.Package = GET_CLUSTER_ID(CpuInfo[Index].Mpidr); - ProcInfoBuffer[Index].Location.Core = GET_CORE_ID(CpuInfo[Index].Mpidr); - ProcInfoBuffer[Index].Location.Thread = GET_CORE_ID(CpuInfo[Index].Mpidr); - - Flags = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT; - if (CpuInfo[Index].Flags & CPU_INFO_FLAG_PRIMARY_CPU) { - Flags |= PROCESSOR_AS_BSP_BIT; - } - ProcInfoBuffer[Index].StatusFlag = Flags; - } - - // Create a Guided HOB to tell the ARM TF CPU driver the location and length - // of the communication buffer shared with the Normal world. - NsCommBufMmramRange = (EFI_MMRAM_DESCRIPTOR *) BuildGuidHob ( - &gEfiStandaloneMmNonSecureBufferGuid, - sizeof (EFI_MMRAM_DESCRIPTOR) - ); - NsCommBufMmramRange->PhysicalStart = PayloadBootInfo->SpNsCommBufBase; - NsCommBufMmramRange->CpuStart = PayloadBootInfo->SpNsCommBufBase; - NsCommBufMmramRange->PhysicalSize = PayloadBootInfo->SpNsCommBufSize; - NsCommBufMmramRange->RegionState = EFI_CACHEABLE | EFI_ALLOCATED; - - // Create a Guided HOB to enable the ARM TF CPU driver to share its entry - // point and populate it with the address of the shared buffer - CpuDriverEntryPointDesc = (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *) BuildGuidHob ( - &gEfiArmTfCpuDriverEpDescriptorGuid, - sizeof (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR) - ); - - *CpuDriverEntryPoint = NULL; - CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr = CpuDriverEntryPoint; - - // Find the size of the GUIDed HOB with SRAM ranges - BufferSize = sizeof (EFI_MMRAM_HOB_DESCRIPTOR_BLOCK); - BufferSize += PayloadBootInfo->NumSpMemRegions * sizeof (EFI_MMRAM_DESCRIPTOR); - - // Create a GUIDed HOB with SRAM ranges - MmramRangesHob = BuildGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, BufferSize); - - // Fill up the number of MMRAM memory regions - MmramRangesHob->NumberOfMmReservedRegions = PayloadBootInfo->NumSpMemRegions; - // Fill up the MMRAM ranges - MmramRanges = &MmramRangesHob->Descriptor[0]; - - // Base and size of memory occupied by the Standalone MM image - MmramRanges[0].PhysicalStart = PayloadBootInfo->SpImageBase; - MmramRanges[0].CpuStart = PayloadBootInfo->SpImageBase; - MmramRanges[0].PhysicalSize = PayloadBootInfo->SpImageSize; - MmramRanges[0].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; - - // Base and size of buffer shared with privileged Secure world software - MmramRanges[1].PhysicalStart = PayloadBootInfo->SpSharedBufBase; - MmramRanges[1].CpuStart = PayloadBootInfo->SpSharedBufBase; - MmramRanges[1].PhysicalSize = PayloadBootInfo->SpPcpuSharedBufSize * PayloadBootInfo->NumCpus; - MmramRanges[1].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; - - // Base and size of buffer used for synchronous communication with Normal - // world software - MmramRanges[2].PhysicalStart = PayloadBootInfo->SpNsCommBufBase; - MmramRanges[2].CpuStart = PayloadBootInfo->SpNsCommBufBase; - MmramRanges[2].PhysicalSize = PayloadBootInfo->SpNsCommBufSize; - MmramRanges[2].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; - - // Base and size of memory allocated for stacks for all cpus - MmramRanges[3].PhysicalStart = PayloadBootInfo->SpStackBase; - MmramRanges[3].CpuStart = PayloadBootInfo->SpStackBase; - MmramRanges[3].PhysicalSize = PayloadBootInfo->SpPcpuStackSize * PayloadBootInfo->NumCpus; - MmramRanges[3].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; - - // Base and size of heap memory shared by all cpus - MmramRanges[4].PhysicalStart = (EFI_PHYSICAL_ADDRESS) (UINTN) HobStart; - MmramRanges[4].CpuStart = (EFI_PHYSICAL_ADDRESS) (UINTN) HobStart; - MmramRanges[4].PhysicalSize = HobStart->EfiFreeMemoryBottom - (EFI_PHYSICAL_ADDRESS) (UINTN) HobStart; - MmramRanges[4].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; - - // Base and size of heap memory shared by all cpus - MmramRanges[5].PhysicalStart = HobStart->EfiFreeMemoryBottom; - MmramRanges[5].CpuStart = HobStart->EfiFreeMemoryBottom; - MmramRanges[5].PhysicalSize = HobStart->EfiFreeMemoryTop - HobStart->EfiFreeMemoryBottom; - MmramRanges[5].RegionState = EFI_CACHEABLE; - - return HobStart; -} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c deleted file mode 100644 index 4a380df4a6..0000000000 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c +++ /dev/null @@ -1,322 +0,0 @@ -/** @file - Locate, get and update PE/COFF permissions during Standalone MM - Foundation Entry point on ARM platforms. - -Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/** - Privileged firmware assigns RO & Executable attributes to all memory occupied - by the Boot Firmware Volume. This function sets the correct permissions of - sections in the Standalone MM Core module to be able to access RO and RW data - and make further progress in the boot process. - - @param [in] ImageContext Pointer to PE/COFF image context - @param [in] ImageBase Base of image in memory - @param [in] SectionHeaderOffset Offset of PE/COFF image section header - @param [in] NumberOfSections Number of Sections - @param [in] TextUpdater Function to change code permissions - @param [in] ReadOnlyUpdater Function to change RO permissions - @param [in] ReadWriteUpdater Function to change RW permissions - -**/ -EFI_STATUS -EFIAPI -UpdateMmFoundationPeCoffPermissions ( - IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, - IN EFI_PHYSICAL_ADDRESS ImageBase, - IN UINT32 SectionHeaderOffset, - IN CONST UINT16 NumberOfSections, - IN REGION_PERMISSION_UPDATE_FUNC TextUpdater, - IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater, - IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater - ) -{ - EFI_IMAGE_SECTION_HEADER SectionHeader; - RETURN_STATUS Status; - EFI_PHYSICAL_ADDRESS Base; - UINTN Size; - UINTN ReadSize; - UINTN Index; - - ASSERT (ImageContext != NULL); - - // - // Iterate over the sections - // - for (Index = 0; Index < NumberOfSections; Index++) { - // - // Read section header from file - // - Size = sizeof (EFI_IMAGE_SECTION_HEADER); - ReadSize = Size; - Status = ImageContext->ImageRead ( - ImageContext->Handle, - SectionHeaderOffset, - &Size, - &SectionHeader - ); - - if (RETURN_ERROR (Status) || (Size != ReadSize)) { - DEBUG ((DEBUG_ERROR, - "%a: ImageContext->ImageRead () failed (Status = %r)\n", - __FUNCTION__, Status)); - return Status; - } - - DEBUG ((DEBUG_INFO, - "%a: Section %d of image at 0x%lx has 0x%x permissions\n", - __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics)); - DEBUG ((DEBUG_INFO, - "%a: Section %d of image at 0x%lx has %a name\n", - __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Name)); - DEBUG ((DEBUG_INFO, - "%a: Section %d of image at 0x%lx has 0x%x address\n", - __FUNCTION__, Index, ImageContext->ImageAddress, - ImageContext->ImageAddress + SectionHeader.VirtualAddress)); - DEBUG ((DEBUG_INFO, - "%a: Section %d of image at 0x%lx has 0x%x data\n", - __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.PointerToRawData)); - - // - // If the section is marked as XN then remove the X attribute. Furthermore, - // if it is a writeable section then mark it appropriately as well. - // - if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) { - Base = ImageBase + SectionHeader.VirtualAddress; - - TextUpdater (Base, SectionHeader.Misc.VirtualSize); - - if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) { - ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize); - DEBUG ((DEBUG_INFO, - "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n", - __FUNCTION__, Index, ImageContext->ImageAddress)); - } else { - DEBUG ((DEBUG_INFO, - "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n", - __FUNCTION__, Index, ImageContext->ImageAddress)); - } - } else { - DEBUG ((DEBUG_INFO, - "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n", - __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics)); - } - SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); - } - - return RETURN_SUCCESS; -} - -/** - Privileged firmware assigns RO & Executable attributes to all memory occupied - by the Boot Firmware Volume. This function locates the Standalone MM Core - module PE/COFF image in the BFV and returns this information. - - @param [in] BfvAddress Base Address of Boot Firmware Volume - @param [in, out] TeData Pointer to address for allocating memory - for PE/COFF image data - @param [in, out] TeDataSize Pointer to size of PE/COFF image data - -**/ -EFI_STATUS -EFIAPI -LocateStandaloneMmCorePeCoffData ( - IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress, - IN OUT VOID **TeData, - IN OUT UINTN *TeDataSize - ) -{ - EFI_FFS_FILE_HEADER *FileHeader; - EFI_STATUS Status; - - FileHeader = NULL; - Status = FfsFindNextFile ( - EFI_FV_FILETYPE_SECURITY_CORE, - BfvAddress, - &FileHeader - ); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM FFS file - 0x%x\n", - Status)); - return Status; - } - - Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize); - if (EFI_ERROR (Status)) { - Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Section data - %r\n", - Status)); - return Status; - } - } - - DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData)); - return Status; -} - -/** - Returns the PC COFF section information. - - @param [in, out] ImageContext Pointer to PE/COFF image context - @param [out] ImageBase Base of image in memory - @param [out] SectionHeaderOffset Offset of PE/COFF image section header - @param [out] NumberOfSections Number of Sections - -**/ -STATIC -EFI_STATUS -GetPeCoffSectionInformation ( - IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, - OUT EFI_PHYSICAL_ADDRESS *ImageBase, - OUT UINT32 *SectionHeaderOffset, - OUT UINT16 *NumberOfSections - ) -{ - RETURN_STATUS Status; - EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; - EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; - UINTN Size; - UINTN ReadSize; - - ASSERT (ImageContext != NULL); - ASSERT (SectionHeaderOffset != NULL); - ASSERT (NumberOfSections != NULL); - - Status = PeCoffLoaderGetImageInfo (ImageContext); - if (RETURN_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, - "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n", - __FUNCTION__, Status)); - return Status; - } - - if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) { - // - // The sections need to be at least 4 KB aligned, since that is the - // granularity at which we can tighten permissions. - // - if (!ImageContext->IsTeImage) { - DEBUG ((DEBUG_WARN, - "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n", - __FUNCTION__, ImageContext->ImageAddress, ImageContext->SectionAlignment)); - return RETURN_UNSUPPORTED; - } - ImageContext->SectionAlignment = EFI_PAGE_SIZE; - } - - // - // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much - // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic - // determines if this is a PE32 or PE32+ image. The magic is in the same - // location in both images. - // - Hdr.Union = &HdrData; - Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); - ReadSize = Size; - Status = ImageContext->ImageRead ( - ImageContext->Handle, - ImageContext->PeCoffHeaderOffset, - &Size, - Hdr.Pe32 - ); - - if (RETURN_ERROR (Status) || (Size != ReadSize)) { - DEBUG ((DEBUG_ERROR, - "%a: TmpContext->ImageRead () failed (Status = %r)\n", - __FUNCTION__, Status)); - return Status; - } - - *ImageBase = ImageContext->ImageAddress; - if (!ImageContext->IsTeImage) { - ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE); - - *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + - sizeof (EFI_IMAGE_FILE_HEADER); - *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections; - - switch (Hdr.Pe32->OptionalHeader.Magic) { - case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC: - *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader; - break; - case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC: - *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader; - break; - default: - ASSERT (FALSE); - } - } else { - *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER)); - *NumberOfSections = Hdr.Te->NumberOfSections; - *ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); - } - return RETURN_SUCCESS; -} - -/** - Privileged firmware assigns RO & Executable attributes to all memory occupied - by the Boot Firmware Volume. This function locates the section information of - the Standalone MM Core module to be able to change permissions of the - individual sections later in the boot process. - - @param [in] TeData Pointer to PE/COFF image data - @param [in, out] ImageContext Pointer to PE/COFF image context - @param [out] ImageBase Pointer to ImageBase variable - @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header - @param [in, out] NumberOfSections Number of Sections - -**/ -EFI_STATUS -EFIAPI -GetStandaloneMmCorePeCoffSections ( - IN VOID *TeData, - IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, - OUT EFI_PHYSICAL_ADDRESS *ImageBase, - IN OUT UINT32 *SectionHeaderOffset, - IN OUT UINT16 *NumberOfSections - ) -{ - EFI_STATUS Status; - - // Initialize the Image Context - ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); - ImageContext->Handle = TeData; - ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory; - - DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData)); - - Status = GetPeCoffSectionInformation (ImageContext, ImageBase, - SectionHeaderOffset, NumberOfSections); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status)); - return Status; - } - - DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n", - *SectionHeaderOffset, *NumberOfSections)); - - return Status; -} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c deleted file mode 100644 index b445d6942e..0000000000 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c +++ /dev/null @@ -1,413 +0,0 @@ -/** @file - Entry point to the Standalone MM Foundation when initialized during the SEC - phase on ARM platforms - -Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define SPM_MAJOR_VER_MASK 0xFFFF0000 -#define SPM_MINOR_VER_MASK 0x0000FFFF -#define SPM_MAJOR_VER_SHIFT 16 -#define FFA_NOT_SUPPORTED -1 - -STATIC CONST UINT32 mSpmMajorVer = SPM_MAJOR_VERSION; -STATIC CONST UINT32 mSpmMinorVer = SPM_MINOR_VERSION; - -STATIC CONST UINT32 mSpmMajorVerFfa = SPM_MAJOR_VERSION_FFA; -STATIC CONST UINT32 mSpmMinorVerFfa = SPM_MINOR_VERSION_FFA; - -#define BOOT_PAYLOAD_VERSION 1 - -PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint = NULL; - -/** - Retrieve a pointer to and print the boot information passed by privileged - secure firmware. - - @param [in] SharedBufAddress The pointer memory shared with privileged - firmware. - -**/ -EFI_SECURE_PARTITION_BOOT_INFO * -GetAndPrintBootinformation ( - IN VOID *SharedBufAddress -) -{ - EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo; - EFI_SECURE_PARTITION_CPU_INFO *PayloadCpuInfo; - UINTN Index; - - PayloadBootInfo = (EFI_SECURE_PARTITION_BOOT_INFO *) SharedBufAddress; - - if (PayloadBootInfo == NULL) { - DEBUG ((DEBUG_ERROR, "PayloadBootInfo NULL\n")); - return NULL; - } - - if (PayloadBootInfo->Header.Version != BOOT_PAYLOAD_VERSION) { - DEBUG ((DEBUG_ERROR, "Boot Information Version Mismatch. Current=0x%x, Expected=0x%x.\n", - PayloadBootInfo->Header.Version, BOOT_PAYLOAD_VERSION)); - return NULL; - } - - DEBUG ((DEBUG_INFO, "NumSpMemRegions - 0x%x\n", PayloadBootInfo->NumSpMemRegions)); - DEBUG ((DEBUG_INFO, "SpMemBase - 0x%lx\n", PayloadBootInfo->SpMemBase)); - DEBUG ((DEBUG_INFO, "SpMemLimit - 0x%lx\n", PayloadBootInfo->SpMemLimit)); - DEBUG ((DEBUG_INFO, "SpImageBase - 0x%lx\n", PayloadBootInfo->SpImageBase)); - DEBUG ((DEBUG_INFO, "SpStackBase - 0x%lx\n", PayloadBootInfo->SpStackBase)); - DEBUG ((DEBUG_INFO, "SpHeapBase - 0x%lx\n", PayloadBootInfo->SpHeapBase)); - DEBUG ((DEBUG_INFO, "SpNsCommBufBase - 0x%lx\n", PayloadBootInfo->SpNsCommBufBase)); - DEBUG ((DEBUG_INFO, "SpSharedBufBase - 0x%lx\n", PayloadBootInfo->SpSharedBufBase)); - - DEBUG ((DEBUG_INFO, "SpImageSize - 0x%x\n", PayloadBootInfo->SpImageSize)); - DEBUG ((DEBUG_INFO, "SpPcpuStackSize - 0x%x\n", PayloadBootInfo->SpPcpuStackSize)); - DEBUG ((DEBUG_INFO, "SpHeapSize - 0x%x\n", PayloadBootInfo->SpHeapSize)); - DEBUG ((DEBUG_INFO, "SpNsCommBufSize - 0x%x\n", PayloadBootInfo->SpNsCommBufSize)); - DEBUG ((DEBUG_INFO, "SpPcpuSharedBufSize - 0x%x\n", PayloadBootInfo->SpPcpuSharedBufSize)); - - DEBUG ((DEBUG_INFO, "NumCpus - 0x%x\n", PayloadBootInfo->NumCpus)); - DEBUG ((DEBUG_INFO, "CpuInfo - 0x%p\n", PayloadBootInfo->CpuInfo)); - - PayloadCpuInfo = (EFI_SECURE_PARTITION_CPU_INFO *) PayloadBootInfo->CpuInfo; - - if (PayloadCpuInfo == NULL) { - DEBUG ((DEBUG_ERROR, "PayloadCpuInfo NULL\n")); - return NULL; - } - - for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) { - DEBUG ((DEBUG_INFO, "Mpidr - 0x%lx\n", PayloadCpuInfo[Index].Mpidr)); - DEBUG ((DEBUG_INFO, "LinearId - 0x%x\n", PayloadCpuInfo[Index].LinearId)); - DEBUG ((DEBUG_INFO, "Flags - 0x%x\n", PayloadCpuInfo[Index].Flags)); - } - - return PayloadBootInfo; -} - -/** - A loop to delegated events. - - @param [in] EventCompleteSvcArgs Pointer to the event completion arguments. - -**/ -VOID -EFIAPI -DelegatedEventLoop ( - IN ARM_SVC_ARGS *EventCompleteSvcArgs - ) -{ - BOOLEAN FfaEnabled; - EFI_STATUS Status; - UINTN SvcStatus; - - while (TRUE) { - ArmCallSvc (EventCompleteSvcArgs); - - DEBUG ((DEBUG_INFO, "Received delegated event\n")); - DEBUG ((DEBUG_INFO, "X0 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg0)); - DEBUG ((DEBUG_INFO, "X1 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg1)); - DEBUG ((DEBUG_INFO, "X2 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg2)); - DEBUG ((DEBUG_INFO, "X3 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg3)); - DEBUG ((DEBUG_INFO, "X4 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg4)); - DEBUG ((DEBUG_INFO, "X5 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg5)); - DEBUG ((DEBUG_INFO, "X6 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg6)); - DEBUG ((DEBUG_INFO, "X7 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg7)); - - FfaEnabled = FeaturePcdGet (PcdFfaEnable); - if (FfaEnabled) { - Status = CpuDriverEntryPoint ( - EventCompleteSvcArgs->Arg0, - EventCompleteSvcArgs->Arg6, - EventCompleteSvcArgs->Arg3 - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n", - EventCompleteSvcArgs->Arg3, Status)); - } - } else { - Status = CpuDriverEntryPoint ( - EventCompleteSvcArgs->Arg0, - EventCompleteSvcArgs->Arg3, - EventCompleteSvcArgs->Arg1 - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n", - EventCompleteSvcArgs->Arg0, Status)); - } - } - - switch (Status) { - case EFI_SUCCESS: - SvcStatus = ARM_SVC_SPM_RET_SUCCESS; - break; - case EFI_INVALID_PARAMETER: - SvcStatus = ARM_SVC_SPM_RET_INVALID_PARAMS; - break; - case EFI_ACCESS_DENIED: - SvcStatus = ARM_SVC_SPM_RET_DENIED; - break; - case EFI_OUT_OF_RESOURCES: - SvcStatus = ARM_SVC_SPM_RET_NO_MEMORY; - break; - case EFI_UNSUPPORTED: - SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED; - break; - default: - SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED; - break; - } - - if (FfaEnabled) { - EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64; - EventCompleteSvcArgs->Arg1 = 0; - EventCompleteSvcArgs->Arg2 = 0; - EventCompleteSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64; - EventCompleteSvcArgs->Arg4 = SvcStatus; - } else { - EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64; - EventCompleteSvcArgs->Arg1 = SvcStatus; - } - } -} - -/** - Query the SPM version, check compatibility and return success if compatible. - - @retval EFI_SUCCESS SPM versions compatible. - @retval EFI_UNSUPPORTED SPM versions not compatible. -**/ -STATIC -EFI_STATUS -GetSpmVersion (VOID) -{ - EFI_STATUS Status; - UINT16 CalleeSpmMajorVer; - UINT16 CallerSpmMajorVer; - UINT16 CalleeSpmMinorVer; - UINT16 CallerSpmMinorVer; - UINT32 SpmVersion; - ARM_SVC_ARGS SpmVersionArgs; - - if (FeaturePcdGet (PcdFfaEnable)) { - SpmVersionArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32; - SpmVersionArgs.Arg1 = mSpmMajorVerFfa << SPM_MAJOR_VER_SHIFT; - SpmVersionArgs.Arg1 |= mSpmMinorVerFfa; - CallerSpmMajorVer = mSpmMajorVerFfa; - CallerSpmMinorVer = mSpmMinorVerFfa; - } else { - SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32; - CallerSpmMajorVer = mSpmMajorVer; - CallerSpmMinorVer = mSpmMinorVer; - } - - ArmCallSvc (&SpmVersionArgs); - - SpmVersion = SpmVersionArgs.Arg0; - if (SpmVersion == FFA_NOT_SUPPORTED) { - return EFI_UNSUPPORTED; - } - - CalleeSpmMajorVer = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT); - CalleeSpmMinorVer = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0); - - // Different major revision values indicate possibly incompatible functions. - // For two revisions, A and B, for which the major revision values are - // identical, if the minor revision value of revision B is greater than - // the minor revision value of revision A, then every function in - // revision A must work in a compatible way with revision B. - // However, it is possible for revision B to have a higher - // function count than revision A. - if ((CalleeSpmMajorVer == CallerSpmMajorVer) && - (CalleeSpmMinorVer >= CallerSpmMinorVer)) - { - DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n", - CalleeSpmMajorVer, CalleeSpmMinorVer)); - Status = EFI_SUCCESS; - } - else - { - DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Callee Version: Major=0x%x, Minor=0x%x.\n Caller: Major=0x%x, Minor>=0x%x.\n", - CalleeSpmMajorVer, CalleeSpmMinorVer, CallerSpmMajorVer, CallerSpmMinorVer)); - Status = EFI_UNSUPPORTED; - } - - return Status; -} - -/** - Initialize parameters to be sent via SVC call. - - @param[out] InitMmFoundationSvcArgs Args structure - @param[out] Ret Return Code - -**/ -STATIC -VOID -InitArmSvcArgs ( - OUT ARM_SVC_ARGS *InitMmFoundationSvcArgs, - OUT INT32 *Ret - ) -{ - if (FeaturePcdGet (PcdFfaEnable)) { - InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64; - InitMmFoundationSvcArgs->Arg1 = 0; - InitMmFoundationSvcArgs->Arg2 = 0; - InitMmFoundationSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64; - InitMmFoundationSvcArgs->Arg4 = *Ret; - } else { - InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64; - InitMmFoundationSvcArgs->Arg1 = *Ret; - } -} - -/** - The entry point of Standalone MM Foundation. - - @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP. - @param [in] SharedBufSize Size of the shared buffer. - @param [in] cookie1 Cookie 1 - @param [in] cookie2 Cookie 2 - -**/ -VOID -EFIAPI -_ModuleEntryPoint ( - IN VOID *SharedBufAddress, - IN UINT64 SharedBufSize, - IN UINT64 cookie1, - IN UINT64 cookie2 - ) -{ - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo; - ARM_SVC_ARGS InitMmFoundationSvcArgs; - EFI_STATUS Status; - INT32 Ret; - UINT32 SectionHeaderOffset; - UINT16 NumberOfSections; - VOID *HobStart; - VOID *TeData; - UINTN TeDataSize; - EFI_PHYSICAL_ADDRESS ImageBase; - - // Get Secure Partition Manager Version Information - Status = GetSpmVersion (); - if (EFI_ERROR (Status)) { - goto finish; - } - - PayloadBootInfo = GetAndPrintBootinformation (SharedBufAddress); - if (PayloadBootInfo == NULL) { - Status = EFI_UNSUPPORTED; - goto finish; - } - - // Locate PE/COFF File information for the Standalone MM core module - Status = LocateStandaloneMmCorePeCoffData ( - (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PayloadBootInfo->SpImageBase, - &TeData, - &TeDataSize - ); - - if (EFI_ERROR (Status)) { - goto finish; - } - - // Obtain the PE/COFF Section information for the Standalone MM core module - Status = GetStandaloneMmCorePeCoffSections ( - TeData, - &ImageContext, - &ImageBase, - &SectionHeaderOffset, - &NumberOfSections - ); - - if (EFI_ERROR (Status)) { - goto finish; - } - - // - // ImageBase may deviate from ImageContext.ImageAddress if we are dealing - // with a TE image, in which case the latter points to the actual offset - // of the image, whereas ImageBase refers to the address where the image - // would start if the stripped PE headers were still in place. In either - // case, we need to fix up ImageBase so it refers to the actual current - // load address. - // - ImageBase += (UINTN)TeData - ImageContext.ImageAddress; - - // Update the memory access permissions of individual sections in the - // Standalone MM core module - Status = UpdateMmFoundationPeCoffPermissions ( - &ImageContext, - ImageBase, - SectionHeaderOffset, - NumberOfSections, - ArmSetMemoryRegionNoExec, - ArmSetMemoryRegionReadOnly, - ArmClearMemoryRegionReadOnly - ); - - if (EFI_ERROR (Status)) { - goto finish; - } - - if (ImageContext.ImageAddress != (UINTN)TeData) { - ImageContext.ImageAddress = (UINTN)TeData; - ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB); - ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB); - - Status = PeCoffLoaderRelocateImage (&ImageContext); - ASSERT_EFI_ERROR (Status); - } - - // - // Create Hoblist based upon boot information passed by privileged software - // - HobStart = CreateHobListFromBootInfo (&CpuDriverEntryPoint, PayloadBootInfo); - - // - // Call the MM Core entry point - // - ProcessModuleEntryPointList (HobStart); - - DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP 0x%lx\n", (UINT64) CpuDriverEntryPoint)); - -finish: - if (Status == RETURN_UNSUPPORTED) { - Ret = -1; - } else if (Status == RETURN_INVALID_PARAMETER) { - Ret = -2; - } else if (Status == EFI_NOT_FOUND) { - Ret = -7; - } else { - Ret = 0; - } - ZeroMem (&InitMmFoundationSvcArgs, sizeof(InitMmFoundationSvcArgs)); - InitArmSvcArgs (&InitMmFoundationSvcArgs, &Ret); - DelegatedEventLoop (&InitMmFoundationSvcArgs); -} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/CreateHobList.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/CreateHobList.c new file mode 100644 index 0000000000..85f8194687 --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/CreateHobList.c @@ -0,0 +1,205 @@ +/** @file + Creates HOB during Standalone MM Foundation entry point + on ARM platforms. + +Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern EFI_HOB_HANDOFF_INFO_TABLE* +HobConstructor ( + IN VOID *EfiMemoryBegin, + IN UINTN EfiMemoryLength, + IN VOID *EfiFreeMemoryBottom, + IN VOID *EfiFreeMemoryTop + ); + +// GUID to identify HOB with whereabouts of communication buffer with Normal +// World +extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid; + +// GUID to identify HOB where the entry point of the CPU driver will be +// populated to allow this entry point driver to invoke it upon receipt of an +// event +extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid; + +/** + Use the boot information passed by privileged firmware to populate a HOB list + suitable for consumption by the MM Core and drivers. + + @param [in, out] CpuDriverEntryPoint Address of MM CPU driver entrypoint + @param [in] PayloadBootInfo Boot information passed by privileged + firmware + +**/ +VOID * +CreateHobListFromBootInfo ( + IN OUT PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *CpuDriverEntryPoint, + IN EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo +) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HobStart; + EFI_RESOURCE_ATTRIBUTE_TYPE Attributes; + UINT32 Index; + UINT32 BufferSize; + UINT32 Flags; + EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHob; + EFI_MMRAM_DESCRIPTOR *MmramRanges; + EFI_MMRAM_DESCRIPTOR *NsCommBufMmramRange; + MP_INFORMATION_HOB_DATA *MpInformationHobData; + EFI_PROCESSOR_INFORMATION *ProcInfoBuffer; + EFI_SECURE_PARTITION_CPU_INFO *CpuInfo; + ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc; + + // Create a hoblist with a PHIT and EOH + HobStart = HobConstructor ( + (VOID *) (UINTN) PayloadBootInfo->SpMemBase, + (UINTN) PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase, + (VOID *) (UINTN) PayloadBootInfo->SpHeapBase, + (VOID *) (UINTN) (PayloadBootInfo->SpHeapBase + PayloadBootInfo->SpHeapSize) + ); + + // Check that the Hoblist starts at the bottom of the Heap + ASSERT (HobStart == (VOID *) (UINTN) PayloadBootInfo->SpHeapBase); + + // Build a Boot Firmware Volume HOB + BuildFvHob (PayloadBootInfo->SpImageBase, PayloadBootInfo->SpImageSize); + + // Build a resource descriptor Hob that describes the available physical + // memory range + Attributes = ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + Attributes, + (UINTN) PayloadBootInfo->SpMemBase, + PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase + ); + + // Find the size of the GUIDed HOB with MP information + BufferSize = sizeof (MP_INFORMATION_HOB_DATA); + BufferSize += sizeof (EFI_PROCESSOR_INFORMATION) * PayloadBootInfo->NumCpus; + + // Create a Guided MP information HOB to enable the ARM TF CPU driver to + // perform per-cpu allocations. + MpInformationHobData = BuildGuidHob (&gMpInformationHobGuid, BufferSize); + + // Populate the MP information HOB with the topology information passed by + // privileged firmware + MpInformationHobData->NumberOfProcessors = PayloadBootInfo->NumCpus; + MpInformationHobData->NumberOfEnabledProcessors = PayloadBootInfo->NumCpus; + ProcInfoBuffer = MpInformationHobData->ProcessorInfoBuffer; + CpuInfo = PayloadBootInfo->CpuInfo; + + for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) { + ProcInfoBuffer[Index].ProcessorId = CpuInfo[Index].Mpidr; + ProcInfoBuffer[Index].Location.Package = GET_CLUSTER_ID(CpuInfo[Index].Mpidr); + ProcInfoBuffer[Index].Location.Core = GET_CORE_ID(CpuInfo[Index].Mpidr); + ProcInfoBuffer[Index].Location.Thread = GET_CORE_ID(CpuInfo[Index].Mpidr); + + Flags = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT; + if (CpuInfo[Index].Flags & CPU_INFO_FLAG_PRIMARY_CPU) { + Flags |= PROCESSOR_AS_BSP_BIT; + } + ProcInfoBuffer[Index].StatusFlag = Flags; + } + + // Create a Guided HOB to tell the ARM TF CPU driver the location and length + // of the communication buffer shared with the Normal world. + NsCommBufMmramRange = (EFI_MMRAM_DESCRIPTOR *) BuildGuidHob ( + &gEfiStandaloneMmNonSecureBufferGuid, + sizeof (EFI_MMRAM_DESCRIPTOR) + ); + NsCommBufMmramRange->PhysicalStart = PayloadBootInfo->SpNsCommBufBase; + NsCommBufMmramRange->CpuStart = PayloadBootInfo->SpNsCommBufBase; + NsCommBufMmramRange->PhysicalSize = PayloadBootInfo->SpNsCommBufSize; + NsCommBufMmramRange->RegionState = EFI_CACHEABLE | EFI_ALLOCATED; + + // Create a Guided HOB to enable the ARM TF CPU driver to share its entry + // point and populate it with the address of the shared buffer + CpuDriverEntryPointDesc = (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *) BuildGuidHob ( + &gEfiArmTfCpuDriverEpDescriptorGuid, + sizeof (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR) + ); + + *CpuDriverEntryPoint = NULL; + CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr = CpuDriverEntryPoint; + + // Find the size of the GUIDed HOB with SRAM ranges + BufferSize = sizeof (EFI_MMRAM_HOB_DESCRIPTOR_BLOCK); + BufferSize += PayloadBootInfo->NumSpMemRegions * sizeof (EFI_MMRAM_DESCRIPTOR); + + // Create a GUIDed HOB with SRAM ranges + MmramRangesHob = BuildGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, BufferSize); + + // Fill up the number of MMRAM memory regions + MmramRangesHob->NumberOfMmReservedRegions = PayloadBootInfo->NumSpMemRegions; + // Fill up the MMRAM ranges + MmramRanges = &MmramRangesHob->Descriptor[0]; + + // Base and size of memory occupied by the Standalone MM image + MmramRanges[0].PhysicalStart = PayloadBootInfo->SpImageBase; + MmramRanges[0].CpuStart = PayloadBootInfo->SpImageBase; + MmramRanges[0].PhysicalSize = PayloadBootInfo->SpImageSize; + MmramRanges[0].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; + + // Base and size of buffer shared with privileged Secure world software + MmramRanges[1].PhysicalStart = PayloadBootInfo->SpSharedBufBase; + MmramRanges[1].CpuStart = PayloadBootInfo->SpSharedBufBase; + MmramRanges[1].PhysicalSize = PayloadBootInfo->SpPcpuSharedBufSize * PayloadBootInfo->NumCpus; + MmramRanges[1].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; + + // Base and size of buffer used for synchronous communication with Normal + // world software + MmramRanges[2].PhysicalStart = PayloadBootInfo->SpNsCommBufBase; + MmramRanges[2].CpuStart = PayloadBootInfo->SpNsCommBufBase; + MmramRanges[2].PhysicalSize = PayloadBootInfo->SpNsCommBufSize; + MmramRanges[2].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; + + // Base and size of memory allocated for stacks for all cpus + MmramRanges[3].PhysicalStart = PayloadBootInfo->SpStackBase; + MmramRanges[3].CpuStart = PayloadBootInfo->SpStackBase; + MmramRanges[3].PhysicalSize = PayloadBootInfo->SpPcpuStackSize * PayloadBootInfo->NumCpus; + MmramRanges[3].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; + + // Base and size of heap memory shared by all cpus + MmramRanges[4].PhysicalStart = (EFI_PHYSICAL_ADDRESS) (UINTN) HobStart; + MmramRanges[4].CpuStart = (EFI_PHYSICAL_ADDRESS) (UINTN) HobStart; + MmramRanges[4].PhysicalSize = HobStart->EfiFreeMemoryBottom - (EFI_PHYSICAL_ADDRESS) (UINTN) HobStart; + MmramRanges[4].RegionState = EFI_CACHEABLE | EFI_ALLOCATED; + + // Base and size of heap memory shared by all cpus + MmramRanges[5].PhysicalStart = HobStart->EfiFreeMemoryBottom; + MmramRanges[5].CpuStart = HobStart->EfiFreeMemoryBottom; + MmramRanges[5].PhysicalSize = HobStart->EfiFreeMemoryTop - HobStart->EfiFreeMemoryBottom; + MmramRanges[5].RegionState = EFI_CACHEABLE; + + return HobStart; +} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c new file mode 100644 index 0000000000..cd4b90823e --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/SetPermissions.c @@ -0,0 +1,322 @@ +/** @file + Locate, get and update PE/COFF permissions during Standalone MM + Foundation Entry point on ARM platforms. + +Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + Privileged firmware assigns RO & Executable attributes to all memory occupied + by the Boot Firmware Volume. This function sets the correct permissions of + sections in the Standalone MM Core module to be able to access RO and RW data + and make further progress in the boot process. + + @param [in] ImageContext Pointer to PE/COFF image context + @param [in] ImageBase Base of image in memory + @param [in] SectionHeaderOffset Offset of PE/COFF image section header + @param [in] NumberOfSections Number of Sections + @param [in] TextUpdater Function to change code permissions + @param [in] ReadOnlyUpdater Function to change RO permissions + @param [in] ReadWriteUpdater Function to change RW permissions + +**/ +EFI_STATUS +EFIAPI +UpdateMmFoundationPeCoffPermissions ( + IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT32 SectionHeaderOffset, + IN CONST UINT16 NumberOfSections, + IN REGION_PERMISSION_UPDATE_FUNC TextUpdater, + IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater, + IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater + ) +{ + EFI_IMAGE_SECTION_HEADER SectionHeader; + RETURN_STATUS Status; + EFI_PHYSICAL_ADDRESS Base; + UINTN Size; + UINTN ReadSize; + UINTN Index; + + ASSERT (ImageContext != NULL); + + // + // Iterate over the sections + // + for (Index = 0; Index < NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + DEBUG ((DEBUG_ERROR, + "%a: ImageContext->ImageRead () failed (Status = %r)\n", + __FUNCTION__, Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, + "%a: Section %d of image at 0x%lx has 0x%x permissions\n", + __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics)); + DEBUG ((DEBUG_INFO, + "%a: Section %d of image at 0x%lx has %a name\n", + __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Name)); + DEBUG ((DEBUG_INFO, + "%a: Section %d of image at 0x%lx has 0x%x address\n", + __FUNCTION__, Index, ImageContext->ImageAddress, + ImageContext->ImageAddress + SectionHeader.VirtualAddress)); + DEBUG ((DEBUG_INFO, + "%a: Section %d of image at 0x%lx has 0x%x data\n", + __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.PointerToRawData)); + + // + // If the section is marked as XN then remove the X attribute. Furthermore, + // if it is a writeable section then mark it appropriately as well. + // + if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) { + Base = ImageBase + SectionHeader.VirtualAddress; + + TextUpdater (Base, SectionHeader.Misc.VirtualSize); + + if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) { + ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize); + DEBUG ((DEBUG_INFO, + "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n", + __FUNCTION__, Index, ImageContext->ImageAddress)); + } else { + DEBUG ((DEBUG_INFO, + "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n", + __FUNCTION__, Index, ImageContext->ImageAddress)); + } + } else { + DEBUG ((DEBUG_INFO, + "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n", + __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics)); + } + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + return RETURN_SUCCESS; +} + +/** + Privileged firmware assigns RO & Executable attributes to all memory occupied + by the Boot Firmware Volume. This function locates the Standalone MM Core + module PE/COFF image in the BFV and returns this information. + + @param [in] BfvAddress Base Address of Boot Firmware Volume + @param [in, out] TeData Pointer to address for allocating memory + for PE/COFF image data + @param [in, out] TeDataSize Pointer to size of PE/COFF image data + +**/ +EFI_STATUS +EFIAPI +LocateStandaloneMmCorePeCoffData ( + IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress, + IN OUT VOID **TeData, + IN OUT UINTN *TeDataSize + ) +{ + EFI_FFS_FILE_HEADER *FileHeader; + EFI_STATUS Status; + + FileHeader = NULL; + Status = FfsFindNextFile ( + EFI_FV_FILETYPE_SECURITY_CORE, + BfvAddress, + &FileHeader + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM FFS file - 0x%x\n", + Status)); + return Status; + } + + Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize); + if (EFI_ERROR (Status)) { + Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Section data - %r\n", + Status)); + return Status; + } + } + + DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData)); + return Status; +} + +/** + Returns the PC COFF section information. + + @param [in, out] ImageContext Pointer to PE/COFF image context + @param [out] ImageBase Base of image in memory + @param [out] SectionHeaderOffset Offset of PE/COFF image section header + @param [out] NumberOfSections Number of Sections + +**/ +STATIC +EFI_STATUS +GetPeCoffSectionInformation ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_PHYSICAL_ADDRESS *ImageBase, + OUT UINT32 *SectionHeaderOffset, + OUT UINT16 *NumberOfSections + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; + UINTN Size; + UINTN ReadSize; + + ASSERT (ImageContext != NULL); + ASSERT (SectionHeaderOffset != NULL); + ASSERT (NumberOfSections != NULL); + + Status = PeCoffLoaderGetImageInfo (ImageContext); + if (RETURN_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n", + __FUNCTION__, Status)); + return Status; + } + + if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) { + // + // The sections need to be at least 4 KB aligned, since that is the + // granularity at which we can tighten permissions. + // + if (!ImageContext->IsTeImage) { + DEBUG ((DEBUG_WARN, + "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n", + __FUNCTION__, ImageContext->ImageAddress, ImageContext->SectionAlignment)); + return RETURN_UNSUPPORTED; + } + ImageContext->SectionAlignment = EFI_PAGE_SIZE; + } + + // + // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much + // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic + // determines if this is a PE32 or PE32+ image. The magic is in the same + // location in both images. + // + Hdr.Union = &HdrData; + Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); + ReadSize = Size; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + Hdr.Pe32 + ); + + if (RETURN_ERROR (Status) || (Size != ReadSize)) { + DEBUG ((DEBUG_ERROR, + "%a: TmpContext->ImageRead () failed (Status = %r)\n", + __FUNCTION__, Status)); + return Status; + } + + *ImageBase = ImageContext->ImageAddress; + if (!ImageContext->IsTeImage) { + ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE); + + *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER); + *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections; + + switch (Hdr.Pe32->OptionalHeader.Magic) { + case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC: + *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader; + break; + case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC: + *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader; + break; + default: + ASSERT (FALSE); + } + } else { + *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER)); + *NumberOfSections = Hdr.Te->NumberOfSections; + *ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + } + return RETURN_SUCCESS; +} + +/** + Privileged firmware assigns RO & Executable attributes to all memory occupied + by the Boot Firmware Volume. This function locates the section information of + the Standalone MM Core module to be able to change permissions of the + individual sections later in the boot process. + + @param [in] TeData Pointer to PE/COFF image data + @param [in, out] ImageContext Pointer to PE/COFF image context + @param [out] ImageBase Pointer to ImageBase variable + @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header + @param [in, out] NumberOfSections Number of Sections + +**/ +EFI_STATUS +EFIAPI +GetStandaloneMmCorePeCoffSections ( + IN VOID *TeData, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_PHYSICAL_ADDRESS *ImageBase, + IN OUT UINT32 *SectionHeaderOffset, + IN OUT UINT16 *NumberOfSections + ) +{ + EFI_STATUS Status; + + // Initialize the Image Context + ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + ImageContext->Handle = TeData; + ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory; + + DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData)); + + Status = GetPeCoffSectionInformation (ImageContext, ImageBase, + SectionHeaderOffset, NumberOfSections); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n", + *SectionHeaderOffset, *NumberOfSections)); + + return Status; +} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c new file mode 100644 index 0000000000..49cf51a789 --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreEntryPoint.c @@ -0,0 +1,413 @@ +/** @file + Entry point to the Standalone MM Foundation when initialized during the SEC + phase on ARM platforms + +Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SPM_MAJOR_VER_MASK 0xFFFF0000 +#define SPM_MINOR_VER_MASK 0x0000FFFF +#define SPM_MAJOR_VER_SHIFT 16 +#define FFA_NOT_SUPPORTED -1 + +STATIC CONST UINT32 mSpmMajorVer = SPM_MAJOR_VERSION; +STATIC CONST UINT32 mSpmMinorVer = SPM_MINOR_VERSION; + +STATIC CONST UINT32 mSpmMajorVerFfa = SPM_MAJOR_VERSION_FFA; +STATIC CONST UINT32 mSpmMinorVerFfa = SPM_MINOR_VERSION_FFA; + +#define BOOT_PAYLOAD_VERSION 1 + +PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint = NULL; + +/** + Retrieve a pointer to and print the boot information passed by privileged + secure firmware. + + @param [in] SharedBufAddress The pointer memory shared with privileged + firmware. + +**/ +EFI_SECURE_PARTITION_BOOT_INFO * +GetAndPrintBootinformation ( + IN VOID *SharedBufAddress +) +{ + EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo; + EFI_SECURE_PARTITION_CPU_INFO *PayloadCpuInfo; + UINTN Index; + + PayloadBootInfo = (EFI_SECURE_PARTITION_BOOT_INFO *) SharedBufAddress; + + if (PayloadBootInfo == NULL) { + DEBUG ((DEBUG_ERROR, "PayloadBootInfo NULL\n")); + return NULL; + } + + if (PayloadBootInfo->Header.Version != BOOT_PAYLOAD_VERSION) { + DEBUG ((DEBUG_ERROR, "Boot Information Version Mismatch. Current=0x%x, Expected=0x%x.\n", + PayloadBootInfo->Header.Version, BOOT_PAYLOAD_VERSION)); + return NULL; + } + + DEBUG ((DEBUG_INFO, "NumSpMemRegions - 0x%x\n", PayloadBootInfo->NumSpMemRegions)); + DEBUG ((DEBUG_INFO, "SpMemBase - 0x%lx\n", PayloadBootInfo->SpMemBase)); + DEBUG ((DEBUG_INFO, "SpMemLimit - 0x%lx\n", PayloadBootInfo->SpMemLimit)); + DEBUG ((DEBUG_INFO, "SpImageBase - 0x%lx\n", PayloadBootInfo->SpImageBase)); + DEBUG ((DEBUG_INFO, "SpStackBase - 0x%lx\n", PayloadBootInfo->SpStackBase)); + DEBUG ((DEBUG_INFO, "SpHeapBase - 0x%lx\n", PayloadBootInfo->SpHeapBase)); + DEBUG ((DEBUG_INFO, "SpNsCommBufBase - 0x%lx\n", PayloadBootInfo->SpNsCommBufBase)); + DEBUG ((DEBUG_INFO, "SpSharedBufBase - 0x%lx\n", PayloadBootInfo->SpSharedBufBase)); + + DEBUG ((DEBUG_INFO, "SpImageSize - 0x%x\n", PayloadBootInfo->SpImageSize)); + DEBUG ((DEBUG_INFO, "SpPcpuStackSize - 0x%x\n", PayloadBootInfo->SpPcpuStackSize)); + DEBUG ((DEBUG_INFO, "SpHeapSize - 0x%x\n", PayloadBootInfo->SpHeapSize)); + DEBUG ((DEBUG_INFO, "SpNsCommBufSize - 0x%x\n", PayloadBootInfo->SpNsCommBufSize)); + DEBUG ((DEBUG_INFO, "SpPcpuSharedBufSize - 0x%x\n", PayloadBootInfo->SpPcpuSharedBufSize)); + + DEBUG ((DEBUG_INFO, "NumCpus - 0x%x\n", PayloadBootInfo->NumCpus)); + DEBUG ((DEBUG_INFO, "CpuInfo - 0x%p\n", PayloadBootInfo->CpuInfo)); + + PayloadCpuInfo = (EFI_SECURE_PARTITION_CPU_INFO *) PayloadBootInfo->CpuInfo; + + if (PayloadCpuInfo == NULL) { + DEBUG ((DEBUG_ERROR, "PayloadCpuInfo NULL\n")); + return NULL; + } + + for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) { + DEBUG ((DEBUG_INFO, "Mpidr - 0x%lx\n", PayloadCpuInfo[Index].Mpidr)); + DEBUG ((DEBUG_INFO, "LinearId - 0x%x\n", PayloadCpuInfo[Index].LinearId)); + DEBUG ((DEBUG_INFO, "Flags - 0x%x\n", PayloadCpuInfo[Index].Flags)); + } + + return PayloadBootInfo; +} + +/** + A loop to delegated events. + + @param [in] EventCompleteSvcArgs Pointer to the event completion arguments. + +**/ +VOID +EFIAPI +DelegatedEventLoop ( + IN ARM_SVC_ARGS *EventCompleteSvcArgs + ) +{ + BOOLEAN FfaEnabled; + EFI_STATUS Status; + UINTN SvcStatus; + + while (TRUE) { + ArmCallSvc (EventCompleteSvcArgs); + + DEBUG ((DEBUG_INFO, "Received delegated event\n")); + DEBUG ((DEBUG_INFO, "X0 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg0)); + DEBUG ((DEBUG_INFO, "X1 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg1)); + DEBUG ((DEBUG_INFO, "X2 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg2)); + DEBUG ((DEBUG_INFO, "X3 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg3)); + DEBUG ((DEBUG_INFO, "X4 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg4)); + DEBUG ((DEBUG_INFO, "X5 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg5)); + DEBUG ((DEBUG_INFO, "X6 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg6)); + DEBUG ((DEBUG_INFO, "X7 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg7)); + + FfaEnabled = FeaturePcdGet (PcdFfaEnable); + if (FfaEnabled) { + Status = CpuDriverEntryPoint ( + EventCompleteSvcArgs->Arg0, + EventCompleteSvcArgs->Arg6, + EventCompleteSvcArgs->Arg3 + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n", + EventCompleteSvcArgs->Arg3, Status)); + } + } else { + Status = CpuDriverEntryPoint ( + EventCompleteSvcArgs->Arg0, + EventCompleteSvcArgs->Arg3, + EventCompleteSvcArgs->Arg1 + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n", + EventCompleteSvcArgs->Arg0, Status)); + } + } + + switch (Status) { + case EFI_SUCCESS: + SvcStatus = ARM_SVC_SPM_RET_SUCCESS; + break; + case EFI_INVALID_PARAMETER: + SvcStatus = ARM_SVC_SPM_RET_INVALID_PARAMS; + break; + case EFI_ACCESS_DENIED: + SvcStatus = ARM_SVC_SPM_RET_DENIED; + break; + case EFI_OUT_OF_RESOURCES: + SvcStatus = ARM_SVC_SPM_RET_NO_MEMORY; + break; + case EFI_UNSUPPORTED: + SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED; + break; + default: + SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED; + break; + } + + if (FfaEnabled) { + EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP; + EventCompleteSvcArgs->Arg1 = 0; + EventCompleteSvcArgs->Arg2 = 0; + EventCompleteSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE; + EventCompleteSvcArgs->Arg4 = SvcStatus; + } else { + EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE; + EventCompleteSvcArgs->Arg1 = SvcStatus; + } + } +} + +/** + Query the SPM version, check compatibility and return success if compatible. + + @retval EFI_SUCCESS SPM versions compatible. + @retval EFI_UNSUPPORTED SPM versions not compatible. +**/ +STATIC +EFI_STATUS +GetSpmVersion (VOID) +{ + EFI_STATUS Status; + UINT16 CalleeSpmMajorVer; + UINT16 CallerSpmMajorVer; + UINT16 CalleeSpmMinorVer; + UINT16 CallerSpmMinorVer; + UINT32 SpmVersion; + ARM_SVC_ARGS SpmVersionArgs; + + if (FeaturePcdGet (PcdFfaEnable)) { + SpmVersionArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32; + SpmVersionArgs.Arg1 = mSpmMajorVerFfa << SPM_MAJOR_VER_SHIFT; + SpmVersionArgs.Arg1 |= mSpmMinorVerFfa; + CallerSpmMajorVer = mSpmMajorVerFfa; + CallerSpmMinorVer = mSpmMinorVerFfa; + } else { + SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32; + CallerSpmMajorVer = mSpmMajorVer; + CallerSpmMinorVer = mSpmMinorVer; + } + + ArmCallSvc (&SpmVersionArgs); + + SpmVersion = SpmVersionArgs.Arg0; + if (SpmVersion == FFA_NOT_SUPPORTED) { + return EFI_UNSUPPORTED; + } + + CalleeSpmMajorVer = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT); + CalleeSpmMinorVer = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0); + + // Different major revision values indicate possibly incompatible functions. + // For two revisions, A and B, for which the major revision values are + // identical, if the minor revision value of revision B is greater than + // the minor revision value of revision A, then every function in + // revision A must work in a compatible way with revision B. + // However, it is possible for revision B to have a higher + // function count than revision A. + if ((CalleeSpmMajorVer == CallerSpmMajorVer) && + (CalleeSpmMinorVer >= CallerSpmMinorVer)) + { + DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n", + CalleeSpmMajorVer, CalleeSpmMinorVer)); + Status = EFI_SUCCESS; + } + else + { + DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Callee Version: Major=0x%x, Minor=0x%x.\n Caller: Major=0x%x, Minor>=0x%x.\n", + CalleeSpmMajorVer, CalleeSpmMinorVer, CallerSpmMajorVer, CallerSpmMinorVer)); + Status = EFI_UNSUPPORTED; + } + + return Status; +} + +/** + Initialize parameters to be sent via SVC call. + + @param[out] InitMmFoundationSvcArgs Args structure + @param[out] Ret Return Code + +**/ +STATIC +VOID +InitArmSvcArgs ( + OUT ARM_SVC_ARGS *InitMmFoundationSvcArgs, + OUT INT32 *Ret + ) +{ + if (FeaturePcdGet (PcdFfaEnable)) { + InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP; + InitMmFoundationSvcArgs->Arg1 = 0; + InitMmFoundationSvcArgs->Arg2 = 0; + InitMmFoundationSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE; + InitMmFoundationSvcArgs->Arg4 = *Ret; + } else { + InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE; + InitMmFoundationSvcArgs->Arg1 = *Ret; + } +} + +/** + The entry point of Standalone MM Foundation. + + @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP. + @param [in] SharedBufSize Size of the shared buffer. + @param [in] cookie1 Cookie 1 + @param [in] cookie2 Cookie 2 + +**/ +VOID +EFIAPI +_ModuleEntryPoint ( + IN VOID *SharedBufAddress, + IN UINT64 SharedBufSize, + IN UINT64 cookie1, + IN UINT64 cookie2 + ) +{ + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo; + ARM_SVC_ARGS InitMmFoundationSvcArgs; + EFI_STATUS Status; + INT32 Ret; + UINT32 SectionHeaderOffset; + UINT16 NumberOfSections; + VOID *HobStart; + VOID *TeData; + UINTN TeDataSize; + EFI_PHYSICAL_ADDRESS ImageBase; + + // Get Secure Partition Manager Version Information + Status = GetSpmVersion (); + if (EFI_ERROR (Status)) { + goto finish; + } + + PayloadBootInfo = GetAndPrintBootinformation (SharedBufAddress); + if (PayloadBootInfo == NULL) { + Status = EFI_UNSUPPORTED; + goto finish; + } + + // Locate PE/COFF File information for the Standalone MM core module + Status = LocateStandaloneMmCorePeCoffData ( + (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PayloadBootInfo->SpImageBase, + &TeData, + &TeDataSize + ); + + if (EFI_ERROR (Status)) { + goto finish; + } + + // Obtain the PE/COFF Section information for the Standalone MM core module + Status = GetStandaloneMmCorePeCoffSections ( + TeData, + &ImageContext, + &ImageBase, + &SectionHeaderOffset, + &NumberOfSections + ); + + if (EFI_ERROR (Status)) { + goto finish; + } + + // + // ImageBase may deviate from ImageContext.ImageAddress if we are dealing + // with a TE image, in which case the latter points to the actual offset + // of the image, whereas ImageBase refers to the address where the image + // would start if the stripped PE headers were still in place. In either + // case, we need to fix up ImageBase so it refers to the actual current + // load address. + // + ImageBase += (UINTN)TeData - ImageContext.ImageAddress; + + // Update the memory access permissions of individual sections in the + // Standalone MM core module + Status = UpdateMmFoundationPeCoffPermissions ( + &ImageContext, + ImageBase, + SectionHeaderOffset, + NumberOfSections, + ArmSetMemoryRegionNoExec, + ArmSetMemoryRegionReadOnly, + ArmClearMemoryRegionReadOnly + ); + + if (EFI_ERROR (Status)) { + goto finish; + } + + if (ImageContext.ImageAddress != (UINTN)TeData) { + ImageContext.ImageAddress = (UINTN)TeData; + ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB); + ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB); + + Status = PeCoffLoaderRelocateImage (&ImageContext); + ASSERT_EFI_ERROR (Status); + } + + // + // Create Hoblist based upon boot information passed by privileged software + // + HobStart = CreateHobListFromBootInfo (&CpuDriverEntryPoint, PayloadBootInfo); + + // + // Call the MM Core entry point + // + ProcessModuleEntryPointList (HobStart); + + DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP %p\n", (VOID *) CpuDriverEntryPoint)); + +finish: + if (Status == RETURN_UNSUPPORTED) { + Ret = -1; + } else if (Status == RETURN_INVALID_PARAMETER) { + Ret = -2; + } else if (Status == EFI_NOT_FOUND) { + Ret = -7; + } else { + Ret = 0; + } + ZeroMem (&InitMmFoundationSvcArgs, sizeof(InitMmFoundationSvcArgs)); + InitArmSvcArgs (&InitMmFoundationSvcArgs, &Ret); + DelegatedEventLoop (&InitMmFoundationSvcArgs); +} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf index 4fa426f58e..1762586cfa 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf @@ -21,10 +21,10 @@ # VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only) # -[Sources.AARCH64] - AArch64/StandaloneMmCoreEntryPoint.c - AArch64/SetPermissions.c - AArch64/CreateHobList.c +[Sources.AARCH64, Sources.ARM] + Arm/StandaloneMmCoreEntryPoint.c + Arm/SetPermissions.c + Arm/CreateHobList.c [Sources.X64] X64/StandaloneMmCoreEntryPoint.c @@ -34,14 +34,14 @@ MdeModulePkg/MdeModulePkg.dec StandaloneMmPkg/StandaloneMmPkg.dec -[Packages.AARCH64] +[Packages.ARM, Packages.AARCH64] ArmPkg/ArmPkg.dec [LibraryClasses] BaseLib DebugLib -[LibraryClasses.AARCH64] +[LibraryClasses.ARM, LibraryClasses.AARCH64] StandaloneMmMmuLib ArmSvcLib @@ -51,7 +51,7 @@ gEfiStandaloneMmNonSecureBufferGuid gEfiArmTfCpuDriverEpDescriptorGuid -[FeaturePcd.AARCH64] +[FeaturePcd.ARM, FeaturePcd.AARCH64] gArmTokenSpaceGuid.PcdFfaEnable [BuildOptions] diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c deleted file mode 100644 index 0ec2d4ad6f..0000000000 --- a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c +++ /dev/null @@ -1,330 +0,0 @@ -/** @file - HOB Library implementation for Standalone MM Core. - -Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
-Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
- -SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include - -#include -#include -#include - -#include - -// -// Cache copy of HobList pointer. -// -VOID *gHobList = NULL; - -VOID * -CreateHob ( - IN UINT16 HobType, - IN UINT16 HobLength - ) -{ - EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; - EFI_HOB_GENERIC_HEADER *HobEnd; - EFI_PHYSICAL_ADDRESS FreeMemory; - VOID *Hob; - - HandOffHob = GetHobList (); - - HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); - - FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; - - if (FreeMemory < HobLength) { - return NULL; - } - - Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; - ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType; - ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength; - ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0; - - HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength); - HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; - - HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; - HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER); - HobEnd->Reserved = 0; - HobEnd++; - HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; - - return Hob; -} - -/** - Builds a HOB for a loaded PE32 module. - - This function builds a HOB for a loaded PE32 module. - If ModuleName is NULL, then ASSERT(). - If there is no additional space for HOB creation, then ASSERT(). - - @param ModuleName The GUID File Name of the module. - @param MemoryAllocationModule The 64 bit physical address of the module. - @param ModuleLength The length of the module in bytes. - @param EntryPoint The 64 bit physical address of the module entry point. - -**/ -VOID -EFIAPI -BuildModuleHob ( - IN CONST EFI_GUID *ModuleName, - IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, - IN UINT64 ModuleLength, - IN EFI_PHYSICAL_ADDRESS EntryPoint - ) -{ - EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; - - ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && - ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); - - Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); - - CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); - Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; - Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; - Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; - - // - // Zero the reserved space to match HOB spec - // - ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); - - CopyGuid (&Hob->ModuleName, ModuleName); - Hob->EntryPoint = EntryPoint; -} - -/** - Builds a HOB that describes a chunk of system memory. - - This function builds a HOB that describes a chunk of system memory. - If there is no additional space for HOB creation, then ASSERT(). - - @param ResourceType The type of resource described by this HOB. - @param ResourceAttribute The resource attributes of the memory described by this HOB. - @param PhysicalStart The 64 bit physical address of memory described by this HOB. - @param NumberOfBytes The length of the memory described by this HOB in bytes. - -**/ -VOID -EFIAPI -BuildResourceDescriptorHob ( - IN EFI_RESOURCE_TYPE ResourceType, - IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, - IN EFI_PHYSICAL_ADDRESS PhysicalStart, - IN UINT64 NumberOfBytes - ) -{ - EFI_HOB_RESOURCE_DESCRIPTOR *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); - ASSERT (Hob != NULL); - - Hob->ResourceType = ResourceType; - Hob->ResourceAttribute = ResourceAttribute; - Hob->PhysicalStart = PhysicalStart; - Hob->ResourceLength = NumberOfBytes; -} - -/** - Builds a GUID HOB with a certain data length. - - This function builds a customized HOB tagged with a GUID for identification - and returns the start address of GUID HOB data so that caller can fill the customized data. - The HOB Header and Name field is already stripped. - If Guid is NULL, then ASSERT(). - If there is no additional space for HOB creation, then ASSERT(). - If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). - - @param Guid The GUID to tag the customized HOB. - @param DataLength The size of the data payload for the GUID HOB. - - @return The start address of GUID HOB data. - -**/ -VOID * -EFIAPI -BuildGuidHob ( - IN CONST EFI_GUID *Guid, - IN UINTN DataLength - ) -{ - EFI_HOB_GUID_TYPE *Hob; - - // - // Make sure that data length is not too long. - // - ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); - - Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); - CopyGuid (&Hob->Name, Guid); - return Hob + 1; -} - - -/** - Copies a data buffer to a newly-built HOB. - - This function builds a customized HOB tagged with a GUID for identification, - copies the input data to the HOB data field and returns the start address of the GUID HOB data. - The HOB Header and Name field is already stripped. - If Guid is NULL, then ASSERT(). - If Data is NULL and DataLength > 0, then ASSERT(). - If there is no additional space for HOB creation, then ASSERT(). - If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). - - @param Guid The GUID to tag the customized HOB. - @param Data The data to be copied into the data field of the GUID HOB. - @param DataLength The size of the data payload for the GUID HOB. - - @return The start address of GUID HOB data. - -**/ -VOID * -EFIAPI -BuildGuidDataHob ( - IN CONST EFI_GUID *Guid, - IN VOID *Data, - IN UINTN DataLength - ) -{ - VOID *HobData; - - ASSERT (Data != NULL || DataLength == 0); - - HobData = BuildGuidHob (Guid, DataLength); - - return CopyMem (HobData, Data, DataLength); -} - -/** - Builds a Firmware Volume HOB. - - This function builds a Firmware Volume HOB. - If there is no additional space for HOB creation, then ASSERT(). - - @param BaseAddress The base address of the Firmware Volume. - @param Length The size of the Firmware Volume in bytes. - -**/ -VOID -EFIAPI -BuildFvHob ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length - ) -{ - EFI_HOB_FIRMWARE_VOLUME *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); - - Hob->BaseAddress = BaseAddress; - Hob->Length = Length; -} - - -/** - Builds a EFI_HOB_TYPE_FV2 HOB. - - This function builds a EFI_HOB_TYPE_FV2 HOB. - If there is no additional space for HOB creation, then ASSERT(). - - @param BaseAddress The base address of the Firmware Volume. - @param Length The size of the Firmware Volume in bytes. - @param FvName The name of the Firmware Volume. - @param FileName The name of the file. - -**/ -VOID -EFIAPI -BuildFv2Hob ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN CONST EFI_GUID *FvName, - IN CONST EFI_GUID *FileName - ) -{ - EFI_HOB_FIRMWARE_VOLUME2 *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); - - Hob->BaseAddress = BaseAddress; - Hob->Length = Length; - CopyGuid (&Hob->FvName, FvName); - CopyGuid (&Hob->FileName, FileName); -} - - -/** - Builds a HOB for the CPU. - - This function builds a HOB for the CPU. - If there is no additional space for HOB creation, then ASSERT(). - - @param SizeOfMemorySpace The maximum physical memory addressability of the processor. - @param SizeOfIoSpace The maximum physical I/O addressability of the processor. - -**/ -VOID -EFIAPI -BuildCpuHob ( - IN UINT8 SizeOfMemorySpace, - IN UINT8 SizeOfIoSpace - ) -{ - EFI_HOB_CPU *Hob; - - Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); - - Hob->SizeOfMemorySpace = SizeOfMemorySpace; - Hob->SizeOfIoSpace = SizeOfIoSpace; - - // - // Zero the reserved space to match HOB spec - // - ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); -} - -/** - Builds a HOB for the memory allocation. - - This function builds a HOB for the memory allocation. - If there is no additional space for HOB creation, then ASSERT(). - - @param BaseAddress The 64 bit physical address of the memory. - @param Length The length of the memory allocation in bytes. - @param MemoryType Type of memory allocated by this HOB. - -**/ -VOID -EFIAPI -BuildMemoryAllocationHob ( - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN EFI_MEMORY_TYPE MemoryType - ) -{ - EFI_HOB_MEMORY_ALLOCATION *Hob; - - ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && - ((Length & (EFI_PAGE_SIZE - 1)) == 0)); - - Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); - - ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); - Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; - Hob->AllocDescriptor.MemoryLength = Length; - Hob->AllocDescriptor.MemoryType = MemoryType; - // - // Zero the reserved space to match HOB spec - // - ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); -} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLibInternal.c deleted file mode 100644 index 3f1e0cb749..0000000000 --- a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLibInternal.c +++ /dev/null @@ -1,58 +0,0 @@ -/** @file - HOB Library implementation for Standalone MM Core. - -Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
-Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
- -SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include - -#include -#include -#include - -#include - -// -// Cache copy of HobList pointer. -// -extern VOID *gHobList; - -EFI_HOB_HANDOFF_INFO_TABLE* -HobConstructor ( - IN VOID *EfiMemoryBegin, - IN UINTN EfiMemoryLength, - IN VOID *EfiFreeMemoryBottom, - IN VOID *EfiFreeMemoryTop - ) -{ - EFI_HOB_HANDOFF_INFO_TABLE *Hob; - EFI_HOB_GENERIC_HEADER *HobEnd; - - Hob = EfiFreeMemoryBottom; - HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1); - - Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; - Hob->Header.HobLength = sizeof (EFI_HOB_HANDOFF_INFO_TABLE); - Hob->Header.Reserved = 0; - - HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; - HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER); - HobEnd->Reserved = 0; - - Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; - Hob->BootMode = BOOT_WITH_FULL_CONFIGURATION; - - Hob->EfiMemoryTop = (UINTN)EfiMemoryBegin + EfiMemoryLength; - Hob->EfiMemoryBottom = (UINTN)EfiMemoryBegin; - Hob->EfiFreeMemoryTop = (UINTN)EfiFreeMemoryTop; - Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1); - Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; - - gHobList = Hob; - - return Hob; -} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c new file mode 100644 index 0000000000..0ec2d4ad6f --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c @@ -0,0 +1,330 @@ +/** @file + HOB Library implementation for Standalone MM Core. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +#include + +// +// Cache copy of HobList pointer. +// +VOID *gHobList = NULL; + +VOID * +CreateHob ( + IN UINT16 HobType, + IN UINT16 HobLength + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + VOID *Hob; + + HandOffHob = GetHobList (); + + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < HobLength) { + return NULL; + } + + Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength; + ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return Hob; +} + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) && + ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); + + CopyGuid (&Hob->ModuleName, ModuleName); + Hob->EntryPoint = EntryPoint; +} + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + ASSERT (Hob != NULL); + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; +} + +/** + Builds a GUID HOB with a certain data length. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + // + // Make sure that data length is not too long. + // + ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); + + Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); + CopyGuid (&Hob->Name, Guid); + return Hob + 1; +} + + +/** + Copies a data buffer to a newly-built HOB. + + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field and returns the start address of the GUID HOB data. + The HOB Header and Name field is already stripped. + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + VOID *HobData; + + ASSERT (Data != NULL || DataLength == 0); + + HobData = BuildGuidHob (Guid, DataLength); + + return CopyMem (HobData, Data, DataLength); +} + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); +} + + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_HOB_CPU *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); +} + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION *Hob; + + ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) && + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLibInternal.c new file mode 100644 index 0000000000..3f1e0cb749 --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLibInternal.c @@ -0,0 +1,58 @@ +/** @file + HOB Library implementation for Standalone MM Core. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +#include + +// +// Cache copy of HobList pointer. +// +extern VOID *gHobList; + +EFI_HOB_HANDOFF_INFO_TABLE* +HobConstructor ( + IN VOID *EfiMemoryBegin, + IN UINTN EfiMemoryLength, + IN VOID *EfiFreeMemoryBottom, + IN VOID *EfiFreeMemoryTop + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = EfiFreeMemoryBottom; + HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1); + + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof (EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BOOT_WITH_FULL_CONFIGURATION; + + Hob->EfiMemoryTop = (UINTN)EfiMemoryBegin + EfiMemoryLength; + Hob->EfiMemoryBottom = (UINTN)EfiMemoryBegin; + Hob->EfiFreeMemoryTop = (UINTN)EfiFreeMemoryTop; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + gHobList = Hob; + + return Hob; +} diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf index a2559920e8..34ed536480 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf +++ b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf @@ -22,7 +22,7 @@ LIBRARY_CLASS = HobLib|MM_CORE_STANDALONE # -# VALID_ARCHITECTURES = X64 AARCH64 +# VALID_ARCHITECTURES = X64 AARCH64 ARM # [Sources.common] Common.c @@ -30,9 +30,9 @@ [Sources.X64] X64/StandaloneMmCoreHobLib.c -[Sources.AARCH64] - AArch64/StandaloneMmCoreHobLib.c - AArch64/StandaloneMmCoreHobLibInternal.c +[Sources.AARCH64, Sources.ARM] + Arm/StandaloneMmCoreHobLib.c + Arm/StandaloneMmCoreHobLibInternal.c [Packages] MdePkg/MdePkg.dec diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c deleted file mode 100644 index 4124959e04..0000000000 --- a/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c +++ /dev/null @@ -1,70 +0,0 @@ -/** @file - Internal ARCH Specific file of MM memory check library. - - MM memory check library implementation. This library consumes MM_ACCESS_PROTOCOL - to get MMRAM information. In order to use this library instance, the platform should produce - all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core - and MM driver) and/or specific dedicated hardware. - - Copyright (c) 2015, Intel Corporation. All rights reserved.
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ -#include -#include -#include -// -// Maximum support address used to check input buffer -// -extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress; - -/** - Calculate and save the maximum support address. - -**/ -VOID -MmMemLibInternalCalculateMaximumSupportAddress ( - VOID - ) -{ - UINT8 PhysicalAddressBits; - - PhysicalAddressBits = 36; - - // - // Save the maximum support address in one global variable - // - mMmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1); - DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress)); -} - -/** - Initialize cached Mmram Ranges from HOB. - - @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information. - @retval EFI_SUCCESS MmRanges are populated successfully. - -**/ -EFI_STATUS -MmMemLibInternalPopulateMmramRanges ( - VOID - ) -{ - // Not implemented for AARCH64. - return EFI_SUCCESS; -} - -/** - Deinitialize cached Mmram Ranges. - -**/ -VOID -MmMemLibInternalFreeMmramRanges ( - VOID - ) -{ - // Not implemented for AARCH64. -} - diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c b/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c new file mode 100644 index 0000000000..fa7df46413 --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmMemLib/ArmStandaloneMmMemLibInternal.c @@ -0,0 +1,77 @@ +/** @file + Internal ARCH Specific file of MM memory check library. + + MM memory check library implementation. This library consumes MM_ACCESS_PROTOCOL + to get MMRAM information. In order to use this library instance, the platform should produce + all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core + and MM driver) and/or specific dedicated hardware. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +// +// Maximum support address used to check input buffer +// +extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress; + +#ifdef MDE_CPU_AARCH64 +#define ARM_PHYSICAL_ADDRESS_BITS 36 +#endif +#ifdef MDE_CPU_ARM +#define ARM_PHYSICAL_ADDRESS_BITS 32 +#endif + +/** + Calculate and save the maximum support address. + +**/ +VOID +MmMemLibInternalCalculateMaximumSupportAddress ( + VOID + ) +{ + UINT8 PhysicalAddressBits; + + PhysicalAddressBits = ARM_PHYSICAL_ADDRESS_BITS; + + // + // Save the maximum support address in one global variable + // + mMmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1); + DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress)); +} + +/** + Initialize cached Mmram Ranges from HOB. + + @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information. + @retval EFI_SUCCESS MmRanges are populated successfully. + +**/ +EFI_STATUS +MmMemLibInternalPopulateMmramRanges ( + VOID + ) +{ + // Not implemented for AARCH64. + return EFI_SUCCESS; +} + +/** + Deinitialize cached Mmram Ranges. + +**/ +VOID +MmMemLibInternalFreeMmramRanges ( + VOID + ) +{ + // Not implemented for AARCH64. +} + diff --git a/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf b/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf index 062b0d7a11..b29d97a746 100644 --- a/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf +++ b/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf @@ -28,7 +28,7 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# VALID_ARCHITECTURES = IA32 X64 AARCH64 ARM # [Sources.Common] @@ -37,8 +37,8 @@ [Sources.IA32, Sources.X64] X86StandaloneMmMemLibInternal.c -[Sources.AARCH64] - AArch64/StandaloneMmMemLibInternal.c +[Sources.AARCH64, Sources.ARM] + ArmStandaloneMmMemLibInternal.c [Packages] MdePkg/MdePkg.dec diff --git a/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf b/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf index a2a059c5d6..ffb2a6d083 100644 --- a/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf +++ b/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf @@ -20,7 +20,7 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = AARCH64 +# VALID_ARCHITECTURES = AARCH64|ARM # # diff --git a/StandaloneMmPkg/StandaloneMmPkg.dec b/StandaloneMmPkg/StandaloneMmPkg.dec index 0dfed4ee99..46784d94e4 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dec +++ b/StandaloneMmPkg/StandaloneMmPkg.dec @@ -29,10 +29,10 @@ ## MM Memory Operation. MemLib|Include/Library/StandaloneMmMemLib.h -[LibraryClasses.AArch64] +[LibraryClasses.AArch64, LibraryClasses.ARM] ## @libraryclass Defines a set of interfaces for the MM core entrypoint for - ## AArch64. - StandaloneMmCoreEntryPoint|Include/Library/AArch64/StandaloneMmCoreEntryPoint.h + ## AArch64 and ARM. + StandaloneMmCoreEntryPoint|Include/Library/Arm/StandaloneMmCoreEntryPoint.h [Guids] gStandaloneMmPkgTokenSpaceGuid = { 0x18fe7632, 0xf5c8, 0x4e63, { 0x8d, 0xe8, 0x17, 0xa5, 0x5c, 0x59, 0x13, 0xbd }} diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/StandaloneMmPkg.dsc index 0c45df95e2..8012f93b7d 100644 --- a/StandaloneMmPkg/StandaloneMmPkg.dsc +++ b/StandaloneMmPkg/StandaloneMmPkg.dsc @@ -20,7 +20,7 @@ PLATFORM_VERSION = 1.0 DSC_SPECIFICATION = 0x00010011 OUTPUT_DIRECTORY = Build/StandaloneMm - SUPPORTED_ARCHITECTURES = AARCH64|X64 + SUPPORTED_ARCHITECTURES = AARCH64|X64|ARM BUILD_TARGETS = DEBUG|RELEASE SKUID_IDENTIFIER = DEFAULT @@ -60,7 +60,7 @@ StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf -[LibraryClasses.AARCH64] +[LibraryClasses.AARCH64, LibraryClasses.ARM] ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf @@ -118,8 +118,8 @@ StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf -[Components.AARCH64] - StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf +[Components.AARCH64, Components.ARM] + StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf ################################################################################################### @@ -135,6 +135,10 @@ GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000 -march=armv8-a+nofp -mstrict-align GCC:*_*_*_CC_FLAGS = -mstrict-align +[BuildOptions.ARM] +GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000 -march=armv7-a +GCC:*_*_*_CC_FLAGS = -fno-stack-protector + [BuildOptions.X64] MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096 GCC:*_GCC*_*_DLINK_FLAGS = -z common-page-size=0x1000 -- cgit