1 /** @file
2   Creates HOB during Standalone MM Foundation entry point
3   on ARM platforms.
4 
5 Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 
11 #include <PiMm.h>
12 
13 #include <PiPei.h>
14 #include <Guid/MmramMemoryReserve.h>
15 #include <Guid/MpInformation.h>
16 
17 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>
18 #include <Library/ArmMmuLib.h>
19 #include <Library/ArmSvcLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/HobLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/SerialPortLib.h>
25 
26 #include <IndustryStandard/ArmStdSmc.h>
27 
28 extern EFI_HOB_HANDOFF_INFO_TABLE*
29 HobConstructor (
30   IN VOID   *EfiMemoryBegin,
31   IN UINTN  EfiMemoryLength,
32   IN VOID   *EfiFreeMemoryBottom,
33   IN VOID   *EfiFreeMemoryTop
34   );
35 
36 // GUID to identify HOB with whereabouts of communication buffer with Normal
37 // World
38 extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid;
39 
40 // GUID to identify HOB where the entry point of the CPU driver will be
41 // populated to allow this entry point driver to invoke it upon receipt of an
42 // event
43 extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid;
44 
45 /**
46   Use the boot information passed by privileged firmware to populate a HOB list
47   suitable for consumption by the MM Core and drivers.
48 
49   @param  PayloadBootInfo    Boot information passed by privileged firmware
50 
51 **/
52 VOID *
CreateHobListFromBootInfo(IN OUT PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT * CpuDriverEntryPoint,IN EFI_SECURE_PARTITION_BOOT_INFO * PayloadBootInfo)53 CreateHobListFromBootInfo (
54   IN  OUT  PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT *CpuDriverEntryPoint,
55   IN       EFI_SECURE_PARTITION_BOOT_INFO     *PayloadBootInfo
56 )
57 {
58   EFI_HOB_HANDOFF_INFO_TABLE      *HobStart;
59   EFI_RESOURCE_ATTRIBUTE_TYPE     Attributes;
60   UINT32                          Index;
61   UINT32                          BufferSize;
62   UINT32                          Flags;
63   EFI_MMRAM_HOB_DESCRIPTOR_BLOCK  *MmramRangesHob;
64   EFI_MMRAM_DESCRIPTOR            *MmramRanges;
65   EFI_MMRAM_DESCRIPTOR            *NsCommBufMmramRange;
66   MP_INFORMATION_HOB_DATA         *MpInformationHobData;
67   EFI_PROCESSOR_INFORMATION       *ProcInfoBuffer;
68   EFI_SECURE_PARTITION_CPU_INFO   *CpuInfo;
69   ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc;
70 
71   // Create a hoblist with a PHIT and EOH
72   HobStart = HobConstructor (
73                (VOID *) PayloadBootInfo->SpMemBase,
74                (UINTN)  PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase,
75                (VOID *) PayloadBootInfo->SpHeapBase,
76                (VOID *) (PayloadBootInfo->SpHeapBase + PayloadBootInfo->SpHeapSize)
77                );
78 
79   // Check that the Hoblist starts at the bottom of the Heap
80   ASSERT (HobStart == (VOID *) PayloadBootInfo->SpHeapBase);
81 
82   // Build a Boot Firmware Volume HOB
83   BuildFvHob (PayloadBootInfo->SpImageBase, PayloadBootInfo->SpImageSize);
84 
85   // Build a resource descriptor Hob that describes the available physical
86   // memory range
87   Attributes = (
88     EFI_RESOURCE_ATTRIBUTE_PRESENT |
89     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
90     EFI_RESOURCE_ATTRIBUTE_TESTED |
91     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
92     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
93     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
94     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
95   );
96 
97   BuildResourceDescriptorHob (
98     EFI_RESOURCE_SYSTEM_MEMORY,
99     Attributes,
100     (UINTN) PayloadBootInfo->SpMemBase,
101     PayloadBootInfo->SpMemLimit - PayloadBootInfo->SpMemBase
102     );
103 
104   // Find the size of the GUIDed HOB with MP information
105   BufferSize = sizeof (MP_INFORMATION_HOB_DATA);
106   BufferSize += sizeof (EFI_PROCESSOR_INFORMATION) * PayloadBootInfo->NumCpus;
107 
108   // Create a Guided MP information HOB to enable the ARM TF CPU driver to
109   // perform per-cpu allocations.
110   MpInformationHobData = BuildGuidHob (&gMpInformationHobGuid, BufferSize);
111 
112   // Populate the MP information HOB with the topology information passed by
113   // privileged firmware
114   MpInformationHobData->NumberOfProcessors = PayloadBootInfo->NumCpus;
115   MpInformationHobData->NumberOfEnabledProcessors = PayloadBootInfo->NumCpus;
116   ProcInfoBuffer = MpInformationHobData->ProcessorInfoBuffer;
117   CpuInfo = PayloadBootInfo->CpuInfo;
118 
119   for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) {
120     ProcInfoBuffer[Index].ProcessorId      = CpuInfo[Index].Mpidr;
121     ProcInfoBuffer[Index].Location.Package = GET_CLUSTER_ID(CpuInfo[Index].Mpidr);
122     ProcInfoBuffer[Index].Location.Core    = GET_CORE_ID(CpuInfo[Index].Mpidr);
123     ProcInfoBuffer[Index].Location.Thread  = GET_CORE_ID(CpuInfo[Index].Mpidr);
124 
125     Flags = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
126     if (CpuInfo[Index].Flags & CPU_INFO_FLAG_PRIMARY_CPU) {
127       Flags |= PROCESSOR_AS_BSP_BIT;
128     }
129     ProcInfoBuffer[Index].StatusFlag = Flags;
130   }
131 
132   // Create a Guided HOB to tell the ARM TF CPU driver the location and length
133   // of the communication buffer shared with the Normal world.
134   NsCommBufMmramRange = (EFI_MMRAM_DESCRIPTOR *) BuildGuidHob (
135                                                    &gEfiStandaloneMmNonSecureBufferGuid,
136                                                    sizeof (EFI_MMRAM_DESCRIPTOR)
137                                                    );
138   NsCommBufMmramRange->PhysicalStart = PayloadBootInfo->SpNsCommBufBase;
139   NsCommBufMmramRange->CpuStart      = PayloadBootInfo->SpNsCommBufBase;
140   NsCommBufMmramRange->PhysicalSize  = PayloadBootInfo->SpNsCommBufSize;
141   NsCommBufMmramRange->RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;
142 
143   // Create a Guided HOB to enable the ARM TF CPU driver to share its entry
144   // point and populate it with the address of the shared buffer
145   CpuDriverEntryPointDesc = (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *) BuildGuidHob (
146                                                                   &gEfiArmTfCpuDriverEpDescriptorGuid,
147                                                                   sizeof (ARM_TF_CPU_DRIVER_EP_DESCRIPTOR)
148                                                                   );
149 
150   *CpuDriverEntryPoint = NULL;
151   CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr = CpuDriverEntryPoint;
152 
153   // Find the size of the GUIDed HOB with SRAM ranges
154   BufferSize = sizeof (EFI_MMRAM_HOB_DESCRIPTOR_BLOCK);
155   BufferSize += PayloadBootInfo->NumSpMemRegions * sizeof (EFI_MMRAM_DESCRIPTOR);
156 
157   // Create a GUIDed HOB with SRAM ranges
158   MmramRangesHob = BuildGuidHob (&gEfiMmPeiMmramMemoryReserveGuid, BufferSize);
159 
160   // Fill up the number of MMRAM memory regions
161   MmramRangesHob->NumberOfMmReservedRegions = PayloadBootInfo->NumSpMemRegions;
162   // Fill up the MMRAM ranges
163   MmramRanges = &MmramRangesHob->Descriptor[0];
164 
165   // Base and size of memory occupied by the Standalone MM image
166   MmramRanges[0].PhysicalStart = PayloadBootInfo->SpImageBase;
167   MmramRanges[0].CpuStart      = PayloadBootInfo->SpImageBase;
168   MmramRanges[0].PhysicalSize  = PayloadBootInfo->SpImageSize;
169   MmramRanges[0].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;
170 
171   // Base and size of buffer shared with privileged Secure world software
172   MmramRanges[1].PhysicalStart = PayloadBootInfo->SpSharedBufBase;
173   MmramRanges[1].CpuStart      = PayloadBootInfo->SpSharedBufBase;
174   MmramRanges[1].PhysicalSize  = PayloadBootInfo->SpPcpuSharedBufSize * PayloadBootInfo->NumCpus;
175   MmramRanges[1].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;
176 
177   // Base and size of buffer used for synchronous communication with Normal
178   // world software
179   MmramRanges[2].PhysicalStart = PayloadBootInfo->SpNsCommBufBase;
180   MmramRanges[2].CpuStart      = PayloadBootInfo->SpNsCommBufBase;
181   MmramRanges[2].PhysicalSize  = PayloadBootInfo->SpNsCommBufSize;
182   MmramRanges[2].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;
183 
184   // Base and size of memory allocated for stacks for all cpus
185   MmramRanges[3].PhysicalStart = PayloadBootInfo->SpStackBase;
186   MmramRanges[3].CpuStart      = PayloadBootInfo->SpStackBase;
187   MmramRanges[3].PhysicalSize  = PayloadBootInfo->SpPcpuStackSize * PayloadBootInfo->NumCpus;
188   MmramRanges[3].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;
189 
190   // Base and size of heap memory shared by all cpus
191   MmramRanges[4].PhysicalStart = (EFI_PHYSICAL_ADDRESS) HobStart;
192   MmramRanges[4].CpuStart      = (EFI_PHYSICAL_ADDRESS) HobStart;
193   MmramRanges[4].PhysicalSize  = HobStart->EfiFreeMemoryBottom - (EFI_PHYSICAL_ADDRESS) HobStart;
194   MmramRanges[4].RegionState   = EFI_CACHEABLE | EFI_ALLOCATED;
195 
196   // Base and size of heap memory shared by all cpus
197   MmramRanges[5].PhysicalStart = HobStart->EfiFreeMemoryBottom;
198   MmramRanges[5].CpuStart      = HobStart->EfiFreeMemoryBottom;
199   MmramRanges[5].PhysicalSize  = HobStart->EfiFreeMemoryTop - HobStart->EfiFreeMemoryBottom;
200   MmramRanges[5].RegionState   = EFI_CACHEABLE;
201 
202   return HobStart;
203 }
204