microsoft/mu_feature_ffa

Public

mirrored fromhttps://github.com/microsoft/mu_feature_ffaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
test_delay

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/ArmFfaLibEx/ArmFfaLibEx.c

941lines · modecode

1// SPDX-License-Identifier: BSD-3-Clause
2
3/*
4 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
5 * Copyright (c), Microsoft Corporation.
6 */
7
8#include <Uefi.h>
9#include <IndustryStandard/ArmFfaSvc.h>
10#include <IndustryStandard/ArmFfaPartInfo.h>
11#include <Library/BaseLib.h>
12#include <Library/DebugLib.h>
13#include <Library/ArmFfaLib.h>
14#include <Library/ArmSvcLib.h>
15#include <Library/ArmSmcLib.h>
16#include <Library/BaseMemoryLib.h>
17#include <Library/ArmFfaLibEx.h>
18#include <Library/PlatformFfaInterruptLib.h>
19
20extern UINT16 gPartId;
21
22/**
23 This function is used to prepare a GUID for FF-A.
24
25 The FF-A expects a GUID to be in a specific format. This function
26 manipulates the input Guid to be understood by the FF-A.
27
28 Note: This function is symmetric, i.e., calling it twice will return the
29 original GUID. Thus, it can be used to prepare and restore the GUID.
30
31 @param Guid - Supplies the pointer for original GUID. This is the one you
32 get from VS GUID creator.
33
34 @retval None.
35**/
36VOID
37FfaPrepareGuid (
38 IN OUT EFI_GUID *Guid
39 )
40{
41 UINT32 *Data32;
42 UINT16 *Data16;
43
44 if (Guid == NULL) {
45 return;
46 }
47
48 Data32 = (UINT32 *)Guid;
49 Data32[0] = SwapBytes32 (Data32[0]);
50 Data16 = (UINT16 *)&Data32[1];
51 Data16[0] = SwapBytes16 (Data16[0]);
52 Data16[1] = SwapBytes16 (Data16[1]);
53}
54
55STATIC
56VOID
57ArmCallSxc (
58 ARM_SXC_ARGS *Request,
59 ARM_SXC_ARGS *Response
60 )
61{
62 ARM_SXC_ARGS LocalParams;
63
64 CopyMem (&LocalParams, Request, sizeof (ARM_SXC_ARGS));
65
66 /*
67 * The ArmCallSxc function is a wrapper around the ffa_params structure
68 * which checks the current execution level and calls the appropriate
69 * conduit.
70 */
71 if (PcdGetBool (PcdFfaLibConduitSmc) == 1) {
72 ArmCallSmc ((ARM_SMC_ARGS *)&LocalParams);
73 } else {
74 ArmCallSvc ((ARM_SVC_ARGS *)&LocalParams);
75 }
76
77 CopyMem (Response, &LocalParams, sizeof (ARM_SXC_ARGS));
78}
79
80/*
81 * Unpacks the content of the ffa instruction Response into an ffa_direct_msg structure.
82 */
83STATIC
84VOID
85FfaUnpackDirectMessage (
86 ARM_SXC_ARGS *Response,
87 DIRECT_MSG_ARGS_EX *Message
88 )
89{
90 Message->FunctionId = Response->Arg0;
91 Message->SourceId = (Response->Arg1 >> 16);
92 Message->DestinationId = Response->Arg1;
93
94 if ((Message->FunctionId == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH32) ||
95 (Message->FunctionId == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH64))
96 {
97 Message->Arg0 = Response->Arg2;
98 Message->Arg1 = Response->Arg3;
99 Message->Arg2 = Response->Arg4;
100 Message->Arg3 = Response->Arg5;
101 Message->Arg4 = Response->Arg6;
102 Message->Arg5 = Response->Arg7;
103 } else {
104 CopyMem (&Message->ServiceGuid, &Response->Arg2, sizeof (EFI_GUID));
105 FfaPrepareGuid (&Message->ServiceGuid);
106 Message->Arg0 = Response->Arg4;
107 Message->Arg1 = Response->Arg5;
108 Message->Arg2 = Response->Arg6;
109 Message->Arg3 = Response->Arg7;
110 Message->Arg4 = Response->Arg8;
111 Message->Arg5 = Response->Arg9;
112 Message->Arg6 = Response->Arg10;
113 Message->Arg7 = Response->Arg11;
114 Message->Arg8 = Response->Arg12;
115 Message->Arg9 = Response->Arg13;
116 Message->Arg10 = Response->Arg14;
117 Message->Arg11 = Response->Arg15;
118 Message->Arg12 = Response->Arg16;
119 Message->Arg13 = Response->Arg17;
120 }
121}
122
123/*
124 * Packs the content of the ffa_direct_msg into a Request message.
125 */
126STATIC
127VOID
128FfaPackDirectMessage (
129 OUT ARM_SXC_ARGS *Request,
130 IN DIRECT_MSG_ARGS_EX *Message
131 )
132{
133 EFI_GUID ServiceGuid;
134
135 Request->Arg0 = Message->FunctionId;
136
137 /* NOTE: There is a DIRECT_RESP define in ffa_api_defines.h, this may need to be updated
138 * in the future if the defines differ, for now they are identical. */
139 Request->Arg1 = ((UINT32)Message->SourceId << 16) | Message->DestinationId;
140
141 if ((Message->FunctionId == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH32) ||
142 (Message->FunctionId == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH64) ||
143 (Message->FunctionId == ARM_FID_FFA_MSG_SEND_DIRECT_RESP_AARCH32) ||
144 (Message->FunctionId == ARM_FID_FFA_MSG_SEND_DIRECT_RESP_AARCH64))
145 {
146 Request->Arg2 = Message->Arg0;
147 Request->Arg3 = Message->Arg1;
148 Request->Arg4 = Message->Arg2;
149 Request->Arg5 = Message->Arg3;
150 Request->Arg6 = Message->Arg4;
151 Request->Arg7 = Message->Arg5;
152 } else {
153 CopyMem (&ServiceGuid, &Message->ServiceGuid, sizeof (EFI_GUID));
154 FfaPrepareGuid (&ServiceGuid);
155 CopyMem (&Request->Arg2, &ServiceGuid, sizeof (EFI_GUID));
156 Request->Arg4 = Message->Arg0;
157 Request->Arg5 = Message->Arg1;
158 Request->Arg6 = Message->Arg2;
159 Request->Arg7 = Message->Arg3;
160 Request->Arg8 = Message->Arg4;
161 Request->Arg9 = Message->Arg5;
162 Request->Arg10 = Message->Arg6;
163 Request->Arg11 = Message->Arg7;
164 Request->Arg12 = Message->Arg8;
165 Request->Arg13 = Message->Arg9;
166 Request->Arg14 = Message->Arg10;
167 Request->Arg15 = Message->Arg11;
168 Request->Arg16 = Message->Arg12;
169 Request->Arg17 = Message->Arg13;
170 }
171}
172
173/*
174 * The end of the interrupt handler is indicated by an FFA_MSG_WAIT call.
175 */
176STATIC
177VOID
178FfaReturnFromInterrupt (
179 ARM_SXC_ARGS *Result
180 )
181{
182 ARM_SXC_ARGS Request = { 0 };
183
184 Request.Arg0 = ARM_FID_FFA_WAIT;
185 ArmCallSxc (&Request, Result);
186}
187
188EFI_STATUS
189EFIAPI
190FfaMessageWait (
191 OUT DIRECT_MSG_ARGS_EX *Message
192 )
193{
194 ARM_SXC_ARGS Request = { 0 };
195 ARM_SXC_ARGS Result = { 0 };
196
197 Request.Arg0 = ARM_FID_FFA_WAIT;
198
199 ArmCallSxc (&Request, &Result);
200
201 while (Result.Arg0 == ARM_FID_FFA_INTERRUPT) {
202 SecurePartitionInterruptHandler ((UINT32)Result.Arg2);
203 FfaReturnFromInterrupt (&Result);
204 }
205
206 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
207 return FfaStatusToEfiStatus (Result.Arg2);
208 } else if ((Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH32) ||
209 (Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH64) ||
210 (Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ2))
211 {
212 FfaUnpackDirectMessage (&Result, Message);
213 } else {
214 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
215 *Message = (DIRECT_MSG_ARGS_EX) {
216 .FunctionId = Result.Arg0
217 };
218 }
219
220 return EFI_SUCCESS;
221}
222
223EFI_STATUS
224EFIAPI
225FfaMessageSendDirectReq2 (
226 IN UINT16 DestPartId,
227 IN EFI_GUID *ServiceGuid OPTIONAL,
228 IN OUT DIRECT_MSG_ARGS_EX *ImpDefArgs
229 )
230{
231 ARM_SXC_ARGS InputArgs = { 0 };
232 ARM_SXC_ARGS Result = { 0 };
233
234 ImpDefArgs->FunctionId = ARM_FID_FFA_MSG_SEND_DIRECT_REQ2;
235 ImpDefArgs->SourceId = gPartId;
236 ImpDefArgs->DestinationId = DestPartId;
237 if (ServiceGuid != NULL) {
238 CopyMem (&(ImpDefArgs->ServiceGuid), ServiceGuid, sizeof (EFI_GUID));
239 } else {
240 ZeroMem (&(ImpDefArgs->ServiceGuid), sizeof (EFI_GUID));
241 }
242
243 FfaPackDirectMessage (&InputArgs, ImpDefArgs);
244
245 ArmCallSxc (&InputArgs, &Result);
246
247 while (Result.Arg0 == ARM_FID_FFA_INTERRUPT) {
248 SecurePartitionInterruptHandler ((UINT32)Result.Arg2);
249 FfaReturnFromInterrupt (&Result);
250 }
251
252 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
253 return FfaStatusToEfiStatus (Result.Arg2);
254 } else if (Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_RESP2) {
255 FfaUnpackDirectMessage (&Result, ImpDefArgs);
256 } else {
257 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
258 *ImpDefArgs = (DIRECT_MSG_ARGS_EX) {
259 .FunctionId = Result.Arg0
260 };
261 }
262
263 return EFI_SUCCESS;
264}
265
266STATIC
267EFI_STATUS
268FfaMessageSendDirectResp (
269 IN UINT32 FunctionId,
270 IN DIRECT_MSG_ARGS_EX *Request,
271 OUT DIRECT_MSG_ARGS_EX *Response
272 )
273{
274 ARM_SXC_ARGS InputArgs = { 0 };
275 ARM_SXC_ARGS Result = { 0 };
276
277 Request->FunctionId = FunctionId;
278 FfaPackDirectMessage (&InputArgs, Request);
279
280 ArmCallSxc (&InputArgs, &Result);
281
282 while (Result.Arg0 == ARM_FID_FFA_INTERRUPT) {
283 SecurePartitionInterruptHandler ((UINT32)Result.Arg2);
284 FfaReturnFromInterrupt (&Result);
285 }
286
287 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
288 return FfaStatusToEfiStatus (Result.Arg2);
289 } else if ((Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH32) ||
290 (Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ_AARCH64) ||
291 (Result.Arg0 == ARM_FID_FFA_MSG_SEND_DIRECT_REQ2))
292 {
293 FfaUnpackDirectMessage (&Result, Response);
294 } else {
295 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
296 *Response = (DIRECT_MSG_ARGS_EX) {
297 .FunctionId = Result.Arg0
298 };
299 }
300
301 return EFI_SUCCESS;
302}
303
304EFI_STATUS
305EFIAPI
306FfaMessageSendDirectResp32 (
307 IN DIRECT_MSG_ARGS_EX *Request,
308 OUT DIRECT_MSG_ARGS_EX *Response
309 )
310{
311 return FfaMessageSendDirectResp (
312 ARM_FID_FFA_MSG_SEND_DIRECT_RESP_AARCH32,
313 Request,
314 Response
315 );
316}
317
318EFI_STATUS
319EFIAPI
320FfaMessageSendDirectResp64 (
321 IN DIRECT_MSG_ARGS_EX *Request,
322 OUT DIRECT_MSG_ARGS_EX *Response
323 )
324{
325 return FfaMessageSendDirectResp (
326 ARM_FID_FFA_MSG_SEND_DIRECT_RESP_AARCH64,
327 Request,
328 Response
329 );
330}
331
332EFI_STATUS
333EFIAPI
334FfaMessageSendDirectResp2 (
335 IN DIRECT_MSG_ARGS_EX *Request,
336 OUT DIRECT_MSG_ARGS_EX *Response
337 )
338{
339 return FfaMessageSendDirectResp (
340 ARM_FID_FFA_MSG_SEND_DIRECT_RESP2,
341 Request,
342 Response
343 );
344}
345
346EFI_STATUS
347EFIAPI
348FfaMemDonate (
349 UINT32 TotalLength,
350 UINT32 FragmentLength,
351 VOID *BufferAddr,
352 UINT32 PageCount,
353 UINT64 *Handle
354 )
355{
356 ARM_SXC_ARGS Request = { 0 };
357 ARM_SXC_ARGS Result = { 0 };
358
359 Request.Arg0 = (BufferAddr) ? ARM_FID_FFA_MEM_DONATE_AARCH64 : ARM_FID_FFA_MEM_DONATE_AARCH32;
360 Request.Arg1 = TotalLength;
361 Request.Arg2 = FragmentLength;
362 Request.Arg3 = (UINTN)BufferAddr;
363 Request.Arg4 = PageCount;
364
365 ArmCallSxc (&Request, &Result);
366
367 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
368 *Handle = 0U;
369 return FfaStatusToEfiStatus (Result.Arg2);
370 }
371
372 /*
373 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
374 * will use the default 32-bit version.
375 */
376 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
377 *Handle = ((UINT64)Result.Arg3 << 32) | Result.Arg2;
378 return EFI_SUCCESS;
379}
380
381EFI_STATUS
382EFIAPI
383FfaNotificationSet (
384 IN UINT16 DestinationId,
385 IN UINT64 Flags,
386 IN UINT64 NotificationBitmap
387 )
388{
389 ARM_SXC_ARGS Request = { 0 };
390 ARM_SXC_ARGS Result = { 0 };
391
392 Request.Arg0 = ARM_FID_FFA_NOTIFICATION_SET;
393 Request.Arg1 = ((UINT32)gPartId << 16) | DestinationId;
394 Request.Arg2 = Flags;
395 Request.Arg3 = (UINT32)NotificationBitmap;
396 Request.Arg4 = (UINT32)(NotificationBitmap >> 32);
397
398 ArmCallSxc (&Request, &Result);
399
400 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
401 return FfaStatusToEfiStatus (Result.Arg2);
402 }
403
404 return EFI_SUCCESS;
405}
406
407EFI_STATUS
408EFIAPI
409FfaNotificationGet (
410 IN UINT16 VCpuId,
411 IN UINT64 Flags,
412 IN UINT64 *NotificationBitmap
413 )
414{
415 ARM_SXC_ARGS Request = { 0 };
416 ARM_SXC_ARGS Result = { 0 };
417
418 Request.Arg0 = ARM_FID_FFA_NOTIFICATION_GET;
419 Request.Arg1 = ((UINT32)VCpuId << 16) | gPartId;
420 Request.Arg2 = Flags;
421
422 ArmCallSxc (&Request, &Result);
423
424 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
425 return FfaStatusToEfiStatus (Result.Arg2);
426 }
427
428 switch (Flags) {
429 case ARM_FFA_NOTIFICATION_FLAG_BITMAP_SP:
430 *NotificationBitmap = ((UINT64)Result.Arg3 << 32) | Result.Arg2;
431 break;
432 case ARM_FFA_NOTIFICATION_FLAG_BITMAP_VM:
433 *NotificationBitmap = ((UINT64)Result.Arg5 << 32) | Result.Arg4;
434 break;
435 case ARM_FFA_NOTIFICATION_FLAG_BITMAP_HYP:
436 *NotificationBitmap = ((UINT64)Result.Arg7 << 32) | Result.Arg6;
437 break;
438 default:
439 return EFI_UNSUPPORTED;
440 }
441
442 return EFI_SUCCESS;
443}
444
445EFI_STATUS
446EFIAPI
447FfaPartitionInfoGetRegs (
448 IN EFI_GUID *ServiceGuid,
449 IN UINT16 StartIndex,
450 IN OUT UINT16 *Tag OPTIONAL,
451 IN OUT UINT32 *PartDescCount,
452 OUT EFI_FFA_PART_INFO_DESC *PartDesc OPTIONAL
453 )
454{
455 EFI_GUID ServiceGuidMangled;
456 UINT64 Metadata = 0;
457 UINT16 TagValue = 0;
458 UINT16 CurrentIndex = 0;
459 UINT32 Count = 0;
460
461 ARM_SXC_ARGS Request = { 0 };
462 ARM_SXC_ARGS Result = { 0 };
463
464 if (PartDesc == NULL) {
465 return EFI_INVALID_PARAMETER;
466 }
467
468 if (Tag != NULL) {
469 TagValue = *Tag;
470 }
471
472 if (ServiceGuid != NULL) {
473 CopyMem (&ServiceGuidMangled, ServiceGuid, sizeof (EFI_GUID));
474 } else {
475 ZeroMem (&ServiceGuidMangled, sizeof (EFI_GUID));
476 }
477
478 FfaPrepareGuid (&ServiceGuidMangled);
479 Request.Arg0 = ARM_FID_FFA_PARTITION_INFO_GET_REGS;
480 CopyMem (&Request.Arg1, &ServiceGuidMangled, sizeof (EFI_GUID));
481 Request.Arg3 = ((UINT32)TagValue << 16) | StartIndex;
482
483 ArmCallSxc (&Request, &Result);
484
485 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
486 return FfaStatusToEfiStatus (Result.Arg2);
487 }
488
489 Metadata = Result.Arg2;
490 CurrentIndex = (UINT16)((Metadata >> 16) & 0xFFFF);
491 Count = CurrentIndex - StartIndex + 1;
492 if ((PartDesc == NULL) ||
493 (*PartDescCount < Count))
494 {
495 *PartDescCount = Count;
496 return EFI_BUFFER_TOO_SMALL;
497 }
498
499 *PartDescCount = Count;
500 for (UINTN Index = 0; Index < Count; Index++) {
501 CopyMem (PartDesc + Index, (VOID *)((UINTN)(&Result.Arg3) + Index * sizeof (EFI_FFA_PART_INFO_DESC)), sizeof (EFI_FFA_PART_INFO_DESC));
502 FfaPrepareGuid ((EFI_GUID *)PartDesc->PartitionUuid);
503 }
504
505 if (Tag != NULL) {
506 *Tag = (UINT16)((Metadata >> 32) & 0xFFFF);
507 }
508
509 return EFI_SUCCESS;
510}
511
512EFI_STATUS
513EFIAPI
514FfaNotificationBitmapCreate (
515 IN UINT16 VCpuCount
516 )
517{
518 ARM_SXC_ARGS Request = { 0 };
519 ARM_SXC_ARGS Result = { 0 };
520
521 Request.Arg0 = ARM_FID_FFA_NOTIFICATION_BITMAP_CREATE;
522 Request.Arg1 = gPartId;
523 Request.Arg2 = VCpuCount;
524
525 ArmCallSxc (&Request, &Result);
526
527 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
528 return FfaStatusToEfiStatus (Result.Arg2);
529 }
530
531 return EFI_SUCCESS;
532}
533
534EFI_STATUS
535EFIAPI
536FfaNotificationBitmapDestroy (
537 VOID
538 )
539{
540 ARM_SXC_ARGS Request = { 0 };
541 ARM_SXC_ARGS Result = { 0 };
542
543 Request.Arg0 = ARM_FID_FFA_NOTIFICATION_BITMAP_DESTROY;
544 Request.Arg1 = gPartId;
545
546 ArmCallSxc (&Request, &Result);
547
548 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
549 return FfaStatusToEfiStatus (Result.Arg2);
550 }
551
552 return EFI_SUCCESS;
553}
554
555EFI_STATUS
556EFIAPI
557FfaNotificationBind (
558 IN UINT16 DestinationId,
559 IN UINT32 Flags,
560 IN UINT64 NotificationBitmap
561 )
562{
563 ARM_SXC_ARGS Request = { 0 };
564 ARM_SXC_ARGS Result = { 0 };
565
566 Request.Arg0 = ARM_FID_FFA_NOTIFICATION_BIND;
567 Request.Arg1 = ((UINT32)DestinationId << 16) | gPartId;
568 Request.Arg2 = Flags;
569 Request.Arg3 = (UINT32)NotificationBitmap;
570 Request.Arg4 = (UINT32)(NotificationBitmap >> 32);
571
572 ArmCallSxc (&Request, &Result);
573
574 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
575 return FfaStatusToEfiStatus (Result.Arg2);
576 }
577
578 return EFI_SUCCESS;
579}
580
581EFI_STATUS
582EFIAPI
583FfaNotificationUnbind (
584 IN UINT16 DestinationId,
585 IN UINT64 NotificationBitmap
586 )
587{
588 ARM_SXC_ARGS Request = { 0 };
589 ARM_SXC_ARGS Result = { 0 };
590
591 Request.Arg0 = ARM_FID_FFA_NOTIFICATION_UNBIND;
592 Request.Arg1 = ((UINT32)DestinationId << 16) | gPartId;
593 Request.Arg2 = 0;
594 Request.Arg3 = (UINT32)NotificationBitmap;
595 Request.Arg4 = (UINT32)(NotificationBitmap >> 32);
596
597 ArmCallSxc (&Request, &Result);
598
599 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
600 return FfaStatusToEfiStatus (Result.Arg2);
601 }
602
603 return EFI_SUCCESS;
604}
605
606EFI_STATUS
607EFIAPI
608FfaMemDonateRxTx (
609 UINT32 TotalLength,
610 UINT32 FragmentLength,
611 UINT64 *Handle
612 )
613{
614 return FfaMemDonate (TotalLength, FragmentLength, NULL, 0, Handle);
615}
616
617EFI_STATUS
618EFIAPI
619FfaMemLend (
620 UINT32 TotalLength,
621 UINT32 FragmentLength,
622 VOID *BufferAddr,
623 UINT32 PageCount,
624 UINT64 *Handle
625 )
626{
627 ARM_SXC_ARGS Request = { 0 };
628 ARM_SXC_ARGS Result = { 0 };
629
630 Request.Arg0 = (BufferAddr) ? ARM_FID_FFA_MEM_LEND_AARCH64 : ARM_FID_FFA_MEM_LEND_AARCH32;
631 Request.Arg1 = TotalLength;
632 Request.Arg2 = FragmentLength;
633 Request.Arg3 = (UINTN)BufferAddr;
634 Request.Arg4 = PageCount;
635
636 ArmCallSxc (&Request, &Result);
637
638 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
639 *Handle = 0U;
640 return FfaStatusToEfiStatus (Result.Arg2);
641 }
642
643 /*
644 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
645 * will use the default 32-bit version.
646 */
647 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
648 *Handle = ((UINT64)Result.Arg3 << 32) | Result.Arg2;
649 return EFI_SUCCESS;
650}
651
652EFI_STATUS
653EFIAPI
654FfaMemLendRxTx (
655 UINT32 TotalLength,
656 UINT32 FragmentLength,
657 UINT64 *Handle
658 )
659{
660 return FfaMemLend (TotalLength, FragmentLength, NULL, 0, Handle);
661}
662
663EFI_STATUS
664EFIAPI
665FfaMemShare (
666 UINT32 TotalLength,
667 UINT32 FragmentLength,
668 VOID *BufferAddr,
669 UINT32 PageCount,
670 UINT64 *Handle
671 )
672{
673 ARM_SXC_ARGS Request = { 0 };
674 ARM_SXC_ARGS Result = { 0 };
675
676 Request.Arg0 = (BufferAddr) ? ARM_FID_FFA_MEM_SHARE_AARCH64 : ARM_FID_FFA_MEM_SHARE_AARCH32;
677 Request.Arg1 = TotalLength;
678 Request.Arg2 = FragmentLength;
679 Request.Arg3 = (UINTN)BufferAddr;
680 Request.Arg4 = PageCount;
681
682 ArmCallSxc (&Request, &Result);
683
684 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
685 *Handle = 0U;
686 return FfaStatusToEfiStatus (Result.Arg2);
687 }
688
689 /*
690 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
691 * will use the default 32-bit version.
692 */
693 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
694 *Handle = ((UINT64)Result.Arg3 << 32) | Result.Arg2;
695 return EFI_SUCCESS;
696}
697
698EFI_STATUS
699EFIAPI
700FfaMemShareRxTx (
701 UINT32 TotalLength,
702 UINT32 FragmentLength,
703 UINT64 *Handle
704 )
705{
706 return FfaMemShare (TotalLength, FragmentLength, NULL, 0, Handle);
707}
708
709EFI_STATUS
710EFIAPI
711FfaMemRetrieveReq (
712 UINT32 TotalLength,
713 UINT32 FragmentLength,
714 VOID *BufferAddr,
715 UINT32 PageCount,
716 UINT32 *RespTotalLength,
717 UINT32 *RespFragmentLength
718 )
719{
720 ARM_SXC_ARGS Request = { 0 };
721 ARM_SXC_ARGS Result = { 0 };
722
723 Request.Arg0 = (BufferAddr) ? ARM_FID_FFA_MEM_RETRIEVE_REQ_AARCH64 : ARM_FID_FFA_MEM_RETRIEVE_REQ_AARCH32;
724 Request.Arg1 = TotalLength;
725 Request.Arg2 = FragmentLength;
726 Request.Arg3 = (UINTN)BufferAddr;
727 Request.Arg4 = PageCount;
728
729 ArmCallSxc (&Request, &Result);
730
731 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
732 *RespTotalLength = 0U;
733 *RespFragmentLength = 0U;
734 return FfaStatusToEfiStatus (Result.Arg2);
735 }
736
737 ASSERT (Result.Arg0 == ARM_FID_FFA_MEM_RETRIEVE_RESP);
738 *RespTotalLength = Result.Arg1;
739 *RespFragmentLength = Result.Arg2;
740 return EFI_SUCCESS;
741}
742
743EFI_STATUS
744EFIAPI
745FfaMemRetrieveReqRxTx (
746 UINT32 TotalLength,
747 UINT32 FragmentLength,
748 UINT32 *RespTotalLength,
749 UINT32 *RespFragmentLength
750 )
751{
752 return FfaMemRetrieveReq (
753 TotalLength,
754 FragmentLength,
755 NULL,
756 0,
757 RespTotalLength,
758 RespFragmentLength
759 );
760}
761
762EFI_STATUS
763EFIAPI
764FfaMemRelinquish (
765 VOID
766 )
767{
768 ARM_SXC_ARGS Request = { 0 };
769 ARM_SXC_ARGS Result = { 0 };
770
771 Request.Arg0 = ARM_FID_FFA_MEM_RETRIEVE_RELINQUISH;
772
773 ArmCallSxc (&Request, &Result);
774
775 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
776 return FfaStatusToEfiStatus (Result.Arg2);
777 }
778
779 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
780 return EFI_SUCCESS;
781}
782
783EFI_STATUS
784EFIAPI
785FfaMemReclaim (
786 UINT64 Handle,
787 UINT32 Flags
788 )
789{
790 ARM_SXC_ARGS Request = { 0 };
791 ARM_SXC_ARGS Result = { 0 };
792 UINT32 HandleHi = 0;
793 UINT32 HandleLo = 0;
794
795 HandleHi = (Handle >> 32) & MAX_UINT32;
796 HandleLo = Handle & MAX_UINT32;
797
798 Request.Arg0 = ARM_FID_FFA_MEM_RETRIEVE_RECLAIM;
799 Request.Arg1 = HandleLo;
800 Request.Arg2 = HandleHi;
801 Request.Arg3 = Flags;
802
803 ArmCallSxc (&Request, &Result);
804
805 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
806 return FfaStatusToEfiStatus (Result.Arg2);
807 }
808
809 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
810 return EFI_SUCCESS;
811}
812
813EFI_STATUS
814EFIAPI
815FfaMemPermGet (
816 CONST VOID *BaseAddr,
817 UINT32 *MemoryPerm
818 )
819{
820 ARM_SXC_ARGS Request = { 0 };
821 ARM_SXC_ARGS Result = { 0 };
822
823 Request.Arg0 = ARM_FID_FFA_MEM_PERM_GET_AARCH32;
824 Request.Arg1 = (UINTN)BaseAddr;
825
826 ArmCallSxc (&Request, &Result);
827
828 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
829 return FfaStatusToEfiStatus (Result.Arg2);
830 }
831
832 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
833 *MemoryPerm = Result.Arg2;
834 return EFI_SUCCESS;
835}
836
837EFI_STATUS
838EFIAPI
839FfaMemPermSet (
840 CONST VOID *BaseAddr,
841 UINT32 PageCount,
842 UINT32 MemoryPerm
843 )
844{
845 ARM_SXC_ARGS Request = { 0 };
846 ARM_SXC_ARGS Result = { 0 };
847
848 ASSERT ((MemoryPerm & ARM_FFA_MEM_PERM_RESERVED_MASK) == 0);
849
850 Request.Arg0 = ARM_FID_FFA_MEM_PERM_SET_AARCH32;
851 Request.Arg1 = (UINTN)BaseAddr;
852 Request.Arg2 = PageCount;
853 Request.Arg3 = MemoryPerm;
854
855 ArmCallSxc (&Request, &Result);
856
857 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
858 return FfaStatusToEfiStatus (Result.Arg2);
859 }
860
861 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
862 return EFI_SUCCESS;
863}
864
865EFI_STATUS
866EFIAPI
867FfaConsoleLog32 (
868 CONST CHAR8 *Message,
869 UINTN Length
870 )
871{
872 ARM_SXC_ARGS Request = { 0 };
873 ARM_SXC_ARGS Result = { 0 };
874 UINT32 CharLists[6] = { 0 };
875
876 ASSERT (Length > 0 && Length <= sizeof (CharLists));
877
878 CopyMem (CharLists, Message, MIN (Length, sizeof (CharLists)));
879
880 Request.Arg0 = ARM_FID_FFA_CONSOLE_LOG_AARCH32;
881 Request.Arg1 = Length;
882 Request.Arg2 = CharLists[0];
883 Request.Arg3 = CharLists[1];
884 Request.Arg4 = CharLists[2];
885 Request.Arg5 = CharLists[3];
886 Request.Arg6 = CharLists[4];
887 Request.Arg7 = CharLists[5];
888
889 ArmCallSxc (&Request, &Result);
890
891 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
892 return FfaStatusToEfiStatus (Result.Arg2);
893 }
894
895 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
896 return EFI_SUCCESS;
897}
898
899EFI_STATUS
900EFIAPI
901FfaConsoleLog64 (
902 CONST char *Message,
903 UINTN Length
904 )
905{
906 ARM_SXC_ARGS Request = { 0 };
907 ARM_SXC_ARGS Result = { 0 };
908 UINT64 CharLists[16] = { 0 };
909
910 ASSERT (Length > 0 && Length <= sizeof (CharLists));
911
912 CopyMem (CharLists, Message, MIN (Length, sizeof (CharLists)));
913
914 Request.Arg0 = ARM_FID_FFA_CONSOLE_LOG_AARCH64;
915 Request.Arg1 = Length;
916 Request.Arg2 = CharLists[0];
917 Request.Arg3 = CharLists[1];
918 Request.Arg4 = CharLists[2];
919 Request.Arg5 = CharLists[3];
920 Request.Arg6 = CharLists[4];
921 Request.Arg7 = CharLists[5];
922 Request.Arg8 = CharLists[6];
923 Request.Arg9 = CharLists[7];
924 Request.Arg10 = CharLists[8];
925 Request.Arg11 = CharLists[9];
926 Request.Arg12 = CharLists[10];
927 Request.Arg13 = CharLists[11];
928 Request.Arg14 = CharLists[12];
929 Request.Arg15 = CharLists[13];
930 Request.Arg16 = CharLists[14];
931 Request.Arg17 = CharLists[15];
932
933 ArmCallSxc (&Request, &Result);
934
935 if (Result.Arg0 == ARM_FID_FFA_ERROR) {
936 return FfaStatusToEfiStatus (Result.Arg2);
937 }
938
939 ASSERT (Result.Arg0 == ARM_FID_FFA_SUCCESS_AARCH32);
940 return EFI_SUCCESS;
941}
942