1 /** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2016 HP Development Company, L.P.
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include <Base.h>
12 #include <Pi/PiMmCis.h>
13 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>
14 #include <Library/DebugLib.h>
15 #include <Library/ArmSvcLib.h>
16 #include <Library/ArmLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/HobLib.h>
19
20 #include <Protocol/DebugSupport.h> // for EFI_SYSTEM_CONTEXT
21
22 #include <Guid/ZeroGuid.h>
23 #include <Guid/MmramMemoryReserve.h>
24
25
26 #include "StandaloneMmCpu.h"
27
28 // GUID to identify HOB with whereabouts of communication buffer with Normal
29 // World
30 extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid;
31
32 // GUID to identify HOB where the entry point of this CPU driver will be
33 // populated to allow the entry point driver to invoke it upon receipt of an
34 // event
35 extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid;
36
37 //
38 // Private copy of the MM system table for future use
39 //
40 EFI_MM_SYSTEM_TABLE *mMmst = NULL;
41
42 //
43 // Globals used to initialize the protocol
44 //
45 STATIC EFI_HANDLE mMmCpuHandle = NULL;
46
47 EFI_STATUS
GetGuidedHobData(IN VOID * HobList,IN CONST EFI_GUID * HobGuid,OUT VOID ** HobData)48 GetGuidedHobData (
49 IN VOID *HobList,
50 IN CONST EFI_GUID *HobGuid,
51 OUT VOID **HobData
52 )
53 {
54 EFI_HOB_GUID_TYPE *Hob;
55
56 if (!HobList || !HobGuid || !HobData)
57 return EFI_INVALID_PARAMETER;
58
59 Hob = GetNextGuidHob (HobGuid, HobList);
60 if (!Hob)
61 return EFI_NOT_FOUND;
62
63 *HobData = GET_GUID_HOB_DATA (Hob);
64 if (!HobData)
65 return EFI_NOT_FOUND;
66
67 return EFI_SUCCESS;
68 }
69
70 EFI_STATUS
StandaloneMmCpuInitialize(IN EFI_HANDLE ImageHandle,IN EFI_MM_SYSTEM_TABLE * SystemTable)71 StandaloneMmCpuInitialize (
72 IN EFI_HANDLE ImageHandle, // not actual imagehandle
73 IN EFI_MM_SYSTEM_TABLE *SystemTable // not actual systemtable
74 )
75 {
76 ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc;
77 EFI_CONFIGURATION_TABLE *ConfigurationTable;
78 MP_INFORMATION_HOB_DATA *MpInformationHobData;
79 EFI_MMRAM_DESCRIPTOR *NsCommBufMmramRange;
80 EFI_STATUS Status;
81 EFI_HANDLE DispatchHandle;
82 UINT32 MpInfoSize;
83 UINTN Index;
84 UINTN ArraySize;
85 VOID *HobStart;
86
87 ASSERT (SystemTable != NULL);
88 mMmst = SystemTable;
89
90 // publish the MM config protocol so the MM core can register its entry point
91 Status = mMmst->MmInstallProtocolInterface (
92 &mMmCpuHandle,
93 &gEfiMmConfigurationProtocolGuid,
94 EFI_NATIVE_INTERFACE,
95 &mMmConfig
96 );
97 if (EFI_ERROR (Status)) {
98 return Status;
99 }
100
101 // register the root MMI handler
102 Status = mMmst->MmiHandlerRegister (
103 PiMmCpuTpFwRootMmiHandler,
104 NULL,
105 &DispatchHandle
106 );
107 if (EFI_ERROR (Status)) {
108 return Status;
109 }
110
111 // Retrieve the Hoblist from the MMST to extract the details of the NS
112 // communication buffer that has been reserved by S-EL1/EL3
113 ConfigurationTable = mMmst->MmConfigurationTable;
114 for (Index = 0; Index < mMmst->NumberOfTableEntries; Index++) {
115 if (CompareGuid (&gEfiHobListGuid, &(ConfigurationTable[Index].VendorGuid))) {
116 break;
117 }
118 }
119
120 // Bail out if the Hoblist could not be found
121 if (Index >= mMmst->NumberOfTableEntries) {
122 DEBUG ((DEBUG_INFO, "Hoblist not found - 0x%x\n", Index));
123 return EFI_OUT_OF_RESOURCES;
124 }
125
126 HobStart = ConfigurationTable[Index].VendorTable;
127
128 //
129 // Locate the HOB with the buffer to populate the entry point of this driver
130 //
131 Status = GetGuidedHobData (
132 HobStart,
133 &gEfiArmTfCpuDriverEpDescriptorGuid,
134 (VOID **) &CpuDriverEntryPointDesc
135 );
136 if (EFI_ERROR (Status)) {
137 DEBUG ((DEBUG_INFO, "ArmTfCpuDriverEpDesc HOB data extraction failed - 0x%x\n", Status));
138 return Status;
139 }
140
141 // Share the entry point of the CPU driver
142 DEBUG ((DEBUG_INFO, "Sharing Cpu Driver EP *0x%lx = 0x%lx\n",
143 (UINT64) CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr,
144 (UINT64) PiMmStandaloneArmTfCpuDriverEntry));
145 *(CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr) = PiMmStandaloneArmTfCpuDriverEntry;
146
147 // Find the descriptor that contains the whereabouts of the buffer for
148 // communication with the Normal world.
149 Status = GetGuidedHobData (
150 HobStart,
151 &gEfiStandaloneMmNonSecureBufferGuid,
152 (VOID **) &NsCommBufMmramRange
153 );
154 if (EFI_ERROR (Status)) {
155 DEBUG ((DEBUG_INFO, "NsCommBufMmramRange HOB data extraction failed - 0x%x\n", Status));
156 return Status;
157 }
158
159 DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalStart - 0x%lx\n", (UINT64) NsCommBufMmramRange->PhysicalStart));
160 DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalSize - 0x%lx\n", (UINT64) NsCommBufMmramRange->PhysicalSize));
161
162 CopyMem (&mNsCommBuffer, NsCommBufMmramRange, sizeof(EFI_MMRAM_DESCRIPTOR));
163 DEBUG ((DEBUG_INFO, "mNsCommBuffer: 0x%016lx - 0x%lx\n", mNsCommBuffer.CpuStart, mNsCommBuffer.PhysicalSize));
164
165 //
166 // Extract the MP information from the Hoblist
167 //
168 Status = GetGuidedHobData (
169 HobStart,
170 &gMpInformationHobGuid,
171 (VOID **) &MpInformationHobData
172 );
173 if (EFI_ERROR (Status)) {
174 DEBUG ((DEBUG_INFO, "MpInformationHob extraction failed - 0x%x\n", Status));
175 return Status;
176 }
177
178 //
179 // Allocate memory for the MP information and copy over the MP information
180 // passed by Trusted Firmware. Use the number of processors passed in the HOB
181 // to copy the processor information
182 //
183 MpInfoSize = sizeof (MP_INFORMATION_HOB_DATA) +
184 (sizeof (EFI_PROCESSOR_INFORMATION) *
185 MpInformationHobData->NumberOfProcessors);
186 Status = mMmst->MmAllocatePool (
187 EfiRuntimeServicesData,
188 MpInfoSize,
189 (VOID **) &mMpInformationHobData
190 );
191 if (EFI_ERROR (Status)) {
192 DEBUG ((DEBUG_INFO, "mMpInformationHobData mem alloc failed - 0x%x\n", Status));
193 return Status;
194 }
195
196 CopyMem (mMpInformationHobData, MpInformationHobData, MpInfoSize);
197
198 // Print MP information
199 DEBUG ((DEBUG_INFO, "mMpInformationHobData: 0x%016lx - 0x%lx\n",
200 mMpInformationHobData->NumberOfProcessors,
201 mMpInformationHobData->NumberOfEnabledProcessors));
202 for (Index = 0; Index < mMpInformationHobData->NumberOfProcessors; Index++) {
203 DEBUG ((DEBUG_INFO, "mMpInformationHobData[0x%lx]: %d, %d, %d\n",
204 mMpInformationHobData->ProcessorInfoBuffer[Index].ProcessorId,
205 mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Package,
206 mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Core,
207 mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Thread));
208 }
209
210 //
211 // Allocate memory for a table to hold pointers to a
212 // EFI_MM_COMMUNICATE_HEADER for each CPU
213 //
214 ArraySize = sizeof (EFI_MM_COMMUNICATE_HEADER *) *
215 mMpInformationHobData->NumberOfEnabledProcessors;
216 Status = mMmst->MmAllocatePool (
217 EfiRuntimeServicesData,
218 ArraySize,
219 (VOID **) &PerCpuGuidedEventContext
220 );
221 if (EFI_ERROR (Status)) {
222 DEBUG ((DEBUG_INFO, "PerCpuGuidedEventContext mem alloc failed - 0x%x\n", Status));
223 return Status;
224 }
225 return Status;
226 }
227