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