]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
6c50f470aa3589367e4f07da9fb441ca9b2c0e25
[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 BOOLEAN FfaEnabled;
124 EFI_STATUS Status;
125 UINTN SvcStatus;
126
127 while (TRUE) {
128 ArmCallSvc (EventCompleteSvcArgs);
129
130 DEBUG ((DEBUG_INFO, "Received delegated event\n"));
131 DEBUG ((DEBUG_INFO, "X0 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg0));
132 DEBUG ((DEBUG_INFO, "X1 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg1));
133 DEBUG ((DEBUG_INFO, "X2 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg2));
134 DEBUG ((DEBUG_INFO, "X3 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg3));
135 DEBUG ((DEBUG_INFO, "X4 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg4));
136 DEBUG ((DEBUG_INFO, "X5 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg5));
137 DEBUG ((DEBUG_INFO, "X6 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg6));
138 DEBUG ((DEBUG_INFO, "X7 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg7));
139
140 FfaEnabled = FeaturePcdGet (PcdFfaEnable);
141 if (FfaEnabled) {
142 Status = CpuDriverEntryPoint (
143 EventCompleteSvcArgs->Arg0,
144 EventCompleteSvcArgs->Arg6,
145 EventCompleteSvcArgs->Arg3
146 );
147 if (EFI_ERROR (Status)) {
148 DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
149 EventCompleteSvcArgs->Arg3, Status));
150 }
151 } else {
152 Status = CpuDriverEntryPoint (
153 EventCompleteSvcArgs->Arg0,
154 EventCompleteSvcArgs->Arg3,
155 EventCompleteSvcArgs->Arg1
156 );
157 if (EFI_ERROR (Status)) {
158 DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
159 EventCompleteSvcArgs->Arg0, Status));
160 }
161 }
162
163 switch (Status) {
164 case EFI_SUCCESS:
165 SvcStatus = ARM_SVC_SPM_RET_SUCCESS;
166 break;
167 case EFI_INVALID_PARAMETER:
168 SvcStatus = ARM_SVC_SPM_RET_INVALID_PARAMS;
169 break;
170 case EFI_ACCESS_DENIED:
171 SvcStatus = ARM_SVC_SPM_RET_DENIED;
172 break;
173 case EFI_OUT_OF_RESOURCES:
174 SvcStatus = ARM_SVC_SPM_RET_NO_MEMORY;
175 break;
176 case EFI_UNSUPPORTED:
177 SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED;
178 break;
179 default:
180 SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED;
181 break;
182 }
183
184 if (FfaEnabled) {
185 EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64;
186 EventCompleteSvcArgs->Arg1 = 0;
187 EventCompleteSvcArgs->Arg2 = 0;
188 EventCompleteSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
189 EventCompleteSvcArgs->Arg4 = SvcStatus;
190 } else {
191 EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
192 EventCompleteSvcArgs->Arg1 = SvcStatus;
193 }
194 }
195 }
196
197 /**
198 Query the SPM version, check compatibility and return success if compatible.
199
200 @retval EFI_SUCCESS SPM versions compatible.
201 @retval EFI_UNSUPPORTED SPM versions not compatible.
202 **/
203 STATIC
204 EFI_STATUS
205 GetSpmVersion (VOID)
206 {
207 EFI_STATUS Status;
208 UINT16 CalleeSpmMajorVer;
209 UINT16 CallerSpmMajorVer;
210 UINT16 CalleeSpmMinorVer;
211 UINT16 CallerSpmMinorVer;
212 UINT32 SpmVersion;
213 ARM_SVC_ARGS SpmVersionArgs;
214
215 if (FeaturePcdGet (PcdFfaEnable)) {
216 SpmVersionArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32;
217 SpmVersionArgs.Arg1 = mSpmMajorVerFfa << SPM_MAJOR_VER_SHIFT;
218 SpmVersionArgs.Arg1 |= mSpmMinorVerFfa;
219 CallerSpmMajorVer = mSpmMajorVerFfa;
220 CallerSpmMinorVer = mSpmMinorVerFfa;
221 } else {
222 SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32;
223 CallerSpmMajorVer = mSpmMajorVer;
224 CallerSpmMinorVer = mSpmMinorVer;
225 }
226
227 ArmCallSvc (&SpmVersionArgs);
228
229 SpmVersion = SpmVersionArgs.Arg0;
230 if (SpmVersion == FFA_NOT_SUPPORTED) {
231 return EFI_UNSUPPORTED;
232 }
233
234 CalleeSpmMajorVer = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT);
235 CalleeSpmMinorVer = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0);
236
237 // Different major revision values indicate possibly incompatible functions.
238 // For two revisions, A and B, for which the major revision values are
239 // identical, if the minor revision value of revision B is greater than
240 // the minor revision value of revision A, then every function in
241 // revision A must work in a compatible way with revision B.
242 // However, it is possible for revision B to have a higher
243 // function count than revision A.
244 if ((CalleeSpmMajorVer == CallerSpmMajorVer) &&
245 (CalleeSpmMinorVer >= CallerSpmMinorVer))
246 {
247 DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n",
248 CalleeSpmMajorVer, CalleeSpmMinorVer));
249 Status = EFI_SUCCESS;
250 }
251 else
252 {
253 DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Callee Version: Major=0x%x, Minor=0x%x.\n Caller: Major=0x%x, Minor>=0x%x.\n",
254 CalleeSpmMajorVer, CalleeSpmMinorVer, CallerSpmMajorVer, CallerSpmMinorVer));
255 Status = EFI_UNSUPPORTED;
256 }
257
258 return Status;
259 }
260
261 /**
262 Initialize parameters to be sent via SVC call.
263
264 @param[out] InitMmFoundationSvcArgs Args structure
265 @param[out] Ret Return Code
266
267 **/
268 STATIC
269 VOID
270 InitArmSvcArgs (
271 OUT ARM_SVC_ARGS *InitMmFoundationSvcArgs,
272 OUT INT32 *Ret
273 )
274 {
275 if (FeaturePcdGet (PcdFfaEnable)) {
276 InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64;
277 InitMmFoundationSvcArgs->Arg1 = 0;
278 InitMmFoundationSvcArgs->Arg2 = 0;
279 InitMmFoundationSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
280 InitMmFoundationSvcArgs->Arg4 = *Ret;
281 } else {
282 InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
283 InitMmFoundationSvcArgs->Arg1 = *Ret;
284 }
285 }
286
287 /**
288 The entry point of Standalone MM Foundation.
289
290 @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP.
291 @param [in] SharedBufSize Size of the shared buffer.
292 @param [in] cookie1 Cookie 1
293 @param [in] cookie2 Cookie 2
294
295 **/
296 VOID
297 EFIAPI
298 _ModuleEntryPoint (
299 IN VOID *SharedBufAddress,
300 IN UINT64 SharedBufSize,
301 IN UINT64 cookie1,
302 IN UINT64 cookie2
303 )
304 {
305 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
306 EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
307 ARM_SVC_ARGS InitMmFoundationSvcArgs;
308 EFI_STATUS Status;
309 INT32 Ret;
310 UINT32 SectionHeaderOffset;
311 UINT16 NumberOfSections;
312 VOID *HobStart;
313 VOID *TeData;
314 UINTN TeDataSize;
315 EFI_PHYSICAL_ADDRESS ImageBase;
316
317 // Get Secure Partition Manager Version Information
318 Status = GetSpmVersion ();
319 if (EFI_ERROR (Status)) {
320 goto finish;
321 }
322
323 PayloadBootInfo = GetAndPrintBootinformation (SharedBufAddress);
324 if (PayloadBootInfo == NULL) {
325 Status = EFI_UNSUPPORTED;
326 goto finish;
327 }
328
329 // Locate PE/COFF File information for the Standalone MM core module
330 Status = LocateStandaloneMmCorePeCoffData (
331 (EFI_FIRMWARE_VOLUME_HEADER *) PayloadBootInfo->SpImageBase,
332 &TeData,
333 &TeDataSize
334 );
335
336 if (EFI_ERROR (Status)) {
337 goto finish;
338 }
339
340 // Obtain the PE/COFF Section information for the Standalone MM core module
341 Status = GetStandaloneMmCorePeCoffSections (
342 TeData,
343 &ImageContext,
344 &ImageBase,
345 &SectionHeaderOffset,
346 &NumberOfSections
347 );
348
349 if (EFI_ERROR (Status)) {
350 goto finish;
351 }
352
353 //
354 // ImageBase may deviate from ImageContext.ImageAddress if we are dealing
355 // with a TE image, in which case the latter points to the actual offset
356 // of the image, whereas ImageBase refers to the address where the image
357 // would start if the stripped PE headers were still in place. In either
358 // case, we need to fix up ImageBase so it refers to the actual current
359 // load address.
360 //
361 ImageBase += (UINTN)TeData - ImageContext.ImageAddress;
362
363 // Update the memory access permissions of individual sections in the
364 // Standalone MM core module
365 Status = UpdateMmFoundationPeCoffPermissions (
366 &ImageContext,
367 ImageBase,
368 SectionHeaderOffset,
369 NumberOfSections,
370 ArmSetMemoryRegionNoExec,
371 ArmSetMemoryRegionReadOnly,
372 ArmClearMemoryRegionReadOnly
373 );
374
375 if (EFI_ERROR (Status)) {
376 goto finish;
377 }
378
379 if (ImageContext.ImageAddress != (UINTN)TeData) {
380 ImageContext.ImageAddress = (UINTN)TeData;
381 ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB);
382 ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB);
383
384 Status = PeCoffLoaderRelocateImage (&ImageContext);
385 ASSERT_EFI_ERROR (Status);
386 }
387
388 //
389 // Create Hoblist based upon boot information passed by privileged software
390 //
391 HobStart = CreateHobListFromBootInfo (&CpuDriverEntryPoint, PayloadBootInfo);
392
393 //
394 // Call the MM Core entry point
395 //
396 ProcessModuleEntryPointList (HobStart);
397
398 DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP 0x%lx\n", (UINT64) CpuDriverEntryPoint));
399
400 finish:
401 if (Status == RETURN_UNSUPPORTED) {
402 Ret = -1;
403 } else if (Status == RETURN_INVALID_PARAMETER) {
404 Ret = -2;
405 } else if (Status == EFI_NOT_FOUND) {
406 Ret = -7;
407 } else {
408 Ret = 0;
409 }
410 ZeroMem (&InitMmFoundationSvcArgs, sizeof(InitMmFoundationSvcArgs));
411 InitArmSvcArgs (&InitMmFoundationSvcArgs, &Ret);
412 DelegatedEventLoop (&InitMmFoundationSvcArgs);
413 }