2 Entry point to the Standalone MM Foundation when initialized during the SEC
5 Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>
16 #include <Guid/MmramMemoryReserve.h>
17 #include <Guid/MpInformation.h>
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>
28 #include <IndustryStandard/ArmStdSmc.h>
29 #include <IndustryStandard/ArmMmSvc.h>
30 #include <IndustryStandard/ArmFfaSvc.h>
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
37 STATIC CONST UINT32 mSpmMajorVer
= SPM_MAJOR_VERSION
;
38 STATIC CONST UINT32 mSpmMinorVer
= SPM_MINOR_VERSION
;
40 STATIC CONST UINT32 mSpmMajorVerFfa
= SPM_MAJOR_VERSION_FFA
;
41 STATIC CONST UINT32 mSpmMinorVerFfa
= SPM_MINOR_VERSION_FFA
;
43 #define BOOT_PAYLOAD_VERSION 1
45 PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint
= NULL
;
48 Retrieve a pointer to and print the boot information passed by privileged
51 @param [in] SharedBufAddress The pointer memory shared with privileged
55 EFI_SECURE_PARTITION_BOOT_INFO
*
56 GetAndPrintBootinformation (
57 IN VOID
*SharedBufAddress
60 EFI_SECURE_PARTITION_BOOT_INFO
*PayloadBootInfo
;
61 EFI_SECURE_PARTITION_CPU_INFO
*PayloadCpuInfo
;
64 PayloadBootInfo
= (EFI_SECURE_PARTITION_BOOT_INFO
*) SharedBufAddress
;
66 if (PayloadBootInfo
== NULL
) {
67 DEBUG ((DEBUG_ERROR
, "PayloadBootInfo NULL\n"));
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
));
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
));
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
));
92 DEBUG ((DEBUG_INFO
, "NumCpus - 0x%x\n", PayloadBootInfo
->NumCpus
));
93 DEBUG ((DEBUG_INFO
, "CpuInfo - 0x%p\n", PayloadBootInfo
->CpuInfo
));
95 PayloadCpuInfo
= (EFI_SECURE_PARTITION_CPU_INFO
*) PayloadBootInfo
->CpuInfo
;
97 if (PayloadCpuInfo
== NULL
) {
98 DEBUG ((DEBUG_ERROR
, "PayloadCpuInfo NULL\n"));
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
));
108 return PayloadBootInfo
;
112 A loop to delegated events.
114 @param [in] EventCompleteSvcArgs Pointer to the event completion arguments.
120 IN ARM_SVC_ARGS
*EventCompleteSvcArgs
128 ArmCallSvc (EventCompleteSvcArgs
);
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
));
140 FfaEnabled
= FeaturePcdGet (PcdFfaEnable
);
142 Status
= CpuDriverEntryPoint (
143 EventCompleteSvcArgs
->Arg0
,
144 EventCompleteSvcArgs
->Arg6
,
145 EventCompleteSvcArgs
->Arg3
147 if (EFI_ERROR (Status
)) {
148 DEBUG ((DEBUG_ERROR
, "Failed delegated event 0x%x, Status 0x%x\n",
149 EventCompleteSvcArgs
->Arg3
, Status
));
152 Status
= CpuDriverEntryPoint (
153 EventCompleteSvcArgs
->Arg0
,
154 EventCompleteSvcArgs
->Arg3
,
155 EventCompleteSvcArgs
->Arg1
157 if (EFI_ERROR (Status
)) {
158 DEBUG ((DEBUG_ERROR
, "Failed delegated event 0x%x, Status 0x%x\n",
159 EventCompleteSvcArgs
->Arg0
, Status
));
165 SvcStatus
= ARM_SVC_SPM_RET_SUCCESS
;
167 case EFI_INVALID_PARAMETER
:
168 SvcStatus
= ARM_SVC_SPM_RET_INVALID_PARAMS
;
170 case EFI_ACCESS_DENIED
:
171 SvcStatus
= ARM_SVC_SPM_RET_DENIED
;
173 case EFI_OUT_OF_RESOURCES
:
174 SvcStatus
= ARM_SVC_SPM_RET_NO_MEMORY
;
176 case EFI_UNSUPPORTED
:
177 SvcStatus
= ARM_SVC_SPM_RET_NOT_SUPPORTED
;
180 SvcStatus
= ARM_SVC_SPM_RET_NOT_SUPPORTED
;
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
;
191 EventCompleteSvcArgs
->Arg0
= ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
;
192 EventCompleteSvcArgs
->Arg1
= SvcStatus
;
198 Query the SPM version, check compatibility and return success if compatible.
200 @retval EFI_SUCCESS SPM versions compatible.
201 @retval EFI_UNSUPPORTED SPM versions not compatible.
208 UINT16 CalleeSpmMajorVer
;
209 UINT16 CallerSpmMajorVer
;
210 UINT16 CalleeSpmMinorVer
;
211 UINT16 CallerSpmMinorVer
;
213 ARM_SVC_ARGS SpmVersionArgs
;
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
;
222 SpmVersionArgs
.Arg0
= ARM_SVC_ID_SPM_VERSION_AARCH32
;
223 CallerSpmMajorVer
= mSpmMajorVer
;
224 CallerSpmMinorVer
= mSpmMinorVer
;
227 ArmCallSvc (&SpmVersionArgs
);
229 SpmVersion
= SpmVersionArgs
.Arg0
;
230 if (SpmVersion
== FFA_NOT_SUPPORTED
) {
231 return EFI_UNSUPPORTED
;
234 CalleeSpmMajorVer
= ((SpmVersion
& SPM_MAJOR_VER_MASK
) >> SPM_MAJOR_VER_SHIFT
);
235 CalleeSpmMinorVer
= ((SpmVersion
& SPM_MINOR_VER_MASK
) >> 0);
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
))
247 DEBUG ((DEBUG_INFO
, "SPM Version: Major=0x%x, Minor=0x%x\n",
248 CalleeSpmMajorVer
, CalleeSpmMinorVer
));
249 Status
= EFI_SUCCESS
;
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
;
262 Initialize parameters to be sent via SVC call.
264 @param[out] InitMmFoundationSvcArgs Args structure
265 @param[out] Ret Return Code
271 OUT ARM_SVC_ARGS
*InitMmFoundationSvcArgs
,
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
;
282 InitMmFoundationSvcArgs
->Arg0
= ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
;
283 InitMmFoundationSvcArgs
->Arg1
= *Ret
;
288 The entry point of Standalone MM Foundation.
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
299 IN VOID
*SharedBufAddress
,
300 IN UINT64 SharedBufSize
,
305 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
306 EFI_SECURE_PARTITION_BOOT_INFO
*PayloadBootInfo
;
307 ARM_SVC_ARGS InitMmFoundationSvcArgs
;
310 UINT32 SectionHeaderOffset
;
311 UINT16 NumberOfSections
;
315 EFI_PHYSICAL_ADDRESS ImageBase
;
317 // Get Secure Partition Manager Version Information
318 Status
= GetSpmVersion ();
319 if (EFI_ERROR (Status
)) {
323 PayloadBootInfo
= GetAndPrintBootinformation (SharedBufAddress
);
324 if (PayloadBootInfo
== NULL
) {
325 Status
= EFI_UNSUPPORTED
;
329 // Locate PE/COFF File information for the Standalone MM core module
330 Status
= LocateStandaloneMmCorePeCoffData (
331 (EFI_FIRMWARE_VOLUME_HEADER
*) PayloadBootInfo
->SpImageBase
,
336 if (EFI_ERROR (Status
)) {
340 // Obtain the PE/COFF Section information for the Standalone MM core module
341 Status
= GetStandaloneMmCorePeCoffSections (
345 &SectionHeaderOffset
,
349 if (EFI_ERROR (Status
)) {
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
361 ImageBase
+= (UINTN
)TeData
- ImageContext
.ImageAddress
;
363 // Update the memory access permissions of individual sections in the
364 // Standalone MM core module
365 Status
= UpdateMmFoundationPeCoffPermissions (
370 ArmSetMemoryRegionNoExec
,
371 ArmSetMemoryRegionReadOnly
,
372 ArmClearMemoryRegionReadOnly
375 if (EFI_ERROR (Status
)) {
379 if (ImageContext
.ImageAddress
!= (UINTN
)TeData
) {
380 ImageContext
.ImageAddress
= (UINTN
)TeData
;
381 ArmSetMemoryRegionNoExec (ImageBase
, SIZE_4KB
);
382 ArmClearMemoryRegionReadOnly (ImageBase
, SIZE_4KB
);
384 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
385 ASSERT_EFI_ERROR (Status
);
389 // Create Hoblist based upon boot information passed by privileged software
391 HobStart
= CreateHobListFromBootInfo (&CpuDriverEntryPoint
, PayloadBootInfo
);
394 // Call the MM Core entry point
396 ProcessModuleEntryPointList (HobStart
);
398 DEBUG ((DEBUG_INFO
, "Shared Cpu Driver EP 0x%lx\n", (UINT64
) CpuDriverEntryPoint
));
401 if (Status
== RETURN_UNSUPPORTED
) {
403 } else if (Status
== RETURN_INVALID_PARAMETER
) {
405 } else if (Status
== EFI_NOT_FOUND
) {
410 ZeroMem (&InitMmFoundationSvcArgs
, sizeof(InitMmFoundationSvcArgs
));
411 InitArmSvcArgs (&InitMmFoundationSvcArgs
, &Ret
);
412 DelegatedEventLoop (&InitMmFoundationSvcArgs
);