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