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