blob: ca1190ea17ca3296abd655bee4e98da62a8777bc [file] [log] [blame]
Balint Dobszay5bf492f2024-07-29 17:21:32 +02001// SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4#![cfg_attr(not(test), no_std)]
5
6extern crate alloc;
7
8use alloc::string::String;
9use num_enum::TryFromPrimitive;
10use uuid::Uuid;
11
12pub mod boot_info;
13pub mod memory_management;
14pub mod partition_info;
15
16pub const FFA_PAGE_SIZE: usize = 4096;
17
18#[derive(PartialEq, Clone, Copy)]
19pub enum Instance {
20 SecurePhysical,
21 SecureVirtual(u16),
22}
23
24/// FF-A v1.1, Table 12.2: Error status codes
25#[derive(Debug, Eq, PartialEq, Clone, Copy, TryFromPrimitive)]
26#[repr(i32)]
27pub enum Error {
28 NotSupported = -1,
29 InvalidParameters = -2,
30 NoMemory = -3,
31 Busy = -4,
32 Interrupted = -5,
33 Denied = -6,
34 Retry = -7,
35 Aborted = -8,
36 NoData = -9,
37}
38
39/// FF-A v1.1: Function IDs
40#[derive(Debug, Eq, PartialEq, TryFromPrimitive)]
41#[repr(u32)]
42pub enum FuncId {
43 Error = 0x84000060,
44 Success32 = 0x84000061,
45 Success64 = 0xc4000061,
46 Interrupt = 0x84000062,
47 Version = 0x84000063,
48 Features = 0x84000064,
49 RxAcquire = 0x84000084,
50 RxRelease = 0x84000065,
51 RxTxMap32 = 0x84000066,
52 RxTxMap64 = 0xc4000066,
53 RxTxUnmap = 0x84000067,
54 PartitionInfoGet = 0x84000068,
55 IdGet = 0x84000069,
56 SpmIdGet = 0x84000085,
57 MsgWait = 0x8400006b,
58 Yield = 0x8400006c,
59 Run = 0x8400006d,
60 NormalWorldResume = 0x8400007c,
61 MsgSend2 = 0x84000086,
62 MsgSendDirectReq32 = 0x8400006f,
63 MsgSendDirectReq64 = 0xc400006f,
64 MsgSendDirectResp32 = 0x84000070,
65 MsgSendDirectResp64 = 0xc4000070,
66 MemDonate32 = 0x84000071,
67 MemDonate64 = 0xc4000071,
68 MemLend32 = 0x84000072,
69 MemLend64 = 0xc4000072,
70 MemShare32 = 0x84000073,
71 MemShare64 = 0xc4000073,
72 MemRetrieveReq32 = 0x84000074,
73 MemRetrieveReq64 = 0xc4000074,
74 MemRetrieveResp = 0x84000075,
75 MemRelinquish = 0x84000076,
76 MemReclaim = 0x84000077,
77 MemPermGet32 = 0x84000088,
78 MemPermGet64 = 0xc4000088,
79 MemPermSet32 = 0x84000089,
80 MemPermSet64 = 0xc4000089,
81 ConsoleLog32 = 0x8400008a,
82 ConsoleLog64 = 0xc400008a,
83}
84
85#[derive(Debug, Eq, PartialEq, Clone, Copy)]
86pub enum Interface {
87 Error {
88 target_info: u32,
89 error_code: Error,
90 },
91 Success {
92 target_info: u32,
93 result_regs: [u64; 6],
94 is_32bit: bool,
95 },
96 Interrupt {
97 endpoint_id: u32,
98 interrupt_id: u32,
99 },
100 Version {
101 input_version: u32,
102 },
103 VersionOut {
104 output_version: u32,
105 },
106 Features {
107 feat_id: u32,
108 input_properties: u32,
109 },
110 RxAcquire {
111 vm_id: u32,
112 },
113 RxRelease {
114 vm_id: u32,
115 },
116 RxTxMap {
117 tx_addr: u64,
118 rx_addr: u64,
119 page_cnt: u32,
120 is_32bit: bool,
121 },
122 RxTxUnmap {
123 id: u32,
124 },
125 PartitionInfoGet {
126 uuid: Uuid,
127 flags: u32,
128 },
129 IdGet,
130 SpmIdGet,
131 MsgWait,
132 Yield,
133 Run {
134 target_info: u32,
135 },
136 NormalWorldResume,
137 MsgSend2 {
138 sender_vm_id: u32,
139 flags: u32,
140 },
141 MsgSendDirectReq {
142 src_id: u16,
143 dst_id: u16,
144 flags: u32,
145 args: [u64; 5],
146 is_32bit: bool,
147 },
148 MsgSendDirectResp {
149 src_id: u16,
150 dst_id: u16,
151 flags: u32,
152 args: [u64; 5],
153 is_32bit: bool,
154 },
155 MemDonate {
156 total_len: u32,
157 frag_len: u32,
158 address: u64,
159 page_cnt: u32,
160 is_32bit: bool,
161 },
162 MemLend {
163 total_len: u32,
164 frag_len: u32,
165 address: u64,
166 page_cnt: u32,
167 is_32bit: bool,
168 },
169 MemShare {
170 total_len: u32,
171 frag_len: u32,
172 address: u64,
173 page_cnt: u32,
174 is_32bit: bool,
175 },
176 MemRetrieveReq {
177 total_len: u32,
178 frag_len: u32,
179 address: u64,
180 page_cnt: u32,
181 is_32bit: bool,
182 },
183 MemRetrieveResp {
184 total_len: u32,
185 frag_len: u32,
186 },
187 MemRelinquish,
188 MemReclaim {
189 handle: memory_management::Handle,
190 flags: u32,
191 },
192 MemPermGet {
193 base_addr: u64,
194 is_32bit: bool,
195 },
196 MemPermSet {
197 base_addr: u64,
198 page_cnt: u32,
199 mem_perm: u32,
200 is_32bit: bool,
201 },
202 ConsoleLog {
203 char_cnt: u32,
204 char_lists: [u64; 6],
205 is_32bit: bool,
206 },
207}
208
209impl TryFrom<[u64; 8]> for Interface {
210 type Error = ();
211
212 fn try_from(regs: [u64; 8]) -> Result<Self, ()> {
213 let fid = FuncId::try_from(regs[0] as u32).unwrap();
214
215 let msg = match fid {
216 FuncId::Error => Self::Error {
217 target_info: regs[1] as u32,
218 error_code: Error::try_from(regs[2] as i32).unwrap(),
219 },
220 FuncId::Success32 | FuncId::Success64 => {
221 let target_info = regs[1] as u32;
222 let mut result_regs = [regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]];
223 let mut is_32bit = false;
224
225 if fid == FuncId::Success32 {
226 result_regs[0] &= u32::MAX as u64;
227 result_regs[1] &= u32::MAX as u64;
228 result_regs[2] &= u32::MAX as u64;
229 result_regs[3] &= u32::MAX as u64;
230 result_regs[4] &= u32::MAX as u64;
231 result_regs[5] &= u32::MAX as u64;
232 is_32bit = true;
233 }
234
235 Self::Success {
236 target_info,
237 result_regs,
238 is_32bit,
239 }
240 }
241 FuncId::Interrupt => Self::Interrupt {
242 endpoint_id: regs[1] as u32,
243 interrupt_id: regs[2] as u32,
244 },
245 FuncId::Version => Self::Version {
246 input_version: regs[1] as u32,
247 },
248 FuncId::Features => Self::Features {
249 feat_id: regs[1] as u32,
250 input_properties: regs[2] as u32,
251 },
252 FuncId::RxAcquire => Self::RxAcquire {
253 vm_id: regs[1] as u32,
254 },
255 FuncId::RxRelease => Self::RxRelease {
256 vm_id: regs[1] as u32,
257 },
258 FuncId::RxTxMap32 | FuncId::RxTxMap64 => {
259 let mut tx_addr = regs[1];
260 let mut rx_addr = regs[2];
261 let page_cnt = regs[3] as u32;
262 let mut is_32bit = false;
263
264 if fid == FuncId::RxTxMap32 {
265 tx_addr &= u32::MAX as u64;
266 rx_addr &= u32::MAX as u64;
267 is_32bit = true;
268 }
269
270 Self::RxTxMap {
271 tx_addr,
272 rx_addr,
273 page_cnt,
274 is_32bit,
275 }
276 }
277 FuncId::RxTxUnmap => Self::RxTxUnmap { id: regs[1] as u32 },
278 FuncId::PartitionInfoGet => {
279 let uuid_words = [
280 regs[1] as u32,
281 regs[2] as u32,
282 regs[3] as u32,
283 regs[4] as u32,
284 ];
285 let mut bytes: [u8; 16] = [0; 16];
286 for (i, b) in uuid_words.iter().flat_map(|w| w.to_le_bytes()).enumerate() {
287 bytes[i] = b;
288 }
289 Self::PartitionInfoGet {
290 uuid: Uuid::from_bytes(bytes),
291 flags: regs[5] as u32,
292 }
293 }
294 FuncId::IdGet => Self::IdGet,
295 FuncId::SpmIdGet => Self::SpmIdGet,
296 FuncId::MsgWait => Self::MsgWait,
297 FuncId::Yield => Self::Yield,
298 FuncId::Run => Self::Run {
299 target_info: regs[1] as u32,
300 },
301 FuncId::NormalWorldResume => Self::NormalWorldResume,
302 FuncId::MsgSend2 => Self::MsgSend2 {
303 sender_vm_id: regs[1] as u32,
304 flags: regs[2] as u32,
305 },
306 FuncId::MsgSendDirectReq32 | FuncId::MsgSendDirectReq64 => {
307 let src_id = (regs[1] >> 16) as u16;
308 let dst_id = regs[1] as u16;
309 let flags = regs[2] as u32;
310 let mut args = [regs[3], regs[4], regs[5], regs[6], regs[7]];
311 let mut is_32bit = false;
312
313 if fid == FuncId::MsgSendDirectReq32 {
314 args[0] &= u32::MAX as u64;
315 args[1] &= u32::MAX as u64;
316 args[2] &= u32::MAX as u64;
317 args[3] &= u32::MAX as u64;
318 args[4] &= u32::MAX as u64;
319 is_32bit = true;
320 }
321
322 Self::MsgSendDirectReq {
323 src_id,
324 dst_id,
325 flags,
326 args,
327 is_32bit,
328 }
329 }
330 FuncId::MsgSendDirectResp32 | FuncId::MsgSendDirectResp64 => {
331 let src_id = (regs[1] >> 16) as u16;
332 let dst_id = regs[1] as u16;
333 let flags = regs[2] as u32;
334 let mut args = [regs[3], regs[4], regs[5], regs[6], regs[7]];
335 let mut is_32bit = false;
336
337 if fid == FuncId::MsgSendDirectResp32 {
338 args[0] &= u32::MAX as u64;
339 args[1] &= u32::MAX as u64;
340 args[2] &= u32::MAX as u64;
341 args[3] &= u32::MAX as u64;
342 args[4] &= u32::MAX as u64;
343 is_32bit = true;
344 }
345
346 Self::MsgSendDirectResp {
347 src_id,
348 dst_id,
349 flags,
350 args,
351 is_32bit,
352 }
353 }
354 FuncId::MemDonate32 | FuncId::MemDonate64 => {
355 let total_len = regs[1] as u32;
356 let frag_len = regs[2] as u32;
357 let mut address = regs[3];
358 let page_cnt = regs[4] as u32;
359 let mut is_32bit = false;
360
361 if fid == FuncId::MemDonate32 {
362 address &= u32::MAX as u64;
363 is_32bit = true;
364 }
365
366 Self::MemDonate {
367 total_len,
368 frag_len,
369 address,
370 page_cnt,
371 is_32bit,
372 }
373 }
374 FuncId::MemLend32 | FuncId::MemLend64 => {
375 let total_len = regs[1] as u32;
376 let frag_len = regs[2] as u32;
377 let mut address = regs[3];
378 let page_cnt = regs[4] as u32;
379 let mut is_32bit = false;
380
381 if fid == FuncId::MemLend32 {
382 address &= u32::MAX as u64;
383 is_32bit = true;
384 }
385
386 Self::MemLend {
387 total_len,
388 frag_len,
389 address,
390 page_cnt,
391 is_32bit,
392 }
393 }
394 FuncId::MemShare32 | FuncId::MemShare64 => {
395 let total_len = regs[1] as u32;
396 let frag_len = regs[2] as u32;
397 let mut address = regs[3];
398 let page_cnt = regs[4] as u32;
399 let mut is_32bit = false;
400
401 if fid == FuncId::MemShare32 {
402 address &= u32::MAX as u64;
403 is_32bit = true;
404 }
405
406 Self::MemShare {
407 total_len,
408 frag_len,
409 address,
410 page_cnt,
411 is_32bit,
412 }
413 }
414 FuncId::MemRetrieveReq32 | FuncId::MemRetrieveReq64 => {
415 let total_len = regs[1] as u32;
416 let frag_len = regs[2] as u32;
417 let mut address = regs[3];
418 let page_cnt = regs[4] as u32;
419 let mut is_32bit = false;
420
421 if fid == FuncId::MemRetrieveReq32 {
422 address &= u32::MAX as u64;
423 is_32bit = true;
424 }
425
426 Self::MemRetrieveReq {
427 total_len,
428 frag_len,
429 address,
430 page_cnt,
431 is_32bit,
432 }
433 }
434 FuncId::MemRetrieveResp => Self::MemRetrieveResp {
435 total_len: regs[1] as u32,
436 frag_len: regs[2] as u32,
437 },
438 FuncId::MemRelinquish => Self::MemRelinquish,
439 FuncId::MemReclaim => Self::MemReclaim {
440 handle: memory_management::Handle::from([regs[1] as u32, regs[2] as u32]),
441 flags: regs[3] as u32,
442 },
443 FuncId::MemPermGet32 | FuncId::MemPermGet64 => {
444 let mut base_addr = regs[1];
445 let mut is_32bit = false;
446
447 if fid == FuncId::MemPermGet32 {
448 base_addr &= u32::MAX as u64;
449 is_32bit = true;
450 }
451
452 Self::MemPermGet {
453 base_addr,
454 is_32bit,
455 }
456 }
457 FuncId::MemPermSet32 | FuncId::MemPermSet64 => {
458 let mut base_addr = regs[1];
459 let page_cnt = regs[2] as u32;
460 let mem_perm = regs[3] as u32;
461 let mut is_32bit = false;
462
463 if fid == FuncId::MemPermSet32 {
464 base_addr &= u32::MAX as u64;
465 is_32bit = true;
466 }
467
468 Self::MemPermSet {
469 base_addr,
470 page_cnt,
471 mem_perm,
472 is_32bit,
473 }
474 }
475 FuncId::ConsoleLog32 | FuncId::ConsoleLog64 => {
476 let char_cnt = regs[1] as u32;
477 let mut char_lists = [regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]];
478 let mut is_32bit = false;
479
480 if fid == FuncId::ConsoleLog32 {
481 char_lists[0] &= u32::MAX as u64;
482 char_lists[1] &= u32::MAX as u64;
483 char_lists[2] &= u32::MAX as u64;
484 char_lists[3] &= u32::MAX as u64;
485 char_lists[4] &= u32::MAX as u64;
486 char_lists[5] &= u32::MAX as u64;
487 is_32bit = true;
488 }
489
490 Self::ConsoleLog {
491 char_cnt,
492 char_lists,
493 is_32bit,
494 }
495 }
496 };
497
498 Ok(msg)
499 }
500}
501
502impl Interface {
503 pub fn copy_to_array(&self, a: &mut [u64; 8]) {
504 a.fill(0);
505
506 match *self {
507 Interface::Error {
508 target_info,
509 error_code,
510 } => {
511 a[0] = FuncId::Error as u64;
512 a[1] = target_info as u64;
513 a[2] = error_code as u32 as u64;
514 }
515 Interface::Success {
516 target_info,
517 result_regs,
518 is_32bit,
519 } => {
520 a[1] = target_info as u64;
521 if is_32bit {
522 a[0] = FuncId::Success32 as u64;
523 a[2] = result_regs[0] & u32::MAX as u64;
524 a[3] = result_regs[1] & u32::MAX as u64;
525 a[4] = result_regs[2] & u32::MAX as u64;
526 a[5] = result_regs[3] & u32::MAX as u64;
527 a[6] = result_regs[4] & u32::MAX as u64;
528 a[7] = result_regs[5] & u32::MAX as u64;
529 } else {
530 a[0] = FuncId::Success64 as u64;
531 a[2] = result_regs[0];
532 a[3] = result_regs[1];
533 a[4] = result_regs[2];
534 a[5] = result_regs[3];
535 a[6] = result_regs[4];
536 a[7] = result_regs[5];
537 }
538 }
539 Interface::Interrupt {
540 endpoint_id,
541 interrupt_id,
542 } => {
543 a[0] = FuncId::Interrupt as u64;
544 a[1] = endpoint_id as u64;
545 a[2] = interrupt_id as u64;
546 }
547 Interface::Version { input_version } => {
548 a[0] = FuncId::Version as u64;
549 a[1] = input_version as u64;
550 }
551 Interface::VersionOut { output_version } => {
552 a[0] = output_version as u64;
553 }
554 Interface::Features {
555 feat_id,
556 input_properties,
557 } => {
558 a[0] = FuncId::Features as u64;
559 a[1] = feat_id as u64;
560 a[2] = input_properties as u64;
561 }
562 Interface::RxAcquire { vm_id } => {
563 a[0] = FuncId::RxAcquire as u64;
564 a[1] = vm_id as u64;
565 }
566 Interface::RxRelease { vm_id } => {
567 a[0] = FuncId::RxRelease as u64;
568 a[1] = vm_id as u64;
569 }
570 Interface::RxTxMap {
571 tx_addr,
572 rx_addr,
573 page_cnt,
574 is_32bit,
575 } => {
576 a[3] = page_cnt as u64;
577 if is_32bit {
578 a[0] = FuncId::RxTxMap32 as u64;
579 a[1] = tx_addr & u32::MAX as u64;
580 a[2] = rx_addr & u32::MAX as u64;
581 } else {
582 a[0] = FuncId::RxTxMap64 as u64;
583 a[1] = tx_addr;
584 a[2] = rx_addr;
585 }
586 }
587 Interface::RxTxUnmap { id } => {
588 a[0] = FuncId::RxTxUnmap as u64;
589 a[1] = id as u64;
590 }
591 Interface::PartitionInfoGet { uuid, flags } => {
592 let bytes = uuid.to_bytes_le();
593 a[0] = FuncId::PartitionInfoGet as u64;
594 a[1] = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as u64;
595 a[2] = u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]) as u64;
596 a[3] = u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]) as u64;
597 a[4] = u32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]) as u64;
598 a[5] = flags as u64;
599 }
600 Interface::IdGet => a[0] = FuncId::IdGet as u64,
601 Interface::SpmIdGet => a[0] = FuncId::SpmIdGet as u64,
602 Interface::MsgWait => a[0] = FuncId::MsgWait as u64,
603 Interface::Yield => a[0] = FuncId::Yield as u64,
604 Interface::Run { target_info } => {
605 a[0] = FuncId::Run as u64;
606 a[1] = target_info as u64;
607 }
608 Interface::NormalWorldResume => a[0] = FuncId::NormalWorldResume as u64,
609 Interface::MsgSend2 {
610 sender_vm_id,
611 flags,
612 } => {
613 a[0] = FuncId::MsgSend2 as u64;
614 a[1] = sender_vm_id as u64;
615 a[2] = flags as u64;
616 }
617 Interface::MsgSendDirectReq {
618 src_id,
619 dst_id,
620 flags,
621 args,
622 is_32bit,
623 } => {
624 a[1] = (src_id as u64) << 16 | dst_id as u64;
625 a[2] = flags as u64;
626 if is_32bit {
627 a[0] = FuncId::MsgSendDirectReq32 as u64;
628 a[3] = args[0] & u32::MAX as u64;
629 a[4] = args[1] & u32::MAX as u64;
630 a[5] = args[2] & u32::MAX as u64;
631 a[6] = args[3] & u32::MAX as u64;
632 a[7] = args[4] & u32::MAX as u64;
633 } else {
634 a[0] = FuncId::MsgSendDirectReq64 as u64;
635 a[3] = args[0];
636 a[4] = args[1];
637 a[5] = args[2];
638 a[6] = args[3];
639 a[7] = args[4];
640 }
641 }
642 Interface::MsgSendDirectResp {
643 src_id,
644 dst_id,
645 flags,
646 args,
647 is_32bit,
648 } => {
649 a[1] = (src_id as u64) << 16 | dst_id as u64;
650 a[2] = flags as u64;
651 if is_32bit {
652 a[0] = FuncId::MsgSendDirectResp32 as u64;
653 a[3] = args[0] & u32::MAX as u64;
654 a[4] = args[1] & u32::MAX as u64;
655 a[5] = args[2] & u32::MAX as u64;
656 a[6] = args[3] & u32::MAX as u64;
657 a[7] = args[4] & u32::MAX as u64;
658 } else {
659 a[0] = FuncId::MsgSendDirectResp64 as u64;
660 a[3] = args[0];
661 a[4] = args[1];
662 a[5] = args[2];
663 a[6] = args[3];
664 a[7] = args[4];
665 }
666 }
667 Interface::MemDonate {
668 total_len,
669 frag_len,
670 address,
671 page_cnt,
672 is_32bit,
673 } => {
674 a[1] = total_len as u64;
675 a[2] = frag_len as u64;
676 a[4] = page_cnt as u64;
677 if is_32bit {
678 a[0] = FuncId::MemDonate32 as u64;
679 a[3] = address & u32::MAX as u64;
680 } else {
681 a[0] = FuncId::MemDonate64 as u64;
682 a[3] = address;
683 }
684 }
685 Interface::MemLend {
686 total_len,
687 frag_len,
688 address,
689 page_cnt,
690 is_32bit,
691 } => {
692 a[1] = total_len as u64;
693 a[2] = frag_len as u64;
694 a[4] = page_cnt as u64;
695 if is_32bit {
696 a[0] = FuncId::MemLend32 as u64;
697 a[3] = address & u32::MAX as u64;
698 } else {
699 a[0] = FuncId::MemLend64 as u64;
700 a[3] = address;
701 }
702 }
703 Interface::MemShare {
704 total_len,
705 frag_len,
706 address,
707 page_cnt,
708 is_32bit,
709 } => {
710 a[1] = total_len as u64;
711 a[2] = frag_len as u64;
712 a[4] = page_cnt as u64;
713 if is_32bit {
714 a[0] = FuncId::MemShare32 as u64;
715 a[3] = address & u32::MAX as u64;
716 } else {
717 a[0] = FuncId::MemShare64 as u64;
718 a[3] = address;
719 }
720 }
721 Interface::MemRetrieveReq {
722 total_len,
723 frag_len,
724 address,
725 page_cnt,
726 is_32bit,
727 } => {
728 a[1] = total_len as u64;
729 a[2] = frag_len as u64;
730 a[4] = page_cnt as u64;
731 if is_32bit {
732 a[0] = FuncId::MemRetrieveReq32 as u64;
733 a[3] = address & u32::MAX as u64;
734 } else {
735 a[0] = FuncId::MemRetrieveReq64 as u64;
736 a[3] = address;
737 }
738 }
739 Interface::MemRetrieveResp {
740 total_len,
741 frag_len,
742 } => {
743 a[0] = FuncId::MemRetrieveResp as u64;
744 a[1] = total_len as u64;
745 a[2] = frag_len as u64;
746 }
747 Interface::MemRelinquish => a[0] = FuncId::MemRelinquish as u64,
748 Interface::MemReclaim { handle, flags } => {
749 let handle_regs: [u32; 2] = handle.into();
750 a[0] = FuncId::MemReclaim as u64;
751 a[1] = handle_regs[0] as u64;
752 a[2] = handle_regs[1] as u64;
753 a[3] = flags as u64;
754 }
755 Interface::MemPermGet {
756 base_addr,
757 is_32bit,
758 } => {
759 if is_32bit {
760 a[0] = FuncId::MemPermGet32 as u64;
761 a[1] = base_addr & u32::MAX as u64;
762 } else {
763 a[0] = FuncId::MemPermGet64 as u64;
764 a[1] = base_addr;
765 }
766 }
767 Interface::MemPermSet {
768 base_addr,
769 page_cnt,
770 mem_perm,
771 is_32bit,
772 } => {
773 a[2] = page_cnt as u64;
774 a[3] = mem_perm as u64;
775
776 if is_32bit {
777 a[0] = FuncId::MemPermSet32 as u64;
778 a[1] = base_addr & u32::MAX as u64;
779 } else {
780 a[0] = FuncId::MemPermSet64 as u64;
781 a[1] = base_addr;
782 }
783 }
784 Interface::ConsoleLog {
785 char_cnt,
786 char_lists,
787 is_32bit,
788 } => {
789 a[1] = char_cnt as u64;
790 if is_32bit {
791 a[0] = FuncId::ConsoleLog32 as u64;
792 a[2] = char_lists[0] & u32::MAX as u64;
793 a[3] = char_lists[1] & u32::MAX as u64;
794 a[4] = char_lists[2] & u32::MAX as u64;
795 a[5] = char_lists[3] & u32::MAX as u64;
796 a[6] = char_lists[4] & u32::MAX as u64;
797 a[7] = char_lists[5] & u32::MAX as u64;
798 } else {
799 a[0] = FuncId::ConsoleLog64 as u64;
800 a[2] = char_lists[0];
801 a[3] = char_lists[1];
802 a[4] = char_lists[2];
803 a[5] = char_lists[3];
804 a[6] = char_lists[4];
805 a[7] = char_lists[5];
806 }
807 }
808 }
809 }
810
811 /// Helper function to create an FFA_SUCCESS interface without any arguments
812 pub fn success32_noargs() -> Self {
813 Self::Success {
814 target_info: 0,
815 result_regs: [0, 0, 0, 0, 0, 0],
816 is_32bit: true,
817 }
818 }
819}
820
821#[derive(Clone, Copy, Debug, PartialEq)]
822pub struct Version(pub u16, pub u16);
823
824impl From<u32> for Version {
825 fn from(val: u32) -> Self {
826 Self((val >> 16) as u16, val as u16)
827 }
828}
829
830impl From<Version> for u32 {
831 fn from(v: Version) -> Self {
832 (v.0 as u32) << 16 | v.1 as u32
833 }
834}
835
836pub fn parse_console_log(
837 char_cnt: u32,
838 char_lists: &[u64; 6],
839 is_32bit: bool,
840) -> Result<String, Error> {
841 const CHAR_COUNT_MASK: u32 = 0xff;
842 const LOG_32_MAX_MSG_LEN: usize = 24;
843 const LOG_64_MAX_MSG_LEN: usize = 48;
844
845 let mut msg_bytes = [0u8; LOG_64_MAX_MSG_LEN + 1];
846 let char_count = (char_cnt & CHAR_COUNT_MASK) as usize;
847 let (max_length, reg_size) = if is_32bit {
848 (LOG_32_MAX_MSG_LEN, 4)
849 } else {
850 (LOG_64_MAX_MSG_LEN, 8)
851 };
852
853 if char_count < 1 || char_count > max_length {
854 return Err(Error::InvalidParameters);
855 }
856
857 for i in 0..=5 {
858 msg_bytes[reg_size * i..reg_size * (i + 1)]
859 .copy_from_slice(&char_lists[i].to_le_bytes()[0..reg_size]);
860 }
861
862 String::from_utf8(msg_bytes.to_vec()).map_err(|_| Error::InvalidParameters)
863}