]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.c
ArmPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmPkg / Library / StandaloneMmMmuLib / ArmMmuStandaloneMmLib.c
CommitLineData
eed947be 1/** @file\r
31eaefd4
SM
2 File managing the MMU for ARMv8 architecture in S-EL0\r
3\r
4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>\r
aee0098f 5 Copyright (c) 2021, Linaro Limited\r
31eaefd4
SM
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8 @par Reference(s):\r
9 - [1] SPM based on the MM interface.\r
10 (https://trustedfirmware-a.readthedocs.io/en/latest/components/\r
11 secure-partition-manager-mm.html)\r
12 - [2] Arm Firmware Framework for Armv8-A, DEN0077A, version 1.0\r
13 (https://developer.arm.com/documentation/den0077/a)\r
eed947be
AG
14**/\r
15\r
16#include <Uefi.h>\r
17#include <IndustryStandard/ArmMmSvc.h>\r
67f3f8b6 18#include <IndustryStandard/ArmFfaSvc.h>\r
eed947be
AG
19\r
20#include <Library/ArmLib.h>\r
21#include <Library/ArmMmuLib.h>\r
22#include <Library/ArmSvcLib.h>\r
23#include <Library/BaseLib.h>\r
0931171f 24#include <Library/BaseMemoryLib.h>\r
eed947be 25#include <Library/DebugLib.h>\r
0e43e02b 26#include <Library/PcdLib.h>\r
eed947be 27\r
31eaefd4
SM
28/** Send memory permission request to target.\r
29\r
30 @param [in, out] SvcArgs Pointer to SVC arguments to send. On\r
31 return it contains the response parameters.\r
32 @param [out] RetVal Pointer to return the response value.\r
33\r
34 @retval EFI_SUCCESS Request successfull.\r
35 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
36 @retval EFI_NOT_READY Callee is busy or not in a state to handle\r
37 this request.\r
38 @retval EFI_UNSUPPORTED This function is not implemented by the\r
39 callee.\r
40 @retval EFI_ABORTED Message target ran into an unexpected error\r
41 and has aborted.\r
42 @retval EFI_ACCESS_DENIED Access denied.\r
43 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.\r
44**/\r
eed947be
AG
45STATIC\r
46EFI_STATUS\r
31eaefd4 47SendMemoryPermissionRequest (\r
429309e0
MK
48 IN OUT ARM_SVC_ARGS *SvcArgs,\r
49 OUT INT32 *RetVal\r
eed947be
AG
50 )\r
51{\r
31eaefd4
SM
52 if ((SvcArgs == NULL) || (RetVal == NULL)) {\r
53 return EFI_INVALID_PARAMETER;\r
0e43e02b 54 }\r
eed947be 55\r
31eaefd4
SM
56 ArmCallSvc (SvcArgs);\r
57 if (FeaturePcdGet (PcdFfaEnable)) {\r
58 // Get/Set memory attributes is an atomic call, with\r
0e43e02b
AG
59 // StandaloneMm at S-EL0 being the caller and the SPM\r
60 // core being the callee. Thus there won't be a\r
61 // FFA_INTERRUPT or FFA_SUCCESS response to the Direct\r
62 // Request sent above. This will have to be considered\r
63 // for other Direct Request calls which are not atomic\r
64 // We therefore check only for Direct Response by the\r
65 // callee.\r
aee0098f 66 if (SvcArgs->Arg0 == ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP) {\r
31eaefd4
SM
67 // A Direct Response means FF-A success\r
68 // Now check the payload for errors\r
69 // The callee sends back the return value\r
70 // in Arg3\r
71 *RetVal = SvcArgs->Arg3;\r
72 } else {\r
0e43e02b
AG
73 // If Arg0 is not a Direct Response, that means we\r
74 // have an FF-A error. We need to check Arg2 for the\r
75 // FF-A error code.\r
31eaefd4
SM
76 // See [2], Table 10.8: FFA_ERROR encoding.\r
77 *RetVal = SvcArgs->Arg2;\r
78 switch (*RetVal) {\r
79 case ARM_FFA_SPM_RET_INVALID_PARAMETERS:\r
80 return EFI_INVALID_PARAMETER;\r
0e43e02b 81\r
31eaefd4
SM
82 case ARM_FFA_SPM_RET_DENIED:\r
83 return EFI_ACCESS_DENIED;\r
0e43e02b 84\r
31eaefd4
SM
85 case ARM_FFA_SPM_RET_NOT_SUPPORTED:\r
86 return EFI_UNSUPPORTED;\r
0e43e02b 87\r
31eaefd4
SM
88 case ARM_FFA_SPM_RET_BUSY:\r
89 return EFI_NOT_READY;\r
0e43e02b 90\r
31eaefd4
SM
91 case ARM_FFA_SPM_RET_ABORTED:\r
92 return EFI_ABORTED;\r
0e43e02b 93\r
31eaefd4
SM
94 default:\r
95 // Undefined error code received.\r
96 ASSERT (0);\r
97 return EFI_INVALID_PARAMETER;\r
0e43e02b 98 }\r
0e43e02b
AG
99 }\r
100 } else {\r
31eaefd4 101 *RetVal = SvcArgs->Arg0;\r
0e43e02b
AG
102 }\r
103\r
31eaefd4 104 // Check error response from Callee.\r
fd9cc205 105 if ((*RetVal & BIT31) != 0) {\r
b8de64be 106 // Bit 31 set means there is an error returned\r
31eaefd4
SM
107 // See [1], Section 13.5.5.1 MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 and\r
108 // Section 13.5.5.2 MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.\r
109 switch (*RetVal) {\r
110 case ARM_SVC_SPM_RET_NOT_SUPPORTED:\r
111 return EFI_UNSUPPORTED;\r
112\r
113 case ARM_SVC_SPM_RET_INVALID_PARAMS:\r
114 return EFI_INVALID_PARAMETER;\r
115\r
116 case ARM_SVC_SPM_RET_DENIED:\r
117 return EFI_ACCESS_DENIED;\r
118\r
119 case ARM_SVC_SPM_RET_NO_MEMORY:\r
120 return EFI_OUT_OF_RESOURCES;\r
0e43e02b 121\r
31eaefd4
SM
122 default:\r
123 // Undefined error code received.\r
124 ASSERT (0);\r
125 return EFI_INVALID_PARAMETER;\r
0e43e02b 126 }\r
eed947be
AG
127 }\r
128\r
eed947be
AG
129 return EFI_SUCCESS;\r
130}\r
131\r
31eaefd4
SM
132/** Request the permission attributes of a memory region from S-EL0.\r
133\r
134 @param [in] BaseAddress Base address for the memory region.\r
135 @param [out] MemoryAttributes Pointer to return the memory attributes.\r
136\r
137 @retval EFI_SUCCESS Request successfull.\r
138 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
139 @retval EFI_NOT_READY Callee is busy or not in a state to handle\r
140 this request.\r
141 @retval EFI_UNSUPPORTED This function is not implemented by the\r
142 callee.\r
143 @retval EFI_ABORTED Message target ran into an unexpected error\r
144 and has aborted.\r
145 @retval EFI_ACCESS_DENIED Access denied.\r
146 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.\r
147**/\r
eed947be
AG
148STATIC\r
149EFI_STATUS\r
31eaefd4 150GetMemoryPermissions (\r
429309e0
MK
151 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
152 OUT UINT32 *MemoryAttributes\r
eed947be
AG
153 )\r
154{\r
31eaefd4 155 EFI_STATUS Status;\r
9da5ee11 156 INT32 Ret;\r
31eaefd4 157 ARM_SVC_ARGS SvcArgs;\r
eed947be 158\r
31eaefd4
SM
159 if (MemoryAttributes == NULL) {\r
160 return EFI_INVALID_PARAMETER;\r
9da5ee11 161 }\r
eed947be 162\r
31eaefd4
SM
163 // Prepare the message parameters.\r
164 // See [1], Section 13.5.5.1 MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64.\r
165 ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));\r
166 if (FeaturePcdGet (PcdFfaEnable)) {\r
167 // See [2], Section 10.2 FFA_MSG_SEND_DIRECT_REQ.\r
aee0098f 168 SvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ;\r
31eaefd4
SM
169 SvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
170 SvcArgs.Arg2 = 0;\r
aee0098f 171 SvcArgs.Arg3 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES;\r
31eaefd4 172 SvcArgs.Arg4 = BaseAddress;\r
9da5ee11 173 } else {\r
aee0098f 174 SvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES;\r
31eaefd4
SM
175 SvcArgs.Arg1 = BaseAddress;\r
176 SvcArgs.Arg2 = 0;\r
177 SvcArgs.Arg3 = 0;\r
9da5ee11 178 }\r
eed947be 179\r
31eaefd4
SM
180 Status = SendMemoryPermissionRequest (&SvcArgs, &Ret);\r
181 if (EFI_ERROR (Status)) {\r
182 *MemoryAttributes = 0;\r
183 return Status;\r
184 }\r
eed947be 185\r
31eaefd4
SM
186 *MemoryAttributes = Ret;\r
187 return Status;\r
188}\r
eed947be 189\r
31eaefd4
SM
190/** Set the permission attributes of a memory region from S-EL0.\r
191\r
192 @param [in] BaseAddress Base address for the memory region.\r
193 @param [in] Length Length of the memory region.\r
194 @param [in] Permissions Memory access controls attributes.\r
195\r
196 @retval EFI_SUCCESS Request successfull.\r
197 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
198 @retval EFI_NOT_READY Callee is busy or not in a state to handle\r
199 this request.\r
200 @retval EFI_UNSUPPORTED This function is not implemented by the\r
201 callee.\r
202 @retval EFI_ABORTED Message target ran into an unexpected error\r
203 and has aborted.\r
204 @retval EFI_ACCESS_DENIED Access denied.\r
205 @retval EFI_OUT_OF_RESOURCES Out of memory to perform operation.\r
206**/\r
207STATIC\r
208EFI_STATUS\r
209RequestMemoryPermissionChange (\r
429309e0
MK
210 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
211 IN UINT64 Length,\r
212 IN UINT32 Permissions\r
31eaefd4
SM
213 )\r
214{\r
215 INT32 Ret;\r
216 ARM_SVC_ARGS SvcArgs;\r
217\r
218 // Prepare the message parameters.\r
219 // See [1], Section 13.5.5.2 MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64.\r
220 ZeroMem (&SvcArgs, sizeof (ARM_SVC_ARGS));\r
221 if (FeaturePcdGet (PcdFfaEnable)) {\r
222 // See [2], Section 10.2 FFA_MSG_SEND_DIRECT_REQ.\r
aee0098f 223 SvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ;\r
31eaefd4
SM
224 SvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
225 SvcArgs.Arg2 = 0;\r
aee0098f 226 SvcArgs.Arg3 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES;\r
31eaefd4
SM
227 SvcArgs.Arg4 = BaseAddress;\r
228 SvcArgs.Arg5 = EFI_SIZE_TO_PAGES (Length);\r
229 SvcArgs.Arg6 = Permissions;\r
230 } else {\r
aee0098f 231 SvcArgs.Arg0 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES;\r
31eaefd4
SM
232 SvcArgs.Arg1 = BaseAddress;\r
233 SvcArgs.Arg2 = EFI_SIZE_TO_PAGES (Length);\r
234 SvcArgs.Arg3 = Permissions;\r
eed947be
AG
235 }\r
236\r
31eaefd4 237 return SendMemoryPermissionRequest (&SvcArgs, &Ret);\r
eed947be
AG
238}\r
239\r
240EFI_STATUS\r
241ArmSetMemoryRegionNoExec (\r
429309e0
MK
242 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
243 IN UINT64 Length\r
eed947be
AG
244 )\r
245{\r
429309e0
MK
246 EFI_STATUS Status;\r
247 UINT32 MemoryAttributes;\r
248 UINT32 CodePermission;\r
eed947be
AG
249\r
250 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 251 if (!EFI_ERROR (Status)) {\r
eed947be
AG
252 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;\r
253 return RequestMemoryPermissionChange (\r
254 BaseAddress,\r
255 Length,\r
256 MemoryAttributes | CodePermission\r
257 );\r
258 }\r
429309e0 259\r
31eaefd4 260 return Status;\r
eed947be
AG
261}\r
262\r
263EFI_STATUS\r
264ArmClearMemoryRegionNoExec (\r
429309e0
MK
265 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
266 IN UINT64 Length\r
eed947be
AG
267 )\r
268{\r
429309e0
MK
269 EFI_STATUS Status;\r
270 UINT32 MemoryAttributes;\r
271 UINT32 CodePermission;\r
eed947be
AG
272\r
273 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 274 if (!EFI_ERROR (Status)) {\r
eed947be
AG
275 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;\r
276 return RequestMemoryPermissionChange (\r
277 BaseAddress,\r
278 Length,\r
279 MemoryAttributes & ~CodePermission\r
280 );\r
281 }\r
429309e0 282\r
31eaefd4 283 return Status;\r
eed947be
AG
284}\r
285\r
286EFI_STATUS\r
287ArmSetMemoryRegionReadOnly (\r
429309e0
MK
288 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
289 IN UINT64 Length\r
eed947be
AG
290 )\r
291{\r
429309e0
MK
292 EFI_STATUS Status;\r
293 UINT32 MemoryAttributes;\r
294 UINT32 DataPermission;\r
eed947be
AG
295\r
296 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 297 if (!EFI_ERROR (Status)) {\r
eed947be
AG
298 DataPermission = SET_MEM_ATTR_DATA_PERM_RO << SET_MEM_ATTR_DATA_PERM_SHIFT;\r
299 return RequestMemoryPermissionChange (\r
300 BaseAddress,\r
301 Length,\r
302 MemoryAttributes | DataPermission\r
303 );\r
304 }\r
429309e0 305\r
31eaefd4 306 return Status;\r
eed947be
AG
307}\r
308\r
309EFI_STATUS\r
310ArmClearMemoryRegionReadOnly (\r
429309e0
MK
311 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
312 IN UINT64 Length\r
eed947be
AG
313 )\r
314{\r
429309e0
MK
315 EFI_STATUS Status;\r
316 UINT32 MemoryAttributes;\r
317 UINT32 PermissionRequest;\r
eed947be
AG
318\r
319 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);\r
31eaefd4 320 if (!EFI_ERROR (Status)) {\r
429309e0
MK
321 PermissionRequest = SET_MEM_ATTR_MAKE_PERM_REQUEST (\r
322 SET_MEM_ATTR_DATA_PERM_RW,\r
323 MemoryAttributes\r
324 );\r
eed947be
AG
325 return RequestMemoryPermissionChange (\r
326 BaseAddress,\r
327 Length,\r
328 PermissionRequest\r
329 );\r
330 }\r
429309e0 331\r
31eaefd4 332 return Status;\r
eed947be 333}\r