--- /dev/null
+/** @file\r
+ Creates HOB during Standalone MM Foundation entry point\r
+ on ARM platforms.\r
+\r
+Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php.\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <PiMm.h>\r
+\r
+#include <PiPei.h>\r
+#include <Guid/MmramMemoryReserve.h>\r
+#include <Guid/MpInformation.h>\r
+\r
+#include <Library/AArch64/StandaloneMmCoreEntryPoint.h>\r
+#include <Library/ArmMmuLib.h>\r
+#include <Library/ArmSvcLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/SerialPortLib.h>\r
+\r
+#include <IndustryStandard/ArmStdSmc.h>\r
+\r
+extern EFI_HOB_HANDOFF_INFO_TABLE*\r
+HobConstructor (\r
+ IN VOID *EfiMemoryBegin,\r
+ IN UINTN EfiMemoryLength,\r
+ IN VOID *EfiFreeMemoryBottom,\r
+ IN VOID *EfiFreeMemoryTop\r
+ );\r
+\r
+// GUID to identify HOB with whereabouts of communication buffer with Normal\r
+// World\r
+extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid;\r
+\r
+// GUID to identify HOB where the entry point of the CPU driver will be\r
+// populated to allow this entry point driver to invoke it upon receipt of an\r
+// event\r
+extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid;\r
+\r
+/**\r
+ Use the boot information passed by privileged firmware to populate a HOB list\r
+ suitable for consumption by the MM Core and drivers.\r
+\r
+ @param PayloadBootInfo Boot information passed by privileged firmware\r
+\r
+**/\r
+VOID *\r
+CreateHobListFromBootInfo (\r
+ IN OUT PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *CpuDriverEntryPoint,\r
+ IN EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo\r
+)\r
+{\r
+ EFI_HOB_HANDOFF_INFO_TABLE *HobStart;\r
+ EFI_RESOURCE_ATTRIBUTE_TYPE Attributes;\r
+ UINT32 Index;\r
+ UINT32 BufferSize;\r
+ UINT32 Flags;\r
+ EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHob;\r
+ EFI_MMRAM_DESCRIPTOR *MmramRanges;\r
+ EFI_MMRAM_DESCRIPTOR *NsCommBufMmramRange;\r
+ MP_INFORMATION_HOB_DATA *MpInformationHobData;\r
+ EFI_PROCESSOR_INFORMATION *ProcInfoBuffer;\r
+ EFI_SECURE_PARTITION_CPU_INFO *CpuInfo;\r
+ ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc;\r
+\r
+ // Create a hoblist with a PHIT and EOH\r
+ HobStart = HobConstructor (\r
+ (VOID *) PayloadBootInfo->SpMemBase,\r
+ (UINTN) PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase,\r
+ (VOID *) PayloadBootInfo->SpHeapBase,\r
+ (VOID *) (PayloadBootInfo->SpHeapBase + PayloadBootInfo->SpHeapSize)\r
+ );\r
+\r
+ // Check that the Hoblist starts at the bottom of the Heap\r
+ ASSERT (HobStart == (VOID *) PayloadBootInfo->SpHeapBase);\r
+\r
+ // Build a Boot Firmware Volume HOB\r
+ BuildFvHob (PayloadBootInfo->SpImageBase, PayloadBootInfo->SpImageSize);\r
+\r
+ // Build a resource descriptor Hob that describes the available physical\r
+ // memory range\r
+ Attributes = (\r
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+ EFI_RESOURCE_ATTRIBUTE_TESTED |\r
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+ );\r
+\r
+ BuildResourceDescriptorHob (\r
+ EFI_RESOURCE_SYSTEM_MEMORY,\r
+ Attributes,\r
+ (UINTN) PayloadBootInfo->SpMemBase,\r
+ PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase\r
+ );\r
+\r
+ // Find the size of the GUIDed HOB with MP information\r
+ BufferSize = sizeof (MP_INFORMATION_HOB_DATA);\r
+ BufferSize += sizeof (EFI_PROCESSOR_INFORMATION) * PayloadBootInfo->NumCpus;\r
+\r
+ // Create a Guided MP information HOB to enable the ARM TF CPU driver to\r
+ // perform per-cpu allocations.\r
+ MpInformationHobData = BuildGuidHob (&gMpInformationHobGuid, BufferSize);\r
+\r
+ // Populate the MP information HOB with the topology information passed by\r
+ // privileged firmware\r
+ MpInformationHobData->NumberOfProcessors = PayloadBootInfo->NumCpus;\r
+ MpInformationHobData->NumberOfEnabledProcessors = PayloadBootInfo->NumCpus;\r
+ ProcInfoBuffer = MpInformationHobData->ProcessorInfoBuffer;\r
+ CpuInfo = PayloadBootInfo->CpuInfo;\r
+\r
+ for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) {\r
+ ProcInfoBuffer[Index].ProcessorId = CpuInfo[Index].Mpidr;\r
+ ProcInfoBuffer[Index].Location.Package = GET_CLUSTER_ID(CpuInfo[Index].Mpidr);\r
+ ProcInfoBuffer[Index].Location.Core = GET_CORE_ID(CpuInfo[Index].Mpidr);\r
+ ProcInfoBuffer[Index].Location.Thread = GET_CORE_ID(CpuInfo[Index].Mpidr);\r
+\r
+ Flags = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;\r
+ if (CpuInfo[Index].Flags & CPU_INFO_FLAG_PRIMARY_CPU) {\r
+ Flags |= PROCESSOR_AS_BSP_BIT;\r
+ }\r
+ ProcInfoBuffer[Index].StatusFlag = Flags;\r
+ }\r
+\r
+ // Create a Guided HOB to tell the ARM TF CPU driver the location and length\r
+ // of the communication buffer shared with the Normal world.\r
+ NsCommBufMmramRange = (EFI_MMRAM_DESCRIPTOR *) BuildGuidHob (\r
+ &gEfiStandaloneMmNonSecureBufferGuid,\r
+ sizeof (EFI_MMRAM_DESCRIPTOR)\r
+ );\r
+ NsCommBufMmramRange->PhysicalStart = PayloadBootInfo->SpNsCommBufBase;\r
+ NsCommBufMmramRange->CpuStart = PayloadBootInfo->SpNsCommBufBase;\r
+ NsCommBufMmramRange->PhysicalSize = PayloadBootInfo->SpNsCommBufSize;\r
+ NsCommBufMmramRange->RegionState = EFI_CACHEABLE | EFI_ALLOCATED;\r
+\r
+ // Create a Guided HOB to enable the ARM TF CPU driver to share its entry\r
+ // point and populate it with the address of the shared buffer\r
+ CpuDriverEntryPointDesc = (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *) BuildGuidHob (\r
+ &gEfiArmTfCpuDriverEpDescriptorGuid,\r
+ sizeof (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR)\r
+ );\r
+\r
+ *CpuDriverEntryPoint = NULL;\r
+ CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr = CpuDriverEntryPoint;\r
+\r
+ // Find the size of the GUIDed HOB with SRAM ranges\r
+ BufferSize = sizeof (EFI_MMRAM_HOB_DESCRIPTOR_BLOCK);\r
+ BufferSize += PayloadBootInfo->NumSpMemRegions * sizeof (EFI_MMRAM_DESCRIPTOR);\r
+\r
+ // Create a GUIDed HOB with SRAM ranges\r
+ MmramRangesHob = BuildGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, BufferSize);\r
+\r
+ // Fill up the number of MMRAM memory regions\r
+ MmramRangesHob->NumberOfMmReservedRegions = PayloadBootInfo->NumSpMemRegions;\r
+ // Fill up the MMRAM ranges\r
+ MmramRanges = &MmramRangesHob->Descriptor[0];\r
+\r
+ // Base and size of memory occupied by the Standalone MM image\r
+ MmramRanges[0].PhysicalStart = PayloadBootInfo->SpImageBase;\r
+ MmramRanges[0].CpuStart = PayloadBootInfo->SpImageBase;\r
+ MmramRanges[0].PhysicalSize = PayloadBootInfo->SpImageSize;\r
+ MmramRanges[0].RegionState = EFI_CACHEABLE | EFI_ALLOCATED;\r
+\r
+ // Base and size of buffer shared with privileged Secure world software\r
+ MmramRanges[1].PhysicalStart = PayloadBootInfo->SpSharedBufBase;\r
+ MmramRanges[1].CpuStart = PayloadBootInfo->SpSharedBufBase;\r
+ MmramRanges[1].PhysicalSize = PayloadBootInfo->SpPcpuSharedBufSize * PayloadBootInfo->NumCpus;\r
+ MmramRanges[1].RegionState = EFI_CACHEABLE | EFI_ALLOCATED;\r
+\r
+ // Base and size of buffer used for synchronous communication with Normal\r
+ // world software\r
+ MmramRanges[2].PhysicalStart = PayloadBootInfo->SpNsCommBufBase;\r
+ MmramRanges[2].CpuStart = PayloadBootInfo->SpNsCommBufBase;\r
+ MmramRanges[2].PhysicalSize = PayloadBootInfo->SpNsCommBufSize;\r
+ MmramRanges[2].RegionState = EFI_CACHEABLE | EFI_ALLOCATED;\r
+\r
+ // Base and size of memory allocated for stacks for all cpus\r
+ MmramRanges[3].PhysicalStart = PayloadBootInfo->SpStackBase;\r
+ MmramRanges[3].CpuStart = PayloadBootInfo->SpStackBase;\r
+ MmramRanges[3].PhysicalSize = PayloadBootInfo->SpPcpuStackSize * PayloadBootInfo->NumCpus;\r
+ MmramRanges[3].RegionState = EFI_CACHEABLE | EFI_ALLOCATED;\r
+\r
+ // Base and size of heap memory shared by all cpus\r
+ MmramRanges[4].PhysicalStart = (EFI_PHYSICAL_ADDRESS) HobStart;\r
+ MmramRanges[4].CpuStart = (EFI_PHYSICAL_ADDRESS) HobStart;\r
+ MmramRanges[4].PhysicalSize = HobStart->EfiFreeMemoryBottom - (EFI_PHYSICAL_ADDRESS) HobStart;\r
+ MmramRanges[4].RegionState = EFI_CACHEABLE | EFI_ALLOCATED;\r
+\r
+ // Base and size of heap memory shared by all cpus\r
+ MmramRanges[5].PhysicalStart = HobStart->EfiFreeMemoryBottom;\r
+ MmramRanges[5].CpuStart = HobStart->EfiFreeMemoryBottom;\r
+ MmramRanges[5].PhysicalSize = HobStart->EfiFreeMemoryTop - HobStart->EfiFreeMemoryBottom;\r
+ MmramRanges[5].RegionState = EFI_CACHEABLE;\r
+\r
+ return HobStart;\r
+}\r