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