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
))
54 OpteeSharedMemoryRemap (
58 ARM_SMC_ARGS ArmSmcArgs
;
59 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
60 EFI_PHYSICAL_ADDRESS Start
;
61 EFI_PHYSICAL_ADDRESS End
;
65 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
66 ArmSmcArgs
.Arg0
= OPTEE_SMC_GET_SHARED_MEMORY_CONFIG
;
68 ArmCallSmc (&ArmSmcArgs
);
69 if (ArmSmcArgs
.Arg0
!= OPTEE_SMC_RETURN_OK
) {
70 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory not supported\n"));
71 return EFI_UNSUPPORTED
;
74 if (ArmSmcArgs
.Arg3
!= OPTEE_SMC_SHARED_MEMORY_CACHED
) {
75 DEBUG ((DEBUG_WARN
, "OP-TEE: Only normal cached shared memory supported\n"));
76 return EFI_UNSUPPORTED
;
79 Start
= (ArmSmcArgs
.Arg1
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
80 End
= (ArmSmcArgs
.Arg1
+ ArmSmcArgs
.Arg2
) & ~(SIZE_4KB
- 1);
81 PhysicalAddress
= Start
;
84 if (Size
< SIZE_4KB
) {
85 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory too small\n"));
86 return EFI_BUFFER_TOO_SMALL
;
89 Status
= ArmSetMemoryAttributes (PhysicalAddress
, Size
, EFI_MEMORY_WB
);
90 if (EFI_ERROR (Status
)) {
94 OpteeSharedMemoryInformation
.Base
= (UINTN
)PhysicalAddress
;
95 OpteeSharedMemoryInformation
.Size
= Size
;
108 if (!IsOpteePresent ()) {
109 DEBUG ((DEBUG_WARN
, "OP-TEE not present\n"));
110 return EFI_UNSUPPORTED
;
113 Status
= OpteeSharedMemoryRemap ();
114 if (EFI_ERROR (Status
)) {
115 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory remap failed\n"));
124 IsOpteeSmcReturnRpc (
128 return (Return
!= OPTEE_SMC_RETURN_UNKNOWN_FUNCTION
) &&
129 ((Return
& OPTEE_SMC_RETURN_RPC_PREFIX_MASK
) ==
130 OPTEE_SMC_RETURN_RPC_PREFIX
);
134 Does Standard SMC to OP-TEE in secure world.
136 @param[in] PhysicalArg Physical address of message to pass to secure world
138 @return 0 on success, secure world return code otherwise
144 IN UINT64 PhysicalArg
147 ARM_SMC_ARGS ArmSmcArgs
;
149 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
150 ArmSmcArgs
.Arg0
= OPTEE_SMC_CALL_WITH_ARG
;
151 ArmSmcArgs
.Arg1
= (UINT32
)(PhysicalArg
>> 32);
152 ArmSmcArgs
.Arg2
= (UINT32
)PhysicalArg
;
155 ArmCallSmc (&ArmSmcArgs
);
157 if (IsOpteeSmcReturnRpc (ArmSmcArgs
.Arg0
)) {
158 switch (ArmSmcArgs
.Arg0
) {
159 case OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT
:
161 // A foreign interrupt was raised while secure world was
162 // executing, since they are handled in UEFI a dummy RPC is
163 // performed to let UEFI take the interrupt through the normal
169 // Do nothing in case RPC is not implemented.
173 ArmSmcArgs
.Arg0
= OPTEE_SMC_RETURN_FROM_RPC
;
179 return ArmSmcArgs
.Arg0
;
184 EfiGuidToRfc4122Uuid (
185 OUT RFC4122_UUID
*Rfc4122Uuid
,
189 Rfc4122Uuid
->Data1
= SwapBytes32 (Guid
->Data1
);
190 Rfc4122Uuid
->Data2
= SwapBytes16 (Guid
->Data2
);
191 Rfc4122Uuid
->Data3
= SwapBytes16 (Guid
->Data3
);
192 CopyMem (Rfc4122Uuid
->Data4
, Guid
->Data4
, sizeof (Rfc4122Uuid
->Data4
));
198 IN OUT OPTEE_OPEN_SESSION_ARG
*OpenSessionArg
201 OPTEE_MESSAGE_ARG
*MessageArg
;
205 if (OpteeSharedMemoryInformation
.Base
== 0) {
206 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
207 return EFI_NOT_STARTED
;
210 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
211 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
213 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_OPEN_SESSION
;
216 // Initialize and add the meta parameters needed when opening a
219 MessageArg
->Params
[0].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
220 OPTEE_MESSAGE_ATTRIBUTE_META
;
221 MessageArg
->Params
[1].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
222 OPTEE_MESSAGE_ATTRIBUTE_META
;
223 EfiGuidToRfc4122Uuid (
224 (RFC4122_UUID
*)&MessageArg
->Params
[0].Union
.Value
,
225 &OpenSessionArg
->Uuid
227 ZeroMem (&MessageArg
->Params
[1].Union
.Value
, sizeof (EFI_GUID
));
228 MessageArg
->Params
[1].Union
.Value
.C
= OPTEE_LOGIN_PUBLIC
;
230 MessageArg
->NumParams
= 2;
232 if (OpteeCallWithArg ((UINTN
)MessageArg
) != 0) {
233 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
234 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
237 OpenSessionArg
->Session
= MessageArg
->Session
;
238 OpenSessionArg
->Return
= MessageArg
->Return
;
239 OpenSessionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;
250 OPTEE_MESSAGE_ARG
*MessageArg
;
254 if (OpteeSharedMemoryInformation
.Base
== 0) {
255 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
256 return EFI_NOT_STARTED
;
259 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
260 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
262 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_CLOSE_SESSION
;
263 MessageArg
->Session
= Session
;
265 OpteeCallWithArg ((UINTN
)MessageArg
);
272 OpteeToMessageParam (
273 OUT OPTEE_MESSAGE_PARAM
*MessageParams
,
275 IN OPTEE_MESSAGE_PARAM
*InParams
279 UINTN ParamSharedMemoryAddress
;
280 UINTN SharedMemorySize
;
283 Size
= (sizeof (OPTEE_MESSAGE_ARG
) + sizeof (UINT64
) - 1) &
284 ~(sizeof (UINT64
) - 1);
285 ParamSharedMemoryAddress
= OpteeSharedMemoryInformation
.Base
+ Size
;
286 SharedMemorySize
= OpteeSharedMemoryInformation
.Size
- Size
;
288 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
289 CONST OPTEE_MESSAGE_PARAM
*InParam
;
290 OPTEE_MESSAGE_PARAM
*MessageParam
;
293 InParam
= InParams
+ Idx
;
294 MessageParam
= MessageParams
+ Idx
;
295 Attribute
= InParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
298 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
299 MessageParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
300 ZeroMem (&MessageParam
->Union
, sizeof (MessageParam
->Union
));
303 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
304 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
305 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
306 MessageParam
->Attribute
= Attribute
;
307 MessageParam
->Union
.Value
.A
= InParam
->Union
.Value
.A
;
308 MessageParam
->Union
.Value
.B
= InParam
->Union
.Value
.B
;
309 MessageParam
->Union
.Value
.C
= InParam
->Union
.Value
.C
;
312 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
313 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
314 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
315 MessageParam
->Attribute
= Attribute
;
317 if (InParam
->Union
.Memory
.Size
> SharedMemorySize
) {
318 return EFI_OUT_OF_RESOURCES
;
322 (VOID
*)ParamSharedMemoryAddress
,
323 (VOID
*)(UINTN
)InParam
->Union
.Memory
.BufferAddress
,
324 InParam
->Union
.Memory
.Size
326 MessageParam
->Union
.Memory
.BufferAddress
= (UINT64
)ParamSharedMemoryAddress
;
327 MessageParam
->Union
.Memory
.Size
= InParam
->Union
.Memory
.Size
;
329 Size
= (InParam
->Union
.Memory
.Size
+ sizeof (UINT64
) - 1) &
330 ~(sizeof (UINT64
) - 1);
331 ParamSharedMemoryAddress
+= Size
;
332 SharedMemorySize
-= Size
;
336 return EFI_INVALID_PARAMETER
;
345 OpteeFromMessageParam (
346 OUT OPTEE_MESSAGE_PARAM
*OutParams
,
348 IN OPTEE_MESSAGE_PARAM
*MessageParams
353 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
354 OPTEE_MESSAGE_PARAM
*OutParam
;
355 CONST OPTEE_MESSAGE_PARAM
*MessageParam
;
358 OutParam
= OutParams
+ Idx
;
359 MessageParam
= MessageParams
+ Idx
;
360 Attribute
= MessageParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
363 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
364 OutParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
365 ZeroMem (&OutParam
->Union
, sizeof (OutParam
->Union
));
368 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
369 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
370 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
371 OutParam
->Attribute
= Attribute
;
372 OutParam
->Union
.Value
.A
= MessageParam
->Union
.Value
.A
;
373 OutParam
->Union
.Value
.B
= MessageParam
->Union
.Value
.B
;
374 OutParam
->Union
.Value
.C
= MessageParam
->Union
.Value
.C
;
377 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
378 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
379 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
380 OutParam
->Attribute
= Attribute
;
382 if (MessageParam
->Union
.Memory
.Size
> OutParam
->Union
.Memory
.Size
) {
383 return EFI_BAD_BUFFER_SIZE
;
387 (VOID
*)(UINTN
)OutParam
->Union
.Memory
.BufferAddress
,
388 (VOID
*)(UINTN
)MessageParam
->Union
.Memory
.BufferAddress
,
389 MessageParam
->Union
.Memory
.Size
391 OutParam
->Union
.Memory
.Size
= MessageParam
->Union
.Memory
.Size
;
395 return EFI_INVALID_PARAMETER
;
404 OpteeInvokeFunction (
405 IN OUT OPTEE_INVOKE_FUNCTION_ARG
*InvokeFunctionArg
409 OPTEE_MESSAGE_ARG
*MessageArg
;
413 if (OpteeSharedMemoryInformation
.Base
== 0) {
414 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
415 return EFI_NOT_STARTED
;
418 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
419 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
421 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION
;
422 MessageArg
->Function
= InvokeFunctionArg
->Function
;
423 MessageArg
->Session
= InvokeFunctionArg
->Session
;
425 Status
= OpteeToMessageParam (
427 OPTEE_MAX_CALL_PARAMS
,
428 InvokeFunctionArg
->Params
434 MessageArg
->NumParams
= OPTEE_MAX_CALL_PARAMS
;
436 if (OpteeCallWithArg ((UINTN
)MessageArg
) != 0) {
437 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
438 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
441 if (OpteeFromMessageParam (
442 InvokeFunctionArg
->Params
,
443 OPTEE_MAX_CALL_PARAMS
,
447 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
448 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
451 InvokeFunctionArg
->Return
= MessageArg
->Return
;
452 InvokeFunctionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;