VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.c

Last change on this file was 108794, checked in by vboxsync, 3 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 12.7 KB
Line 
1/** @file
2 File managing the MMU for ARMv8 architecture in S-EL0
3
4 Copyright (c) 2017 - 2024, Arm Limited. All rights reserved.<BR>
5 Copyright (c) 2021, Linaro Limited
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 @par Reference(s):
9 - [1] SPM based on the MM interface.
10 (https://trustedfirmware-a.readthedocs.io/en/latest/components/
11 secure-partition-manager-mm.html)
12 - [2] Arm Firmware Framework for Armv8-A, DEN0077, version 1.2
13 (https://developer.arm.com/documentation/den0077/latest/)
14 - [3] FF-A Memory Management Protocol, DEN0140, version 1.2
15 (https://developer.arm.com/documentation/den0140/latest/)
16**/
17
18#include <Uefi.h>
19#include <IndustryStandard/ArmMmSvc.h>
20#include <IndustryStandard/ArmFfaSvc.h>
21
22#include <Library/ArmLib.h>
23#include <Library/ArmMmuLib.h>
24#include <Library/ArmFfaLib.h>
25#include <Library/ArmSvcLib.h>
26#include <Library/BaseLib.h>
27#include <Library/BaseMemoryLib.h>
28#include <Library/DebugLib.h>
29#include <Library/PcdLib.h>
30
31/**
32 Utility function to determine whether ABIs in FF-A to set and get
33 memory permissions can be used. Ideally, this should be invoked once in the
34 library constructor and set a flag that can be used at runtime. However, the
35 StMM Core invokes this library before constructors are called and before the
36 StMM image itself is relocated.
37
38 @retval TRUE Use FF-A MemPerm ABIs.
39 @retval FALSE Use MM MemPerm ABIs.
40
41**/
42STATIC
43BOOLEAN
44EFIAPI
45IsFfaMemoryAbiSupported (
46 IN VOID
47 )
48{
49 EFI_STATUS Status;
50 UINT16 CurrentMajorVersion;
51 UINT16 CurrentMinorVersion;
52
53 Status = ArmFfaLibGetVersion (
54 ARM_FFA_MAJOR_VERSION,
55 ARM_FFA_MINOR_VERSION,
56 &CurrentMajorVersion,
57 &CurrentMinorVersion
58 );
59
60 if (EFI_ERROR (Status)) {
61 return FALSE;
62 }
63
64 return TRUE;
65}
66
67/**
68 Convert FFA return code to EFI_STATUS.
69
70 @param [in] SpmMmStatus SPM_MM return code
71
72 @retval EFI_STATUS correspond EFI_STATUS to SpmMmStatus
73**/
74STATIC
75EFI_STATUS
76SpmMmStatusToEfiStatus (
77 IN UINTN SpmMmStatus
78 )
79{
80 switch (SpmMmStatus) {
81 case ARM_SPM_MM_RET_SUCCESS:
82 return EFI_SUCCESS;
83 case ARM_SPM_MM_RET_INVALID_PARAMS:
84 return EFI_INVALID_PARAMETER;
85 case ARM_SPM_MM_RET_DENIED:
86 return EFI_ACCESS_DENIED;
87 case ARM_SPM_MM_RET_NO_MEMORY:
88 return EFI_OUT_OF_RESOURCES;
89 default:
90 return EFI_UNSUPPORTED;
91 }
92}
93
94/** Send a request the target to get/set the memory permission.
95
96 @param [in] UseFfaAbis Use FF-A abis or not.
97 @param [in, out] SvcArgs Pointer to SVC arguments to send. On
98 return it contains the response parameters.
99 @param [out] RetVal Pointer to return the response value.
100
101 @retval EFI_SUCCESS Request successfull.
102 @retval EFI_INVALID_PARAMETER A parameter is invalid.
103 @retval EFI_NOT_READY Callee is busy or not in a state to handle
104 this request.
105 @retval EFI_UNSUPPORTED This function is not implemented by the
106 callee.
107 @retval EFI_ABORTED Message target ran into an unexpected error
108 and has aborted.
109 @retval EFI_ACCESS_DENIED Access denied.
110 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.
111**/
112STATIC
113EFI_STATUS
114SendMemoryPermissionRequest (
115 IN BOOLEAN UseFfaAbis,
116 IN OUT ARM_SVC_ARGS *SvcArgs,
117 OUT INT32 *RetVal
118 )
119{
120 if ((SvcArgs == NULL) || (RetVal == NULL)) {
121 return EFI_INVALID_PARAMETER;
122 }
123
124 ArmCallSvc (SvcArgs);
125
126 if (UseFfaAbis) {
127 if (IS_FID_FFA_ERROR (SvcArgs->Arg0)) {
128 return FfaStatusToEfiStatus (SvcArgs->Arg2);
129 }
130
131 *RetVal = SvcArgs->Arg2;
132 } else {
133 // Check error response from Callee.
134 // Bit 31 set means there is an error returned
135 // See [1], Section 13.5.5.1 MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 and
136 // Section 13.5.5.2 MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.
137 if ((SvcArgs->Arg0 & BIT31) != 0) {
138 return SpmMmStatusToEfiStatus (SvcArgs->Arg0);
139 }
140
141 *RetVal = SvcArgs->Arg0;
142 }
143
144 return EFI_SUCCESS;
145}
146
147/** Request the permission attributes of a memory region from S-EL0.
148
149 @param [in] UseFfaAbis Use FF-A abis or not.
150 @param [in] BaseAddress Base address for the memory region.
151 @param [out] MemoryAttributes Pointer to return the memory attributes.
152
153 @retval EFI_SUCCESS Request successfull.
154 @retval EFI_INVALID_PARAMETER A parameter is invalid.
155 @retval EFI_NOT_READY Callee is busy or not in a state to handle
156 this request.
157 @retval EFI_UNSUPPORTED This function is not implemented by the
158 callee.
159 @retval EFI_ABORTED Message target ran into an unexpected error
160 and has aborted.
161 @retval EFI_ACCESS_DENIED Access denied.
162 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.
163**/
164STATIC
165EFI_STATUS
166GetMemoryPermissions (
167 IN BOOLEAN UseFfaAbis,
168 IN EFI_PHYSICAL_ADDRESS BaseAddress,
169 OUT UINT32 *MemoryAttributes
170 )
171{
172 EFI_STATUS Status;
173 INT32 Ret;
174 ARM_SVC_ARGS SvcArgs;
175 UINTN Fid;
176
177 if (MemoryAttributes == NULL) {
178 return EFI_INVALID_PARAMETER;
179 }
180
181 // Prepare the message parameters.
182 // See [1], Section 13.5.5.1 MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64.
183 // See [3], Section 2.8 FFA_MEM_PERM_GET
184 Fid = (UseFfaAbis) ? ARM_FID_FFA_MEM_PERM_GET : ARM_FID_SPM_MM_SP_GET_MEM_ATTRIBUTES;
185
186 ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));
187 SvcArgs.Arg0 = Fid;
188 SvcArgs.Arg1 = BaseAddress;
189
190 Status = SendMemoryPermissionRequest (UseFfaAbis, &SvcArgs, &Ret);
191 if (EFI_ERROR (Status)) {
192 *MemoryAttributes = 0;
193 } else {
194 *MemoryAttributes = Ret;
195 }
196
197 return Status;
198}
199
200/** Request the permission attributes of the S-EL0 memory region to be updated.
201
202 @param [in] UseFfaAbis Use FF-A abis or not.
203 @param [in] BaseAddress Base address for the memory region.
204 @param [in] Length Length of the memory region.
205 @param [in] Permissions Memory access controls attributes.
206
207 @retval EFI_SUCCESS Request successfull.
208 @retval EFI_INVALID_PARAMETER A parameter is invalid.
209 @retval EFI_NOT_READY Callee is busy or not in a state to handle
210 this request.
211 @retval EFI_UNSUPPORTED This function is not implemented by the
212 callee.
213 @retval EFI_ABORTED Message target ran into an unexpected error
214 and has aborted.
215 @retval EFI_ACCESS_DENIED Access denied.
216 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.
217**/
218STATIC
219EFI_STATUS
220RequestMemoryPermissionChange (
221 IN BOOLEAN UseFfaAbis,
222 IN EFI_PHYSICAL_ADDRESS BaseAddress,
223 IN UINT64 Length,
224 IN UINT32 Permissions
225 )
226{
227 INT32 Ret;
228 ARM_SVC_ARGS SvcArgs;
229 UINTN Fid;
230
231 // Prepare the message parameters.
232 // See [1], Section 13.5.5.2 MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.
233 // See [3], Section 2.9 FFA_MEM_PERM_SET
234 Fid = (UseFfaAbis) ? ARM_FID_FFA_MEM_PERM_SET : ARM_FID_SPM_MM_SP_SET_MEM_ATTRIBUTES;
235
236 ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));
237
238 SvcArgs.Arg0 = Fid;
239 SvcArgs.Arg1 = BaseAddress;
240 SvcArgs.Arg2 = EFI_SIZE_TO_PAGES (Length);
241 SvcArgs.Arg3 = Permissions;
242
243 return SendMemoryPermissionRequest (UseFfaAbis, &SvcArgs, &Ret);
244}
245
246EFI_STATUS
247ArmSetMemoryRegionNoExec (
248 IN EFI_PHYSICAL_ADDRESS BaseAddress,
249 IN UINT64 Length
250 )
251{
252 EFI_STATUS Status;
253 UINT32 MemoryAttributes;
254 UINT32 PermissionRequest;
255 BOOLEAN UseFfaAbis;
256 UINTN Size;
257
258 UseFfaAbis = IsFfaMemoryAbiSupported ();
259 Size = EFI_PAGE_SIZE;
260
261 while (Length > 0) {
262 Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
263 if (EFI_ERROR (Status)) {
264 break;
265 }
266
267 if (UseFfaAbis) {
268 PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
269 MemoryAttributes,
270 ARM_FFA_SET_MEM_ATTR_CODE_PERM_XN
271 );
272 } else {
273 PermissionRequest = ARM_SPM_MM_SET_MEM_ATTR_MAKE_PERM_REQUEST (
274 MemoryAttributes,
275 ARM_SPM_MM_SET_MEM_ATTR_CODE_PERM_XN
276 );
277 }
278
279 if (Length < Size) {
280 Length = Size;
281 }
282
283 Status = RequestMemoryPermissionChange (
284 UseFfaAbis,
285 BaseAddress,
286 Size,
287 PermissionRequest
288 );
289 if (EFI_ERROR (Status)) {
290 return Status;
291 }
292
293 Length -= Size;
294 BaseAddress += Size;
295 } // while
296
297 return Status;
298}
299
300EFI_STATUS
301ArmClearMemoryRegionNoExec (
302 IN EFI_PHYSICAL_ADDRESS BaseAddress,
303 IN UINT64 Length
304 )
305{
306 EFI_STATUS Status;
307 UINT32 MemoryAttributes;
308 UINT32 PermissionRequest;
309 BOOLEAN UseFfaAbis;
310 UINTN Size;
311
312 UseFfaAbis = IsFfaMemoryAbiSupported ();
313 Size = EFI_PAGE_SIZE;
314
315 while (Length > 0) {
316 Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
317 if (EFI_ERROR (Status)) {
318 break;
319 }
320
321 if (UseFfaAbis) {
322 PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
323 MemoryAttributes,
324 ARM_FFA_SET_MEM_ATTR_CODE_PERM_X
325 );
326 } else {
327 PermissionRequest = ARM_SPM_MM_SET_MEM_ATTR_MAKE_PERM_REQUEST (
328 MemoryAttributes,
329 ARM_SPM_MM_SET_MEM_ATTR_CODE_PERM_X
330 );
331 }
332
333 if (Length < Size) {
334 Length = Size;
335 }
336
337 Status = RequestMemoryPermissionChange (
338 UseFfaAbis,
339 BaseAddress,
340 Size,
341 PermissionRequest
342 );
343 if (EFI_ERROR (Status)) {
344 return Status;
345 }
346
347 Length -= Size;
348 BaseAddress += Size;
349 } // while
350
351 return Status;
352}
353
354EFI_STATUS
355ArmSetMemoryRegionReadOnly (
356 IN EFI_PHYSICAL_ADDRESS BaseAddress,
357 IN UINT64 Length
358 )
359{
360 EFI_STATUS Status;
361 UINT32 MemoryAttributes;
362 UINT32 PermissionRequest;
363 BOOLEAN UseFfaAbis;
364 UINTN Size;
365
366 UseFfaAbis = IsFfaMemoryAbiSupported ();
367 Size = EFI_PAGE_SIZE;
368
369 while (Length > 0) {
370 Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
371 if (EFI_ERROR (Status)) {
372 break;
373 }
374
375 if (UseFfaAbis) {
376 PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
377 ARM_FFA_SET_MEM_ATTR_DATA_PERM_RO,
378 (MemoryAttributes >> ARM_FFA_SET_MEM_ATTR_CODE_PERM_SHIFT)
379 );
380 } else {
381 PermissionRequest = ARM_SPM_MM_SET_MEM_ATTR_MAKE_PERM_REQUEST (
382 ARM_SPM_MM_SET_MEM_ATTR_DATA_PERM_RO,
383 (MemoryAttributes >> ARM_SPM_MM_SET_MEM_ATTR_CODE_PERM_SHIFT)
384 );
385 }
386
387 if (Length < Size) {
388 Length = Size;
389 }
390
391 Status = RequestMemoryPermissionChange (
392 UseFfaAbis,
393 BaseAddress,
394 Size,
395 PermissionRequest
396 );
397 if (EFI_ERROR (Status)) {
398 return Status;
399 }
400
401 Length -= Size;
402 BaseAddress += Size;
403 } // while
404
405 return Status;
406}
407
408EFI_STATUS
409ArmClearMemoryRegionReadOnly (
410 IN EFI_PHYSICAL_ADDRESS BaseAddress,
411 IN UINT64 Length
412 )
413{
414 EFI_STATUS Status;
415 UINT32 MemoryAttributes;
416 UINT32 PermissionRequest;
417 BOOLEAN UseFfaAbis;
418 UINTN Size;
419
420 UseFfaAbis = IsFfaMemoryAbiSupported ();
421 Size = EFI_PAGE_SIZE;
422
423 while (Length > 0) {
424 Status = GetMemoryPermissions (UseFfaAbis, BaseAddress, &MemoryAttributes);
425 if (EFI_ERROR (Status)) {
426 break;
427 }
428
429 if (UseFfaAbis) {
430 PermissionRequest = ARM_FFA_SET_MEM_ATTR_MAKE_PERM_REQUEST (
431 ARM_FFA_SET_MEM_ATTR_DATA_PERM_RW,
432 (MemoryAttributes >> ARM_FFA_SET_MEM_ATTR_CODE_PERM_SHIFT)
433 );
434 } else {
435 PermissionRequest = ARM_SPM_MM_SET_MEM_ATTR_MAKE_PERM_REQUEST (
436 ARM_SPM_MM_SET_MEM_ATTR_DATA_PERM_RW,
437 (MemoryAttributes >> ARM_SPM_MM_SET_MEM_ATTR_CODE_PERM_SHIFT)
438 );
439 }
440
441 if (Length < Size) {
442 Length = Size;
443 }
444
445 Status = RequestMemoryPermissionChange (
446 UseFfaAbis,
447 BaseAddress,
448 Size,
449 PermissionRequest
450 );
451 if (EFI_ERROR (Status)) {
452 return Status;
453 }
454
455 Length -= Size;
456 BaseAddress += Size;
457 } // while
458
459 return Status;
460}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette