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>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/ArmMmuLib.h>
12 #include <Library/ArmSmcLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/BaseLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/OpteeLib.h>
18 #include <IndustryStandard/ArmStdSmc.h>
22 STATIC OPTEE_SHARED_MEMORY_INFORMATION OpteeSharedMemoryInformation
= { 0 };
25 Check for OP-TEE presence.
33 ARM_SMC_ARGS ArmSmcArgs
;
35 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
36 // Send a Trusted OS Calls UID command
37 ArmSmcArgs
.Arg0
= ARM_SMC_ID_TOS_UID
;
38 ArmCallSmc (&ArmSmcArgs
);
40 if ((ArmSmcArgs
.Arg0
== OPTEE_OS_UID0
) &&
41 (ArmSmcArgs
.Arg1
== OPTEE_OS_UID1
) &&
42 (ArmSmcArgs
.Arg2
== OPTEE_OS_UID2
) &&
43 (ArmSmcArgs
.Arg3
== OPTEE_OS_UID3
)) {
52 OpteeSharedMemoryRemap (
56 ARM_SMC_ARGS ArmSmcArgs
;
57 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
58 EFI_PHYSICAL_ADDRESS Start
;
59 EFI_PHYSICAL_ADDRESS End
;
63 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
64 ArmSmcArgs
.Arg0
= OPTEE_SMC_GET_SHARED_MEMORY_CONFIG
;
66 ArmCallSmc (&ArmSmcArgs
);
67 if (ArmSmcArgs
.Arg0
!= OPTEE_SMC_RETURN_OK
) {
68 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory not supported\n"));
69 return EFI_UNSUPPORTED
;
72 if (ArmSmcArgs
.Arg3
!= OPTEE_SMC_SHARED_MEMORY_CACHED
) {
73 DEBUG ((DEBUG_WARN
, "OP-TEE: Only normal cached shared memory supported\n"));
74 return EFI_UNSUPPORTED
;
77 Start
= (ArmSmcArgs
.Arg1
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
78 End
= (ArmSmcArgs
.Arg1
+ ArmSmcArgs
.Arg2
) & ~(SIZE_4KB
- 1);
79 PhysicalAddress
= Start
;
82 if (Size
< SIZE_4KB
) {
83 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory too small\n"));
84 return EFI_BUFFER_TOO_SMALL
;
87 Status
= ArmSetMemoryAttributes (PhysicalAddress
, Size
, EFI_MEMORY_WB
);
88 if (EFI_ERROR (Status
)) {
92 OpteeSharedMemoryInformation
.Base
= (UINTN
)PhysicalAddress
;
93 OpteeSharedMemoryInformation
.Size
= Size
;
106 if (!IsOpteePresent ()) {
107 DEBUG ((DEBUG_WARN
, "OP-TEE not present\n"));
108 return EFI_UNSUPPORTED
;
111 Status
= OpteeSharedMemoryRemap ();
112 if (EFI_ERROR (Status
)) {
113 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory remap failed\n"));
122 IsOpteeSmcReturnRpc (
126 return (Return
!= OPTEE_SMC_RETURN_UNKNOWN_FUNCTION
) &&
127 ((Return
& OPTEE_SMC_RETURN_RPC_PREFIX_MASK
) ==
128 OPTEE_SMC_RETURN_RPC_PREFIX
);
132 Does Standard SMC to OP-TEE in secure world.
134 @param[in] PhysicalArg Physical address of message to pass to secure world
136 @return 0 on success, secure world return code otherwise
142 IN UINT64 PhysicalArg
145 ARM_SMC_ARGS ArmSmcArgs
;
147 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
148 ArmSmcArgs
.Arg0
= OPTEE_SMC_CALL_WITH_ARG
;
149 ArmSmcArgs
.Arg1
= (UINT32
)(PhysicalArg
>> 32);
150 ArmSmcArgs
.Arg2
= (UINT32
)PhysicalArg
;
153 ArmCallSmc (&ArmSmcArgs
);
155 if (IsOpteeSmcReturnRpc (ArmSmcArgs
.Arg0
)) {
156 switch (ArmSmcArgs
.Arg0
) {
157 case OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT
:
159 // A foreign interrupt was raised while secure world was
160 // executing, since they are handled in UEFI a dummy RPC is
161 // performed to let UEFI take the interrupt through the normal
167 // Do nothing in case RPC is not implemented.
171 ArmSmcArgs
.Arg0
= OPTEE_SMC_RETURN_FROM_RPC
;
177 return ArmSmcArgs
.Arg0
;
182 EfiGuidToRfc4122Uuid (
183 OUT RFC4122_UUID
*Rfc4122Uuid
,
187 Rfc4122Uuid
->Data1
= SwapBytes32 (Guid
->Data1
);
188 Rfc4122Uuid
->Data2
= SwapBytes16 (Guid
->Data2
);
189 Rfc4122Uuid
->Data3
= SwapBytes16 (Guid
->Data3
);
190 CopyMem (Rfc4122Uuid
->Data4
, Guid
->Data4
, sizeof (Rfc4122Uuid
->Data4
));
196 IN OUT OPTEE_OPEN_SESSION_ARG
*OpenSessionArg
199 OPTEE_MESSAGE_ARG
*MessageArg
;
203 if (OpteeSharedMemoryInformation
.Base
== 0) {
204 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
205 return EFI_NOT_STARTED
;
208 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
209 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
211 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_OPEN_SESSION
;
214 // Initialize and add the meta parameters needed when opening a
217 MessageArg
->Params
[0].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
218 OPTEE_MESSAGE_ATTRIBUTE_META
;
219 MessageArg
->Params
[1].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
220 OPTEE_MESSAGE_ATTRIBUTE_META
;
221 EfiGuidToRfc4122Uuid (
222 (RFC4122_UUID
*)&MessageArg
->Params
[0].Union
.Value
,
223 &OpenSessionArg
->Uuid
225 ZeroMem (&MessageArg
->Params
[1].Union
.Value
, sizeof (EFI_GUID
));
226 MessageArg
->Params
[1].Union
.Value
.C
= OPTEE_LOGIN_PUBLIC
;
228 MessageArg
->NumParams
= 2;
230 if (OpteeCallWithArg ((UINTN
)MessageArg
)) {
231 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
232 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
235 OpenSessionArg
->Session
= MessageArg
->Session
;
236 OpenSessionArg
->Return
= MessageArg
->Return
;
237 OpenSessionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;
248 OPTEE_MESSAGE_ARG
*MessageArg
;
252 if (OpteeSharedMemoryInformation
.Base
== 0) {
253 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
254 return EFI_NOT_STARTED
;
257 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
258 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
260 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_CLOSE_SESSION
;
261 MessageArg
->Session
= Session
;
263 OpteeCallWithArg ((UINTN
)MessageArg
);
270 OpteeToMessageParam (
271 OUT OPTEE_MESSAGE_PARAM
*MessageParams
,
273 IN OPTEE_MESSAGE_PARAM
*InParams
277 UINTN ParamSharedMemoryAddress
;
278 UINTN SharedMemorySize
;
281 Size
= (sizeof (OPTEE_MESSAGE_ARG
) + sizeof (UINT64
) - 1) &
282 ~(sizeof (UINT64
) - 1);
283 ParamSharedMemoryAddress
= OpteeSharedMemoryInformation
.Base
+ Size
;
284 SharedMemorySize
= OpteeSharedMemoryInformation
.Size
- Size
;
286 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
287 CONST OPTEE_MESSAGE_PARAM
*InParam
;
288 OPTEE_MESSAGE_PARAM
*MessageParam
;
291 InParam
= InParams
+ Idx
;
292 MessageParam
= MessageParams
+ Idx
;
293 Attribute
= InParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
296 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
297 MessageParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
298 ZeroMem (&MessageParam
->Union
, sizeof (MessageParam
->Union
));
301 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
302 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
303 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
304 MessageParam
->Attribute
= Attribute
;
305 MessageParam
->Union
.Value
.A
= InParam
->Union
.Value
.A
;
306 MessageParam
->Union
.Value
.B
= InParam
->Union
.Value
.B
;
307 MessageParam
->Union
.Value
.C
= InParam
->Union
.Value
.C
;
310 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
311 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
312 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
313 MessageParam
->Attribute
= Attribute
;
315 if (InParam
->Union
.Memory
.Size
> SharedMemorySize
) {
316 return EFI_OUT_OF_RESOURCES
;
320 (VOID
*)ParamSharedMemoryAddress
,
321 (VOID
*)(UINTN
)InParam
->Union
.Memory
.BufferAddress
,
322 InParam
->Union
.Memory
.Size
324 MessageParam
->Union
.Memory
.BufferAddress
= (UINT64
)ParamSharedMemoryAddress
;
325 MessageParam
->Union
.Memory
.Size
= InParam
->Union
.Memory
.Size
;
327 Size
= (InParam
->Union
.Memory
.Size
+ sizeof (UINT64
) - 1) &
328 ~(sizeof (UINT64
) - 1);
329 ParamSharedMemoryAddress
+= Size
;
330 SharedMemorySize
-= Size
;
334 return EFI_INVALID_PARAMETER
;
343 OpteeFromMessageParam (
344 OUT OPTEE_MESSAGE_PARAM
*OutParams
,
346 IN OPTEE_MESSAGE_PARAM
*MessageParams
351 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
352 OPTEE_MESSAGE_PARAM
*OutParam
;
353 CONST OPTEE_MESSAGE_PARAM
*MessageParam
;
356 OutParam
= OutParams
+ Idx
;
357 MessageParam
= MessageParams
+ Idx
;
358 Attribute
= MessageParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
361 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
362 OutParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
363 ZeroMem (&OutParam
->Union
, sizeof (OutParam
->Union
));
366 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
367 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
368 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
369 OutParam
->Attribute
= Attribute
;
370 OutParam
->Union
.Value
.A
= MessageParam
->Union
.Value
.A
;
371 OutParam
->Union
.Value
.B
= MessageParam
->Union
.Value
.B
;
372 OutParam
->Union
.Value
.C
= MessageParam
->Union
.Value
.C
;
375 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
376 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
377 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
378 OutParam
->Attribute
= Attribute
;
380 if (MessageParam
->Union
.Memory
.Size
> OutParam
->Union
.Memory
.Size
) {
381 return EFI_BAD_BUFFER_SIZE
;
385 (VOID
*)(UINTN
)OutParam
->Union
.Memory
.BufferAddress
,
386 (VOID
*)(UINTN
)MessageParam
->Union
.Memory
.BufferAddress
,
387 MessageParam
->Union
.Memory
.Size
389 OutParam
->Union
.Memory
.Size
= MessageParam
->Union
.Memory
.Size
;
393 return EFI_INVALID_PARAMETER
;
402 OpteeInvokeFunction (
403 IN OUT OPTEE_INVOKE_FUNCTION_ARG
*InvokeFunctionArg
407 OPTEE_MESSAGE_ARG
*MessageArg
;
411 if (OpteeSharedMemoryInformation
.Base
== 0) {
412 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
413 return EFI_NOT_STARTED
;
416 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
417 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
419 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION
;
420 MessageArg
->Function
= InvokeFunctionArg
->Function
;
421 MessageArg
->Session
= InvokeFunctionArg
->Session
;
423 Status
= OpteeToMessageParam (
425 OPTEE_MAX_CALL_PARAMS
,
426 InvokeFunctionArg
->Params
432 MessageArg
->NumParams
= OPTEE_MAX_CALL_PARAMS
;
434 if (OpteeCallWithArg ((UINTN
)MessageArg
)) {
435 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
436 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
439 if (OpteeFromMessageParam (
440 InvokeFunctionArg
->Params
,
441 OPTEE_MAX_CALL_PARAMS
,
444 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
445 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
448 InvokeFunctionArg
->Return
= MessageArg
->Return
;
449 InvokeFunctionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;