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