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