/** @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
#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 gEfiMmCpuDriverEpDescriptorGuid;
/**
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_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;
MM_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 = (MM_CPU_DRIVER_EP_DESCRIPTOR *)BuildGuidHob (
&gEfiMmCpuDriverEpDescriptorGuid,
sizeof (MM_CPU_DRIVER_EP_DESCRIPTOR)
);
*CpuDriverEntryPoint = NULL;
CpuDriverEntryPointDesc->MmCpuDriverEpPtr = 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->SpSharedBufSize;
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;
}