]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
StandaloneMmPkg: Add an AArch64 specific entry point library.
[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 - 2018, ARM Ltd. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <PiMm.h>
18
19 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>
20
21 #include <PiPei.h>
22 #include <Guid/MmramMemoryReserve.h>
23 #include <Guid/MpInformation.h>
24
25 #include <Library/ArmMmuLib.h>
26 #include <Library/ArmSvcLib.h>
27 #include <Library/DebugLib.h>
28 #include <Library/HobLib.h>
29 #include <Library/BaseLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/SerialPortLib.h>
32
33 #include <IndustryStandard/ArmStdSmc.h>
34 #include <IndustryStandard/ArmMmSvc.h>
35
36 #define SPM_MAJOR_VER_MASK 0xFFFF0000
37 #define SPM_MINOR_VER_MASK 0x0000FFFF
38 #define SPM_MAJOR_VER_SHIFT 16
39
40 CONST UINT32 SPM_MAJOR_VER = 0;
41 CONST UINT32 SPM_MINOR_VER = 1;
42
43 CONST UINT8 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 SharedBufAddress The pointer memory shared with privileged firmware
52
53 **/
54 EFI_SECURE_PARTITION_BOOT_INFO *
55 GetAndPrintBootinformation (
56 IN VOID *SharedBufAddress
57 )
58 {
59 EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
60 EFI_SECURE_PARTITION_CPU_INFO *PayloadCpuInfo;
61 UINTN Index;
62
63 PayloadBootInfo = (EFI_SECURE_PARTITION_BOOT_INFO *) SharedBufAddress;
64
65 if (PayloadBootInfo == NULL) {
66 DEBUG ((DEBUG_ERROR, "PayloadBootInfo NULL\n"));
67 return NULL;
68 }
69
70 if (PayloadBootInfo->Header.Version != BOOT_PAYLOAD_VERSION) {
71 DEBUG ((DEBUG_ERROR, "Boot Information Version Mismatch. Current=0x%x, Expected=0x%x.\n",
72 PayloadBootInfo->Header.Version, BOOT_PAYLOAD_VERSION));
73 return NULL;
74 }
75
76 DEBUG ((DEBUG_INFO, "NumSpMemRegions - 0x%x\n", PayloadBootInfo->NumSpMemRegions));
77 DEBUG ((DEBUG_INFO, "SpMemBase - 0x%lx\n", PayloadBootInfo->SpMemBase));
78 DEBUG ((DEBUG_INFO, "SpMemLimit - 0x%lx\n", PayloadBootInfo->SpMemLimit));
79 DEBUG ((DEBUG_INFO, "SpImageBase - 0x%lx\n", PayloadBootInfo->SpImageBase));
80 DEBUG ((DEBUG_INFO, "SpStackBase - 0x%lx\n", PayloadBootInfo->SpStackBase));
81 DEBUG ((DEBUG_INFO, "SpHeapBase - 0x%lx\n", PayloadBootInfo->SpHeapBase));
82 DEBUG ((DEBUG_INFO, "SpNsCommBufBase - 0x%lx\n", PayloadBootInfo->SpNsCommBufBase));
83 DEBUG ((DEBUG_INFO, "SpSharedBufBase - 0x%lx\n", PayloadBootInfo->SpSharedBufBase));
84
85 DEBUG ((DEBUG_INFO, "SpImageSize - 0x%x\n", PayloadBootInfo->SpImageSize));
86 DEBUG ((DEBUG_INFO, "SpPcpuStackSize - 0x%x\n", PayloadBootInfo->SpPcpuStackSize));
87 DEBUG ((DEBUG_INFO, "SpHeapSize - 0x%x\n", PayloadBootInfo->SpHeapSize));
88 DEBUG ((DEBUG_INFO, "SpNsCommBufSize - 0x%x\n", PayloadBootInfo->SpNsCommBufSize));
89 DEBUG ((DEBUG_INFO, "SpPcpuSharedBufSize - 0x%x\n", PayloadBootInfo->SpPcpuSharedBufSize));
90
91 DEBUG ((DEBUG_INFO, "NumCpus - 0x%x\n", PayloadBootInfo->NumCpus));
92 DEBUG ((DEBUG_INFO, "CpuInfo - 0x%p\n", PayloadBootInfo->CpuInfo));
93
94 PayloadCpuInfo = (EFI_SECURE_PARTITION_CPU_INFO *) PayloadBootInfo->CpuInfo;
95
96 if (PayloadCpuInfo == NULL) {
97 DEBUG ((DEBUG_ERROR, "PayloadCpuInfo NULL\n"));
98 return NULL;
99 }
100
101 for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) {
102 DEBUG ((DEBUG_INFO, "Mpidr - 0x%lx\n", PayloadCpuInfo[Index].Mpidr));
103 DEBUG ((DEBUG_INFO, "LinearId - 0x%x\n", PayloadCpuInfo[Index].LinearId));
104 DEBUG ((DEBUG_INFO, "Flags - 0x%x\n", PayloadCpuInfo[Index].Flags));
105 }
106
107 return PayloadBootInfo;
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 STATIC
166 EFI_STATUS
167 GetSpmVersion (VOID)
168 {
169 EFI_STATUS Status;
170 UINT16 SpmMajorVersion;
171 UINT16 SpmMinorVersion;
172 UINT32 SpmVersion;
173 ARM_SVC_ARGS SpmVersionArgs;
174
175 SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32;
176
177 ArmCallSvc (&SpmVersionArgs);
178
179 SpmVersion = SpmVersionArgs.Arg0;
180
181 SpmMajorVersion = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT);
182 SpmMinorVersion = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0);
183
184 // Different major revision values indicate possibly incompatible functions.
185 // For two revisions, A and B, for which the major revision values are
186 // identical, if the minor revision value of revision B is greater than
187 // the minor revision value of revision A, then every function in
188 // revision A must work in a compatible way with revision B.
189 // However, it is possible for revision B to have a higher
190 // function count than revision A.
191 if ((SpmMajorVersion == SPM_MAJOR_VER) &&
192 (SpmMinorVersion >= SPM_MINOR_VER))
193 {
194 DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n",
195 SpmMajorVersion, SpmMinorVersion));
196 Status = EFI_SUCCESS;
197 }
198 else
199 {
200 DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Current Version: Major=0x%x, Minor=0x%x.\n Expected: Major=0x%x, Minor>=0x%x.\n",
201 SpmMajorVersion, SpmMinorVersion, SPM_MAJOR_VER, SPM_MINOR_VER));
202 Status = EFI_UNSUPPORTED;
203 }
204
205 return Status;
206 }
207
208 /**
209 The entry point of Standalone MM Foundation.
210
211 @param SharedBufAddress Pointer to the Buffer between SPM and SP.
212 @param cookie1.
213 @param cookie2.
214
215 **/
216 VOID
217 EFIAPI
218 _ModuleEntryPoint (
219 IN VOID *SharedBufAddress,
220 IN UINT64 SharedBufSize,
221 IN UINT64 cookie1,
222 IN UINT64 cookie2
223 )
224 {
225 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
226 EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
227 ARM_SVC_ARGS InitMmFoundationSvcArgs = {0};
228 EFI_STATUS Status;
229 UINT32 SectionHeaderOffset;
230 UINT16 NumberOfSections;
231 VOID *HobStart;
232 VOID *TeData;
233 UINTN TeDataSize;
234
235 Status = SerialPortInitialize ();
236 ASSERT_EFI_ERROR (Status);
237
238 // Get Secure Partition Manager Version Information
239 Status = GetSpmVersion ();
240 if (EFI_ERROR (Status)) {
241 goto finish;
242 }
243
244 PayloadBootInfo = GetAndPrintBootinformation (SharedBufAddress);
245 if (PayloadBootInfo == NULL) {
246 Status = EFI_UNSUPPORTED;
247 goto finish;
248 }
249
250 // Locate PE/COFF File information for the Standalone MM core module
251 Status = LocateStandaloneMmCorePeCoffData (
252 (EFI_FIRMWARE_VOLUME_HEADER *) PayloadBootInfo->SpImageBase,
253 &TeData,
254 &TeDataSize
255 );
256
257 if (EFI_ERROR (Status)) {
258 goto finish;
259 }
260
261 // Obtain the PE/COFF Section information for the Standalone MM core module
262 Status = GetStandaloneMmCorePeCoffSections (
263 TeData,
264 &ImageContext,
265 &SectionHeaderOffset,
266 &NumberOfSections
267 );
268
269 if (EFI_ERROR (Status)) {
270 goto finish;
271 }
272
273 // Update the memory access permissions of individual sections in the
274 // Standalone MM core module
275 Status = UpdateMmFoundationPeCoffPermissions (
276 &ImageContext,
277 SectionHeaderOffset,
278 NumberOfSections,
279 ArmSetMemoryRegionNoExec,
280 ArmSetMemoryRegionReadOnly,
281 ArmClearMemoryRegionReadOnly
282 );
283
284 if (EFI_ERROR (Status)) {
285 goto finish;
286 }
287
288 //
289 // Create Hoblist based upon boot information passed by privileged software
290 //
291 HobStart = CreateHobListFromBootInfo (&CpuDriverEntryPoint, PayloadBootInfo);
292
293 //
294 // Call the MM Core entry point
295 //
296 ProcessModuleEntryPointList (HobStart);
297
298 ASSERT_EFI_ERROR (CpuDriverEntryPoint);
299 DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP 0x%lx\n", (UINT64) CpuDriverEntryPoint));
300
301 finish:
302 InitMmFoundationSvcArgs.Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
303 InitMmFoundationSvcArgs.Arg1 = Status;
304 DelegatedEventLoop (&InitMmFoundationSvcArgs);
305 ASSERT_EFI_ERROR (0);
306 }