]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
25ead004e610c562d584c1a651d2bba8978999bf
[mirror_edk2.git] / StandaloneMmPkg / Library / StandaloneMmCoreEntryPoint / AArch64 / StandaloneMmCoreEntryPoint.c
1 /** @file
2 Entry point to the Standalone MM Foundation when initialized during the SEC
3 phase on ARM platforms
4
5 Copyright (c) 2017 - 2021, 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 <Library/AArch64/StandaloneMmCoreEntryPoint.h>
14
15 #include <PiPei.h>
16 #include <Guid/MmramMemoryReserve.h>
17 #include <Guid/MpInformation.h>
18
19 #include <Library/ArmMmuLib.h>
20 #include <Library/ArmSvcLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/HobLib.h>
23 #include <Library/BaseLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/SerialPortLib.h>
26 #include <Library/PcdLib.h>
27
28 #include <IndustryStandard/ArmStdSmc.h>
29 #include <IndustryStandard/ArmMmSvc.h>
30 #include <IndustryStandard/ArmFfaSvc.h>
31
32 #define SPM_MAJOR_VER_MASK 0xFFFF0000
33 #define SPM_MINOR_VER_MASK 0x0000FFFF
34 #define SPM_MAJOR_VER_SHIFT 16
35 #define FFA_NOT_SUPPORTED -1
36
37 STATIC CONST UINT32 mSpmMajorVer = SPM_MAJOR_VERSION;
38 STATIC CONST UINT32 mSpmMinorVer = SPM_MINOR_VERSION;
39
40 STATIC CONST UINT32 mSpmMajorVerFfa = SPM_MAJOR_VERSION_FFA;
41 STATIC CONST UINT32 mSpmMinorVerFfa = SPM_MINOR_VERSION_FFA;
42
43 #define BOOT_PAYLOAD_VERSION 1
44
45 PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint = NULL;
46
47 /**
48 Retrieve a pointer to and print the boot information passed by privileged
49 secure firmware.
50
51 @param [in] SharedBufAddress The pointer memory shared with privileged
52 firmware.
53
54 **/
55 EFI_SECURE_PARTITION_BOOT_INFO *
56 GetAndPrintBootinformation (
57 IN VOID *SharedBufAddress
58 )
59 {
60 EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
61 EFI_SECURE_PARTITION_CPU_INFO *PayloadCpuInfo;
62 UINTN Index;
63
64 PayloadBootInfo = (EFI_SECURE_PARTITION_BOOT_INFO *) SharedBufAddress;
65
66 if (PayloadBootInfo == NULL) {
67 DEBUG ((DEBUG_ERROR, "PayloadBootInfo NULL\n"));
68 return NULL;
69 }
70
71 if (PayloadBootInfo->Header.Version != BOOT_PAYLOAD_VERSION) {
72 DEBUG ((DEBUG_ERROR, "Boot Information Version Mismatch. Current=0x%x, Expected=0x%x.\n",
73 PayloadBootInfo->Header.Version, BOOT_PAYLOAD_VERSION));
74 return NULL;
75 }
76
77 DEBUG ((DEBUG_INFO, "NumSpMemRegions - 0x%x\n", PayloadBootInfo->NumSpMemRegions));
78 DEBUG ((DEBUG_INFO, "SpMemBase - 0x%lx\n", PayloadBootInfo->SpMemBase));
79 DEBUG ((DEBUG_INFO, "SpMemLimit - 0x%lx\n", PayloadBootInfo->SpMemLimit));
80 DEBUG ((DEBUG_INFO, "SpImageBase - 0x%lx\n", PayloadBootInfo->SpImageBase));
81 DEBUG ((DEBUG_INFO, "SpStackBase - 0x%lx\n", PayloadBootInfo->SpStackBase));
82 DEBUG ((DEBUG_INFO, "SpHeapBase - 0x%lx\n", PayloadBootInfo->SpHeapBase));
83 DEBUG ((DEBUG_INFO, "SpNsCommBufBase - 0x%lx\n", PayloadBootInfo->SpNsCommBufBase));
84 DEBUG ((DEBUG_INFO, "SpSharedBufBase - 0x%lx\n", PayloadBootInfo->SpSharedBufBase));
85
86 DEBUG ((DEBUG_INFO, "SpImageSize - 0x%x\n", PayloadBootInfo->SpImageSize));
87 DEBUG ((DEBUG_INFO, "SpPcpuStackSize - 0x%x\n", PayloadBootInfo->SpPcpuStackSize));
88 DEBUG ((DEBUG_INFO, "SpHeapSize - 0x%x\n", PayloadBootInfo->SpHeapSize));
89 DEBUG ((DEBUG_INFO, "SpNsCommBufSize - 0x%x\n", PayloadBootInfo->SpNsCommBufSize));
90 DEBUG ((DEBUG_INFO, "SpPcpuSharedBufSize - 0x%x\n", PayloadBootInfo->SpPcpuSharedBufSize));
91
92 DEBUG ((DEBUG_INFO, "NumCpus - 0x%x\n", PayloadBootInfo->NumCpus));
93 DEBUG ((DEBUG_INFO, "CpuInfo - 0x%p\n", PayloadBootInfo->CpuInfo));
94
95 PayloadCpuInfo = (EFI_SECURE_PARTITION_CPU_INFO *) PayloadBootInfo->CpuInfo;
96
97 if (PayloadCpuInfo == NULL) {
98 DEBUG ((DEBUG_ERROR, "PayloadCpuInfo NULL\n"));
99 return NULL;
100 }
101
102 for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) {
103 DEBUG ((DEBUG_INFO, "Mpidr - 0x%lx\n", PayloadCpuInfo[Index].Mpidr));
104 DEBUG ((DEBUG_INFO, "LinearId - 0x%x\n", PayloadCpuInfo[Index].LinearId));
105 DEBUG ((DEBUG_INFO, "Flags - 0x%x\n", PayloadCpuInfo[Index].Flags));
106 }
107
108 return PayloadBootInfo;
109 }
110
111 /**
112 A loop to delegated events.
113
114 @param [in] EventCompleteSvcArgs Pointer to the event completion arguments.
115
116 **/
117 VOID
118 EFIAPI
119 DelegatedEventLoop (
120 IN ARM_SVC_ARGS *EventCompleteSvcArgs
121 )
122 {
123 EFI_STATUS Status;
124 UINTN SvcStatus;
125
126 while (TRUE) {
127 ArmCallSvc (EventCompleteSvcArgs);
128
129 DEBUG ((DEBUG_INFO, "Received delegated event\n"));
130 DEBUG ((DEBUG_INFO, "X0 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg0));
131 DEBUG ((DEBUG_INFO, "X1 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg1));
132 DEBUG ((DEBUG_INFO, "X2 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg2));
133 DEBUG ((DEBUG_INFO, "X3 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg3));
134
135 Status = CpuDriverEntryPoint (
136 EventCompleteSvcArgs->Arg0,
137 EventCompleteSvcArgs->Arg3,
138 EventCompleteSvcArgs->Arg1
139 );
140
141 if (EFI_ERROR (Status)) {
142 DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
143 EventCompleteSvcArgs->Arg0, Status));
144 }
145
146 switch (Status) {
147 case EFI_SUCCESS:
148 SvcStatus = ARM_SVC_SPM_RET_SUCCESS;
149 break;
150 case EFI_INVALID_PARAMETER:
151 SvcStatus = ARM_SVC_SPM_RET_INVALID_PARAMS;
152 break;
153 case EFI_ACCESS_DENIED:
154 SvcStatus = ARM_SVC_SPM_RET_DENIED;
155 break;
156 case EFI_OUT_OF_RESOURCES:
157 SvcStatus = ARM_SVC_SPM_RET_NO_MEMORY;
158 break;
159 case EFI_UNSUPPORTED:
160 SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED;
161 break;
162 default:
163 SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED;
164 break;
165 }
166
167 EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
168 EventCompleteSvcArgs->Arg1 = SvcStatus;
169 }
170 }
171
172 /**
173 Query the SPM version, check compatibility and return success if compatible.
174
175 @retval EFI_SUCCESS SPM versions compatible.
176 @retval EFI_UNSUPPORTED SPM versions not compatible.
177 **/
178 STATIC
179 EFI_STATUS
180 GetSpmVersion (VOID)
181 {
182 EFI_STATUS Status;
183 UINT16 CalleeSpmMajorVer;
184 UINT16 CallerSpmMajorVer;
185 UINT16 CalleeSpmMinorVer;
186 UINT16 CallerSpmMinorVer;
187 UINT32 SpmVersion;
188 ARM_SVC_ARGS SpmVersionArgs;
189
190 if (FeaturePcdGet (PcdFfaEnable)) {
191 SpmVersionArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32;
192 SpmVersionArgs.Arg1 = mSpmMajorVerFfa << SPM_MAJOR_VER_SHIFT;
193 SpmVersionArgs.Arg1 |= mSpmMinorVerFfa;
194 CallerSpmMajorVer = mSpmMajorVerFfa;
195 CallerSpmMinorVer = mSpmMinorVerFfa;
196 } else {
197 SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32;
198 CallerSpmMajorVer = mSpmMajorVer;
199 CallerSpmMinorVer = mSpmMinorVer;
200 }
201
202 ArmCallSvc (&SpmVersionArgs);
203
204 SpmVersion = SpmVersionArgs.Arg0;
205 if (SpmVersion == FFA_NOT_SUPPORTED) {
206 return EFI_UNSUPPORTED;
207 }
208
209 CalleeSpmMajorVer = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT);
210 CalleeSpmMinorVer = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0);
211
212 // Different major revision values indicate possibly incompatible functions.
213 // For two revisions, A and B, for which the major revision values are
214 // identical, if the minor revision value of revision B is greater than
215 // the minor revision value of revision A, then every function in
216 // revision A must work in a compatible way with revision B.
217 // However, it is possible for revision B to have a higher
218 // function count than revision A.
219 if ((CalleeSpmMajorVer == CallerSpmMajorVer) &&
220 (CalleeSpmMinorVer >= CallerSpmMinorVer))
221 {
222 DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n",
223 CalleeSpmMajorVer, CalleeSpmMinorVer));
224 Status = EFI_SUCCESS;
225 }
226 else
227 {
228 DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Callee Version: Major=0x%x, Minor=0x%x.\n Caller: Major=0x%x, Minor>=0x%x.\n",
229 CalleeSpmMajorVer, CalleeSpmMinorVer, CallerSpmMajorVer, CallerSpmMinorVer));
230 Status = EFI_UNSUPPORTED;
231 }
232
233 return Status;
234 }
235
236 /**
237 The entry point of Standalone MM Foundation.
238
239 @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP.
240 @param [in] SharedBufSize Size of the shared buffer.
241 @param [in] cookie1 Cookie 1
242 @param [in] cookie2 Cookie 2
243
244 **/
245 VOID
246 EFIAPI
247 _ModuleEntryPoint (
248 IN VOID *SharedBufAddress,
249 IN UINT64 SharedBufSize,
250 IN UINT64 cookie1,
251 IN UINT64 cookie2
252 )
253 {
254 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
255 EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
256 ARM_SVC_ARGS InitMmFoundationSvcArgs;
257 EFI_STATUS Status;
258 UINT32 SectionHeaderOffset;
259 UINT16 NumberOfSections;
260 VOID *HobStart;
261 VOID *TeData;
262 UINTN TeDataSize;
263 EFI_PHYSICAL_ADDRESS ImageBase;
264
265 // Get Secure Partition Manager Version Information
266 Status = GetSpmVersion ();
267 if (EFI_ERROR (Status)) {
268 goto finish;
269 }
270
271 PayloadBootInfo = GetAndPrintBootinformation (SharedBufAddress);
272 if (PayloadBootInfo == NULL) {
273 Status = EFI_UNSUPPORTED;
274 goto finish;
275 }
276
277 // Locate PE/COFF File information for the Standalone MM core module
278 Status = LocateStandaloneMmCorePeCoffData (
279 (EFI_FIRMWARE_VOLUME_HEADER *) PayloadBootInfo->SpImageBase,
280 &TeData,
281 &TeDataSize
282 );
283
284 if (EFI_ERROR (Status)) {
285 goto finish;
286 }
287
288 // Obtain the PE/COFF Section information for the Standalone MM core module
289 Status = GetStandaloneMmCorePeCoffSections (
290 TeData,
291 &ImageContext,
292 &ImageBase,
293 &SectionHeaderOffset,
294 &NumberOfSections
295 );
296
297 if (EFI_ERROR (Status)) {
298 goto finish;
299 }
300
301 //
302 // ImageBase may deviate from ImageContext.ImageAddress if we are dealing
303 // with a TE image, in which case the latter points to the actual offset
304 // of the image, whereas ImageBase refers to the address where the image
305 // would start if the stripped PE headers were still in place. In either
306 // case, we need to fix up ImageBase so it refers to the actual current
307 // load address.
308 //
309 ImageBase += (UINTN)TeData - ImageContext.ImageAddress;
310
311 // Update the memory access permissions of individual sections in the
312 // Standalone MM core module
313 Status = UpdateMmFoundationPeCoffPermissions (
314 &ImageContext,
315 ImageBase,
316 SectionHeaderOffset,
317 NumberOfSections,
318 ArmSetMemoryRegionNoExec,
319 ArmSetMemoryRegionReadOnly,
320 ArmClearMemoryRegionReadOnly
321 );
322
323 if (EFI_ERROR (Status)) {
324 goto finish;
325 }
326
327 if (ImageContext.ImageAddress != (UINTN)TeData) {
328 ImageContext.ImageAddress = (UINTN)TeData;
329 ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB);
330 ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB);
331
332 Status = PeCoffLoaderRelocateImage (&ImageContext);
333 ASSERT_EFI_ERROR (Status);
334 }
335
336 //
337 // Create Hoblist based upon boot information passed by privileged software
338 //
339 HobStart = CreateHobListFromBootInfo (&CpuDriverEntryPoint, PayloadBootInfo);
340
341 //
342 // Call the MM Core entry point
343 //
344 ProcessModuleEntryPointList (HobStart);
345
346 DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP 0x%lx\n", (UINT64) CpuDriverEntryPoint));
347
348 finish:
349 ZeroMem (&InitMmFoundationSvcArgs, sizeof(InitMmFoundationSvcArgs));
350 InitMmFoundationSvcArgs.Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
351 InitMmFoundationSvcArgs.Arg1 = Status;
352 DelegatedEventLoop (&InitMmFoundationSvcArgs);
353 }