2 Api's to communicate with OP-TEE OS (Trusted OS based on ARM TrustZone) via
5 Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
6 Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/ArmMmuLib.h>
13 #include <Library/ArmSmcLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/BaseLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/OpteeLib.h>
19 #include <IndustryStandard/ArmStdSmc.h>
23 STATIC OPTEE_SHARED_MEMORY_INFORMATION OpteeSharedMemoryInformation
= { 0 };
26 Check for OP-TEE presence.
34 ARM_SMC_ARGS ArmSmcArgs
;
36 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
37 // Send a Trusted OS Calls UID command
38 ArmSmcArgs
.Arg0
= ARM_SMC_ID_TOS_UID
;
39 ArmCallSmc (&ArmSmcArgs
);
41 if ((ArmSmcArgs
.Arg0
== OPTEE_OS_UID0
) &&
42 (ArmSmcArgs
.Arg1
== OPTEE_OS_UID1
) &&
43 (ArmSmcArgs
.Arg2
== OPTEE_OS_UID2
) &&
44 (ArmSmcArgs
.Arg3
== OPTEE_OS_UID3
)) {
53 OpteeSharedMemoryRemap (
57 ARM_SMC_ARGS ArmSmcArgs
;
58 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
59 EFI_PHYSICAL_ADDRESS Start
;
60 EFI_PHYSICAL_ADDRESS End
;
64 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
65 ArmSmcArgs
.Arg0
= OPTEE_SMC_GET_SHARED_MEMORY_CONFIG
;
67 ArmCallSmc (&ArmSmcArgs
);
68 if (ArmSmcArgs
.Arg0
!= OPTEE_SMC_RETURN_OK
) {
69 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory not supported\n"));
70 return EFI_UNSUPPORTED
;
73 if (ArmSmcArgs
.Arg3
!= OPTEE_SMC_SHARED_MEMORY_CACHED
) {
74 DEBUG ((DEBUG_WARN
, "OP-TEE: Only normal cached shared memory supported\n"));
75 return EFI_UNSUPPORTED
;
78 Start
= (ArmSmcArgs
.Arg1
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
79 End
= (ArmSmcArgs
.Arg1
+ ArmSmcArgs
.Arg2
) & ~(SIZE_4KB
- 1);
80 PhysicalAddress
= Start
;
83 if (Size
< SIZE_4KB
) {
84 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory too small\n"));
85 return EFI_BUFFER_TOO_SMALL
;
88 Status
= ArmSetMemoryAttributes (PhysicalAddress
, Size
, EFI_MEMORY_WB
);
89 if (EFI_ERROR (Status
)) {
93 OpteeSharedMemoryInformation
.Base
= (UINTN
)PhysicalAddress
;
94 OpteeSharedMemoryInformation
.Size
= Size
;
107 if (!IsOpteePresent ()) {
108 DEBUG ((DEBUG_WARN
, "OP-TEE not present\n"));
109 return EFI_UNSUPPORTED
;
112 Status
= OpteeSharedMemoryRemap ();
113 if (EFI_ERROR (Status
)) {
114 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory remap failed\n"));
123 IsOpteeSmcReturnRpc (
127 return (Return
!= OPTEE_SMC_RETURN_UNKNOWN_FUNCTION
) &&
128 ((Return
& OPTEE_SMC_RETURN_RPC_PREFIX_MASK
) ==
129 OPTEE_SMC_RETURN_RPC_PREFIX
);
133 Does Standard SMC to OP-TEE in secure world.
135 @param[in] PhysicalArg Physical address of message to pass to secure world
137 @return 0 on success, secure world return code otherwise
143 IN UINT64 PhysicalArg
146 ARM_SMC_ARGS ArmSmcArgs
;
148 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
149 ArmSmcArgs
.Arg0
= OPTEE_SMC_CALL_WITH_ARG
;
150 ArmSmcArgs
.Arg1
= (UINT32
)(PhysicalArg
>> 32);
151 ArmSmcArgs
.Arg2
= (UINT32
)PhysicalArg
;
154 ArmCallSmc (&ArmSmcArgs
);
156 if (IsOpteeSmcReturnRpc (ArmSmcArgs
.Arg0
)) {
157 switch (ArmSmcArgs
.Arg0
) {
158 case OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT
:
160 // A foreign interrupt was raised while secure world was
161 // executing, since they are handled in UEFI a dummy RPC is
162 // performed to let UEFI take the interrupt through the normal
168 // Do nothing in case RPC is not implemented.
172 ArmSmcArgs
.Arg0
= OPTEE_SMC_RETURN_FROM_RPC
;
178 return ArmSmcArgs
.Arg0
;
183 EfiGuidToRfc4122Uuid (
184 OUT RFC4122_UUID
*Rfc4122Uuid
,
188 Rfc4122Uuid
->Data1
= SwapBytes32 (Guid
->Data1
);
189 Rfc4122Uuid
->Data2
= SwapBytes16 (Guid
->Data2
);
190 Rfc4122Uuid
->Data3
= SwapBytes16 (Guid
->Data3
);
191 CopyMem (Rfc4122Uuid
->Data4
, Guid
->Data4
, sizeof (Rfc4122Uuid
->Data4
));
197 IN OUT OPTEE_OPEN_SESSION_ARG
*OpenSessionArg
200 OPTEE_MESSAGE_ARG
*MessageArg
;
204 if (OpteeSharedMemoryInformation
.Base
== 0) {
205 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
206 return EFI_NOT_STARTED
;
209 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
210 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
212 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_OPEN_SESSION
;
215 // Initialize and add the meta parameters needed when opening a
218 MessageArg
->Params
[0].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
219 OPTEE_MESSAGE_ATTRIBUTE_META
;
220 MessageArg
->Params
[1].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
221 OPTEE_MESSAGE_ATTRIBUTE_META
;
222 EfiGuidToRfc4122Uuid (
223 (RFC4122_UUID
*)&MessageArg
->Params
[0].Union
.Value
,
224 &OpenSessionArg
->Uuid
226 ZeroMem (&MessageArg
->Params
[1].Union
.Value
, sizeof (EFI_GUID
));
227 MessageArg
->Params
[1].Union
.Value
.C
= OPTEE_LOGIN_PUBLIC
;
229 MessageArg
->NumParams
= 2;
231 if (OpteeCallWithArg ((UINTN
)MessageArg
) != 0) {
232 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
233 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
236 OpenSessionArg
->Session
= MessageArg
->Session
;
237 OpenSessionArg
->Return
= MessageArg
->Return
;
238 OpenSessionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;
249 OPTEE_MESSAGE_ARG
*MessageArg
;
253 if (OpteeSharedMemoryInformation
.Base
== 0) {
254 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
255 return EFI_NOT_STARTED
;
258 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
259 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
261 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_CLOSE_SESSION
;
262 MessageArg
->Session
= Session
;
264 OpteeCallWithArg ((UINTN
)MessageArg
);
271 OpteeToMessageParam (
272 OUT OPTEE_MESSAGE_PARAM
*MessageParams
,
274 IN OPTEE_MESSAGE_PARAM
*InParams
278 UINTN ParamSharedMemoryAddress
;
279 UINTN SharedMemorySize
;
282 Size
= (sizeof (OPTEE_MESSAGE_ARG
) + sizeof (UINT64
) - 1) &
283 ~(sizeof (UINT64
) - 1);
284 ParamSharedMemoryAddress
= OpteeSharedMemoryInformation
.Base
+ Size
;
285 SharedMemorySize
= OpteeSharedMemoryInformation
.Size
- Size
;
287 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
288 CONST OPTEE_MESSAGE_PARAM
*InParam
;
289 OPTEE_MESSAGE_PARAM
*MessageParam
;
292 InParam
= InParams
+ Idx
;
293 MessageParam
= MessageParams
+ Idx
;
294 Attribute
= InParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
297 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
298 MessageParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
299 ZeroMem (&MessageParam
->Union
, sizeof (MessageParam
->Union
));
302 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
303 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
304 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
305 MessageParam
->Attribute
= Attribute
;
306 MessageParam
->Union
.Value
.A
= InParam
->Union
.Value
.A
;
307 MessageParam
->Union
.Value
.B
= InParam
->Union
.Value
.B
;
308 MessageParam
->Union
.Value
.C
= InParam
->Union
.Value
.C
;
311 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
312 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
313 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
314 MessageParam
->Attribute
= Attribute
;
316 if (InParam
->Union
.Memory
.Size
> SharedMemorySize
) {
317 return EFI_OUT_OF_RESOURCES
;
321 (VOID
*)ParamSharedMemoryAddress
,
322 (VOID
*)(UINTN
)InParam
->Union
.Memory
.BufferAddress
,
323 InParam
->Union
.Memory
.Size
325 MessageParam
->Union
.Memory
.BufferAddress
= (UINT64
)ParamSharedMemoryAddress
;
326 MessageParam
->Union
.Memory
.Size
= InParam
->Union
.Memory
.Size
;
328 Size
= (InParam
->Union
.Memory
.Size
+ sizeof (UINT64
) - 1) &
329 ~(sizeof (UINT64
) - 1);
330 ParamSharedMemoryAddress
+= Size
;
331 SharedMemorySize
-= Size
;
335 return EFI_INVALID_PARAMETER
;
344 OpteeFromMessageParam (
345 OUT OPTEE_MESSAGE_PARAM
*OutParams
,
347 IN OPTEE_MESSAGE_PARAM
*MessageParams
352 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
353 OPTEE_MESSAGE_PARAM
*OutParam
;
354 CONST OPTEE_MESSAGE_PARAM
*MessageParam
;
357 OutParam
= OutParams
+ Idx
;
358 MessageParam
= MessageParams
+ Idx
;
359 Attribute
= MessageParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
362 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
363 OutParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
364 ZeroMem (&OutParam
->Union
, sizeof (OutParam
->Union
));
367 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
368 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
369 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
370 OutParam
->Attribute
= Attribute
;
371 OutParam
->Union
.Value
.A
= MessageParam
->Union
.Value
.A
;
372 OutParam
->Union
.Value
.B
= MessageParam
->Union
.Value
.B
;
373 OutParam
->Union
.Value
.C
= MessageParam
->Union
.Value
.C
;
376 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
377 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
378 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
379 OutParam
->Attribute
= Attribute
;
381 if (MessageParam
->Union
.Memory
.Size
> OutParam
->Union
.Memory
.Size
) {
382 return EFI_BAD_BUFFER_SIZE
;
386 (VOID
*)(UINTN
)OutParam
->Union
.Memory
.BufferAddress
,
387 (VOID
*)(UINTN
)MessageParam
->Union
.Memory
.BufferAddress
,
388 MessageParam
->Union
.Memory
.Size
390 OutParam
->Union
.Memory
.Size
= MessageParam
->Union
.Memory
.Size
;
394 return EFI_INVALID_PARAMETER
;
403 OpteeInvokeFunction (
404 IN OUT OPTEE_INVOKE_FUNCTION_ARG
*InvokeFunctionArg
408 OPTEE_MESSAGE_ARG
*MessageArg
;
412 if (OpteeSharedMemoryInformation
.Base
== 0) {
413 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
414 return EFI_NOT_STARTED
;
417 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
418 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
420 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION
;
421 MessageArg
->Function
= InvokeFunctionArg
->Function
;
422 MessageArg
->Session
= InvokeFunctionArg
->Session
;
424 Status
= OpteeToMessageParam (
426 OPTEE_MAX_CALL_PARAMS
,
427 InvokeFunctionArg
->Params
433 MessageArg
->NumParams
= OPTEE_MAX_CALL_PARAMS
;
435 if (OpteeCallWithArg ((UINTN
)MessageArg
) != 0) {
436 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
437 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
440 if (OpteeFromMessageParam (
441 InvokeFunctionArg
->Params
,
442 OPTEE_MAX_CALL_PARAMS
,
445 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
446 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
449 InvokeFunctionArg
->Return
= MessageArg
->Return
;
450 InvokeFunctionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;