]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/OpteeLib/Optee.c
ArmPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmPkg / Library / OpteeLib / Optee.c
CommitLineData
d65b78f1
SG
1/** @file\r
2 Api's to communicate with OP-TEE OS (Trusted OS based on ARM TrustZone) via\r
3 secure monitor calls.\r
4\r
5 Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>\r
d61b2e28 6 Copyright (c) 2021, Arm Limited. All rights reserved.<BR>\r
d65b78f1 7\r
4059386c 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
d65b78f1
SG
9\r
10**/\r
11\r
a0f01e8a 12#include <Library/ArmMmuLib.h>\r
d65b78f1 13#include <Library/ArmSmcLib.h>\r
a0f01e8a 14#include <Library/BaseMemoryLib.h>\r
d65b78f1 15#include <Library/BaseLib.h>\r
a0f01e8a 16#include <Library/DebugLib.h>\r
d65b78f1
SG
17#include <Library/OpteeLib.h>\r
18\r
19#include <IndustryStandard/ArmStdSmc.h>\r
a0f01e8a
SG
20#include <OpteeSmc.h>\r
21#include <Uefi.h>\r
22\r
429309e0 23STATIC OPTEE_SHARED_MEMORY_INFORMATION OpteeSharedMemoryInformation = { 0 };\r
d65b78f1
SG
24\r
25/**\r
26 Check for OP-TEE presence.\r
27**/\r
28BOOLEAN\r
29EFIAPI\r
30IsOpteePresent (\r
31 VOID\r
32 )\r
33{\r
429309e0 34 ARM_SMC_ARGS ArmSmcArgs;\r
d65b78f1 35\r
a0f01e8a 36 ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));\r
d65b78f1
SG
37 // Send a Trusted OS Calls UID command\r
38 ArmSmcArgs.Arg0 = ARM_SMC_ID_TOS_UID;\r
39 ArmCallSmc (&ArmSmcArgs);\r
40\r
41 if ((ArmSmcArgs.Arg0 == OPTEE_OS_UID0) &&\r
42 (ArmSmcArgs.Arg1 == OPTEE_OS_UID1) &&\r
43 (ArmSmcArgs.Arg2 == OPTEE_OS_UID2) &&\r
429309e0
MK
44 (ArmSmcArgs.Arg3 == OPTEE_OS_UID3))\r
45 {\r
d65b78f1
SG
46 return TRUE;\r
47 } else {\r
48 return FALSE;\r
49 }\r
50}\r
a0f01e8a
SG
51\r
52STATIC\r
53EFI_STATUS\r
54OpteeSharedMemoryRemap (\r
55 VOID\r
56 )\r
57{\r
429309e0
MK
58 ARM_SMC_ARGS ArmSmcArgs;\r
59 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
60 EFI_PHYSICAL_ADDRESS Start;\r
61 EFI_PHYSICAL_ADDRESS End;\r
62 EFI_STATUS Status;\r
63 UINTN Size;\r
a0f01e8a
SG
64\r
65 ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));\r
66 ArmSmcArgs.Arg0 = OPTEE_SMC_GET_SHARED_MEMORY_CONFIG;\r
67\r
68 ArmCallSmc (&ArmSmcArgs);\r
69 if (ArmSmcArgs.Arg0 != OPTEE_SMC_RETURN_OK) {\r
70 DEBUG ((DEBUG_WARN, "OP-TEE shared memory not supported\n"));\r
71 return EFI_UNSUPPORTED;\r
72 }\r
73\r
74 if (ArmSmcArgs.Arg3 != OPTEE_SMC_SHARED_MEMORY_CACHED) {\r
75 DEBUG ((DEBUG_WARN, "OP-TEE: Only normal cached shared memory supported\n"));\r
76 return EFI_UNSUPPORTED;\r
77 }\r
78\r
429309e0
MK
79 Start = (ArmSmcArgs.Arg1 + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
80 End = (ArmSmcArgs.Arg1 + ArmSmcArgs.Arg2) & ~(SIZE_4KB - 1);\r
a0f01e8a 81 PhysicalAddress = Start;\r
429309e0 82 Size = End - Start;\r
a0f01e8a
SG
83\r
84 if (Size < SIZE_4KB) {\r
85 DEBUG ((DEBUG_WARN, "OP-TEE shared memory too small\n"));\r
86 return EFI_BUFFER_TOO_SMALL;\r
87 }\r
88\r
89 Status = ArmSetMemoryAttributes (PhysicalAddress, Size, EFI_MEMORY_WB);\r
90 if (EFI_ERROR (Status)) {\r
91 return Status;\r
92 }\r
93\r
94 OpteeSharedMemoryInformation.Base = (UINTN)PhysicalAddress;\r
95 OpteeSharedMemoryInformation.Size = Size;\r
96\r
97 return EFI_SUCCESS;\r
98}\r
99\r
100EFI_STATUS\r
101EFIAPI\r
102OpteeInit (\r
103 VOID\r
104 )\r
105{\r
429309e0 106 EFI_STATUS Status;\r
a0f01e8a
SG
107\r
108 if (!IsOpteePresent ()) {\r
109 DEBUG ((DEBUG_WARN, "OP-TEE not present\n"));\r
110 return EFI_UNSUPPORTED;\r
111 }\r
112\r
113 Status = OpteeSharedMemoryRemap ();\r
114 if (EFI_ERROR (Status)) {\r
115 DEBUG ((DEBUG_WARN, "OP-TEE shared memory remap failed\n"));\r
116 return Status;\r
117 }\r
118\r
119 return EFI_SUCCESS;\r
120}\r
121\r
088a5334
SG
122STATIC\r
123BOOLEAN\r
124IsOpteeSmcReturnRpc (\r
429309e0 125 UINT32 Return\r
088a5334
SG
126 )\r
127{\r
128 return (Return != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION) &&\r
129 ((Return & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==\r
130 OPTEE_SMC_RETURN_RPC_PREFIX);\r
131}\r
132\r
a0f01e8a
SG
133/**\r
134 Does Standard SMC to OP-TEE in secure world.\r
135\r
136 @param[in] PhysicalArg Physical address of message to pass to secure world\r
137\r
138 @return 0 on success, secure world return code otherwise\r
139\r
140**/\r
141STATIC\r
142UINT32\r
143OpteeCallWithArg (\r
429309e0 144 IN UINT64 PhysicalArg\r
a0f01e8a
SG
145 )\r
146{\r
429309e0 147 ARM_SMC_ARGS ArmSmcArgs;\r
a0f01e8a
SG
148\r
149 ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));\r
150 ArmSmcArgs.Arg0 = OPTEE_SMC_CALL_WITH_ARG;\r
151 ArmSmcArgs.Arg1 = (UINT32)(PhysicalArg >> 32);\r
152 ArmSmcArgs.Arg2 = (UINT32)PhysicalArg;\r
153\r
154 while (TRUE) {\r
155 ArmCallSmc (&ArmSmcArgs);\r
156\r
088a5334
SG
157 if (IsOpteeSmcReturnRpc (ArmSmcArgs.Arg0)) {\r
158 switch (ArmSmcArgs.Arg0) {\r
429309e0
MK
159 case OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT:\r
160 //\r
161 // A foreign interrupt was raised while secure world was\r
162 // executing, since they are handled in UEFI a dummy RPC is\r
163 // performed to let UEFI take the interrupt through the normal\r
164 // vector.\r
165 //\r
166 break;\r
167\r
168 default:\r
169 // Do nothing in case RPC is not implemented.\r
170 break;\r
088a5334
SG
171 }\r
172\r
a0f01e8a
SG
173 ArmSmcArgs.Arg0 = OPTEE_SMC_RETURN_FROM_RPC;\r
174 } else {\r
175 break;\r
176 }\r
177 }\r
178\r
179 return ArmSmcArgs.Arg0;\r
180}\r
181\r
182STATIC\r
183VOID\r
184EfiGuidToRfc4122Uuid (\r
429309e0
MK
185 OUT RFC4122_UUID *Rfc4122Uuid,\r
186 IN EFI_GUID *Guid\r
a0f01e8a
SG
187 )\r
188{\r
189 Rfc4122Uuid->Data1 = SwapBytes32 (Guid->Data1);\r
190 Rfc4122Uuid->Data2 = SwapBytes16 (Guid->Data2);\r
191 Rfc4122Uuid->Data3 = SwapBytes16 (Guid->Data3);\r
192 CopyMem (Rfc4122Uuid->Data4, Guid->Data4, sizeof (Rfc4122Uuid->Data4));\r
193}\r
194\r
195EFI_STATUS\r
196EFIAPI\r
197OpteeOpenSession (\r
429309e0 198 IN OUT OPTEE_OPEN_SESSION_ARG *OpenSessionArg\r
a0f01e8a
SG
199 )\r
200{\r
429309e0 201 OPTEE_MESSAGE_ARG *MessageArg;\r
a0f01e8a
SG
202\r
203 MessageArg = NULL;\r
204\r
205 if (OpteeSharedMemoryInformation.Base == 0) {\r
206 DEBUG ((DEBUG_WARN, "OP-TEE not initialized\n"));\r
207 return EFI_NOT_STARTED;\r
208 }\r
209\r
210 MessageArg = (OPTEE_MESSAGE_ARG *)OpteeSharedMemoryInformation.Base;\r
211 ZeroMem (MessageArg, sizeof (OPTEE_MESSAGE_ARG));\r
212\r
213 MessageArg->Command = OPTEE_MESSAGE_COMMAND_OPEN_SESSION;\r
214\r
215 //\r
216 // Initialize and add the meta parameters needed when opening a\r
217 // session.\r
218 //\r
219 MessageArg->Params[0].Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT |\r
220 OPTEE_MESSAGE_ATTRIBUTE_META;\r
221 MessageArg->Params[1].Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT |\r
222 OPTEE_MESSAGE_ATTRIBUTE_META;\r
223 EfiGuidToRfc4122Uuid (\r
224 (RFC4122_UUID *)&MessageArg->Params[0].Union.Value,\r
225 &OpenSessionArg->Uuid\r
226 );\r
227 ZeroMem (&MessageArg->Params[1].Union.Value, sizeof (EFI_GUID));\r
228 MessageArg->Params[1].Union.Value.C = OPTEE_LOGIN_PUBLIC;\r
229\r
230 MessageArg->NumParams = 2;\r
231\r
d61b2e28 232 if (OpteeCallWithArg ((UINTN)MessageArg) != 0) {\r
429309e0 233 MessageArg->Return = OPTEE_ERROR_COMMUNICATION;\r
a0f01e8a
SG
234 MessageArg->ReturnOrigin = OPTEE_ORIGIN_COMMUNICATION;\r
235 }\r
236\r
429309e0
MK
237 OpenSessionArg->Session = MessageArg->Session;\r
238 OpenSessionArg->Return = MessageArg->Return;\r
a0f01e8a
SG
239 OpenSessionArg->ReturnOrigin = MessageArg->ReturnOrigin;\r
240\r
241 return EFI_SUCCESS;\r
242}\r
243\r
244EFI_STATUS\r
245EFIAPI\r
246OpteeCloseSession (\r
429309e0 247 IN UINT32 Session\r
a0f01e8a
SG
248 )\r
249{\r
429309e0 250 OPTEE_MESSAGE_ARG *MessageArg;\r
a0f01e8a
SG
251\r
252 MessageArg = NULL;\r
253\r
254 if (OpteeSharedMemoryInformation.Base == 0) {\r
255 DEBUG ((DEBUG_WARN, "OP-TEE not initialized\n"));\r
256 return EFI_NOT_STARTED;\r
257 }\r
258\r
259 MessageArg = (OPTEE_MESSAGE_ARG *)OpteeSharedMemoryInformation.Base;\r
260 ZeroMem (MessageArg, sizeof (OPTEE_MESSAGE_ARG));\r
261\r
262 MessageArg->Command = OPTEE_MESSAGE_COMMAND_CLOSE_SESSION;\r
263 MessageArg->Session = Session;\r
264\r
e40f8efb 265 OpteeCallWithArg ((UINTN)MessageArg);\r
a0f01e8a
SG
266\r
267 return EFI_SUCCESS;\r
268}\r
269\r
270STATIC\r
271EFI_STATUS\r
272OpteeToMessageParam (\r
429309e0
MK
273 OUT OPTEE_MESSAGE_PARAM *MessageParams,\r
274 IN UINT32 NumParams,\r
275 IN OPTEE_MESSAGE_PARAM *InParams\r
a0f01e8a
SG
276 )\r
277{\r
429309e0
MK
278 UINT32 Idx;\r
279 UINTN ParamSharedMemoryAddress;\r
280 UINTN SharedMemorySize;\r
281 UINTN Size;\r
a0f01e8a
SG
282\r
283 Size = (sizeof (OPTEE_MESSAGE_ARG) + sizeof (UINT64) - 1) &\r
429309e0 284 ~(sizeof (UINT64) - 1);\r
a0f01e8a 285 ParamSharedMemoryAddress = OpteeSharedMemoryInformation.Base + Size;\r
429309e0 286 SharedMemorySize = OpteeSharedMemoryInformation.Size - Size;\r
a0f01e8a
SG
287\r
288 for (Idx = 0; Idx < NumParams; Idx++) {\r
429309e0
MK
289 CONST OPTEE_MESSAGE_PARAM *InParam;\r
290 OPTEE_MESSAGE_PARAM *MessageParam;\r
291 UINT32 Attribute;\r
a0f01e8a 292\r
429309e0 293 InParam = InParams + Idx;\r
a0f01e8a 294 MessageParam = MessageParams + Idx;\r
429309e0 295 Attribute = InParam->Attribute & OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK;\r
a0f01e8a
SG
296\r
297 switch (Attribute) {\r
429309e0
MK
298 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE:\r
299 MessageParam->Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE;\r
300 ZeroMem (&MessageParam->Union, sizeof (MessageParam->Union));\r
301 break;\r
a0f01e8a 302\r
429309e0
MK
303 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT:\r
304 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT:\r
305 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT:\r
306 MessageParam->Attribute = Attribute;\r
307 MessageParam->Union.Value.A = InParam->Union.Value.A;\r
308 MessageParam->Union.Value.B = InParam->Union.Value.B;\r
309 MessageParam->Union.Value.C = InParam->Union.Value.C;\r
310 break;\r
a0f01e8a 311\r
429309e0
MK
312 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT:\r
313 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT:\r
314 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT:\r
315 MessageParam->Attribute = Attribute;\r
316\r
317 if (InParam->Union.Memory.Size > SharedMemorySize) {\r
318 return EFI_OUT_OF_RESOURCES;\r
319 }\r
320\r
321 CopyMem (\r
322 (VOID *)ParamSharedMemoryAddress,\r
323 (VOID *)(UINTN)InParam->Union.Memory.BufferAddress,\r
324 InParam->Union.Memory.Size\r
325 );\r
326 MessageParam->Union.Memory.BufferAddress = (UINT64)ParamSharedMemoryAddress;\r
327 MessageParam->Union.Memory.Size = InParam->Union.Memory.Size;\r
328\r
329 Size = (InParam->Union.Memory.Size + sizeof (UINT64) - 1) &\r
330 ~(sizeof (UINT64) - 1);\r
331 ParamSharedMemoryAddress += Size;\r
332 SharedMemorySize -= Size;\r
333 break;\r
a0f01e8a 334\r
429309e0
MK
335 default:\r
336 return EFI_INVALID_PARAMETER;\r
a0f01e8a
SG
337 }\r
338 }\r
339\r
340 return EFI_SUCCESS;\r
341}\r
342\r
343STATIC\r
344EFI_STATUS\r
345OpteeFromMessageParam (\r
429309e0
MK
346 OUT OPTEE_MESSAGE_PARAM *OutParams,\r
347 IN UINT32 NumParams,\r
348 IN OPTEE_MESSAGE_PARAM *MessageParams\r
a0f01e8a
SG
349 )\r
350{\r
429309e0 351 UINT32 Idx;\r
a0f01e8a
SG
352\r
353 for (Idx = 0; Idx < NumParams; Idx++) {\r
429309e0
MK
354 OPTEE_MESSAGE_PARAM *OutParam;\r
355 CONST OPTEE_MESSAGE_PARAM *MessageParam;\r
356 UINT32 Attribute;\r
a0f01e8a 357\r
429309e0 358 OutParam = OutParams + Idx;\r
a0f01e8a 359 MessageParam = MessageParams + Idx;\r
429309e0 360 Attribute = MessageParam->Attribute & OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK;\r
a0f01e8a
SG
361\r
362 switch (Attribute) {\r
429309e0
MK
363 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE:\r
364 OutParam->Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE;\r
365 ZeroMem (&OutParam->Union, sizeof (OutParam->Union));\r
366 break;\r
a0f01e8a 367\r
429309e0
MK
368 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT:\r
369 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT:\r
370 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT:\r
371 OutParam->Attribute = Attribute;\r
372 OutParam->Union.Value.A = MessageParam->Union.Value.A;\r
373 OutParam->Union.Value.B = MessageParam->Union.Value.B;\r
374 OutParam->Union.Value.C = MessageParam->Union.Value.C;\r
375 break;\r
a0f01e8a 376\r
429309e0
MK
377 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT:\r
378 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT:\r
379 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT:\r
380 OutParam->Attribute = Attribute;\r
381\r
382 if (MessageParam->Union.Memory.Size > OutParam->Union.Memory.Size) {\r
383 return EFI_BAD_BUFFER_SIZE;\r
384 }\r
385\r
386 CopyMem (\r
387 (VOID *)(UINTN)OutParam->Union.Memory.BufferAddress,\r
388 (VOID *)(UINTN)MessageParam->Union.Memory.BufferAddress,\r
389 MessageParam->Union.Memory.Size\r
390 );\r
391 OutParam->Union.Memory.Size = MessageParam->Union.Memory.Size;\r
392 break;\r
a0f01e8a 393\r
429309e0
MK
394 default:\r
395 return EFI_INVALID_PARAMETER;\r
a0f01e8a
SG
396 }\r
397 }\r
398\r
399 return EFI_SUCCESS;\r
400}\r
401\r
402EFI_STATUS\r
403EFIAPI\r
404OpteeInvokeFunction (\r
429309e0 405 IN OUT OPTEE_INVOKE_FUNCTION_ARG *InvokeFunctionArg\r
a0f01e8a
SG
406 )\r
407{\r
429309e0
MK
408 EFI_STATUS Status;\r
409 OPTEE_MESSAGE_ARG *MessageArg;\r
a0f01e8a
SG
410\r
411 MessageArg = NULL;\r
412\r
413 if (OpteeSharedMemoryInformation.Base == 0) {\r
414 DEBUG ((DEBUG_WARN, "OP-TEE not initialized\n"));\r
415 return EFI_NOT_STARTED;\r
416 }\r
417\r
418 MessageArg = (OPTEE_MESSAGE_ARG *)OpteeSharedMemoryInformation.Base;\r
419 ZeroMem (MessageArg, sizeof (OPTEE_MESSAGE_ARG));\r
420\r
429309e0 421 MessageArg->Command = OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION;\r
a0f01e8a 422 MessageArg->Function = InvokeFunctionArg->Function;\r
429309e0 423 MessageArg->Session = InvokeFunctionArg->Session;\r
a0f01e8a
SG
424\r
425 Status = OpteeToMessageParam (\r
426 MessageArg->Params,\r
427 OPTEE_MAX_CALL_PARAMS,\r
428 InvokeFunctionArg->Params\r
429 );\r
430 if (Status) {\r
431 return Status;\r
432 }\r
433\r
434 MessageArg->NumParams = OPTEE_MAX_CALL_PARAMS;\r
435\r
d61b2e28 436 if (OpteeCallWithArg ((UINTN)MessageArg) != 0) {\r
429309e0 437 MessageArg->Return = OPTEE_ERROR_COMMUNICATION;\r
a0f01e8a
SG
438 MessageArg->ReturnOrigin = OPTEE_ORIGIN_COMMUNICATION;\r
439 }\r
440\r
441 if (OpteeFromMessageParam (\r
442 InvokeFunctionArg->Params,\r
443 OPTEE_MAX_CALL_PARAMS,\r
444 MessageArg->Params\r
429309e0
MK
445 ) != 0)\r
446 {\r
447 MessageArg->Return = OPTEE_ERROR_COMMUNICATION;\r
a0f01e8a
SG
448 MessageArg->ReturnOrigin = OPTEE_ORIGIN_COMMUNICATION;\r
449 }\r
450\r
429309e0 451 InvokeFunctionArg->Return = MessageArg->Return;\r
a0f01e8a
SG
452 InvokeFunctionArg->ReturnOrigin = MessageArg->ReturnOrigin;\r
453\r
454 return EFI_SUCCESS;\r
455}\r