blob: efd5256c191eb8d1079e642f658dbfb0c624d080 [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
Andrew Walbran19970ba2024-11-25 15:35:00 +00006use core::fmt::{self, Debug, Display, Formatter};
Andrew Walbran44029a02024-11-25 15:34:31 +00007use num_enum::{IntoPrimitive, TryFromPrimitive};
8use thiserror::Error;
Balint Dobszay5bf492f2024-07-29 17:21:32 +02009use uuid::Uuid;
10
11pub mod boot_info;
Balint Dobszayb2ff2bc2024-12-19 18:59:38 +010012mod ffa_v1_1;
Balint Dobszay5bf492f2024-07-29 17:21:32 +020013pub 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
Andrew Walbran44029a02024-11-25 15:34:31 +000025#[derive(Clone, Copy, Debug, Eq, Error, IntoPrimitive, PartialEq, TryFromPrimitive)]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020026#[repr(i32)]
27pub enum Error {
Andrew Walbran44029a02024-11-25 15:34:31 +000028 #[error("Not supported")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020029 NotSupported = -1,
Andrew Walbran44029a02024-11-25 15:34:31 +000030 #[error("Invalid parameters")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020031 InvalidParameters = -2,
Andrew Walbran44029a02024-11-25 15:34:31 +000032 #[error("No memory")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020033 NoMemory = -3,
Andrew Walbran44029a02024-11-25 15:34:31 +000034 #[error("Busy")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020035 Busy = -4,
Andrew Walbran44029a02024-11-25 15:34:31 +000036 #[error("Interrupted")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020037 Interrupted = -5,
Andrew Walbran44029a02024-11-25 15:34:31 +000038 #[error("Denied")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020039 Denied = -6,
Andrew Walbran44029a02024-11-25 15:34:31 +000040 #[error("Retry")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020041 Retry = -7,
Andrew Walbran44029a02024-11-25 15:34:31 +000042 #[error("Aborted")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020043 Aborted = -8,
Andrew Walbran44029a02024-11-25 15:34:31 +000044 #[error("No data")]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020045 NoData = -9,
46}
47
Andrew Walbran1e1aef12024-11-25 16:17:32 +000048/// An integer couldn't be converted to a [`FuncId`] because it is not a recognised function.
49#[derive(Clone, Copy, Debug, Eq, Error, PartialEq)]
50#[error("Unrecognised function ID {0} for FF-A")]
51pub struct UnrecognisedFunctionIdError(u32);
52
Balint Dobszay5bf492f2024-07-29 17:21:32 +020053/// FF-A v1.1: Function IDs
Andrew Walbran969b9252024-11-25 15:35:42 +000054#[derive(Clone, Copy, Debug, Eq, IntoPrimitive, PartialEq, TryFromPrimitive)]
Andrew Walbran1e1aef12024-11-25 16:17:32 +000055#[num_enum(error_type(name = UnrecognisedFunctionIdError, constructor = UnrecognisedFunctionIdError))]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020056#[repr(u32)]
57pub enum FuncId {
58 Error = 0x84000060,
59 Success32 = 0x84000061,
60 Success64 = 0xc4000061,
61 Interrupt = 0x84000062,
62 Version = 0x84000063,
63 Features = 0x84000064,
64 RxAcquire = 0x84000084,
65 RxRelease = 0x84000065,
66 RxTxMap32 = 0x84000066,
67 RxTxMap64 = 0xc4000066,
68 RxTxUnmap = 0x84000067,
69 PartitionInfoGet = 0x84000068,
70 IdGet = 0x84000069,
71 SpmIdGet = 0x84000085,
72 MsgWait = 0x8400006b,
73 Yield = 0x8400006c,
74 Run = 0x8400006d,
75 NormalWorldResume = 0x8400007c,
76 MsgSend2 = 0x84000086,
77 MsgSendDirectReq32 = 0x8400006f,
78 MsgSendDirectReq64 = 0xc400006f,
79 MsgSendDirectResp32 = 0x84000070,
80 MsgSendDirectResp64 = 0xc4000070,
81 MemDonate32 = 0x84000071,
82 MemDonate64 = 0xc4000071,
83 MemLend32 = 0x84000072,
84 MemLend64 = 0xc4000072,
85 MemShare32 = 0x84000073,
86 MemShare64 = 0xc4000073,
87 MemRetrieveReq32 = 0x84000074,
88 MemRetrieveReq64 = 0xc4000074,
89 MemRetrieveResp = 0x84000075,
90 MemRelinquish = 0x84000076,
91 MemReclaim = 0x84000077,
92 MemPermGet32 = 0x84000088,
93 MemPermGet64 = 0xc4000088,
94 MemPermSet32 = 0x84000089,
95 MemPermSet64 = 0xc4000089,
96 ConsoleLog32 = 0x8400008a,
97 ConsoleLog64 = 0xc400008a,
98}
99
100#[derive(Debug, Eq, PartialEq, Clone, Copy)]
101pub enum Interface {
102 Error {
103 target_info: u32,
104 error_code: Error,
105 },
106 Success {
107 target_info: u32,
108 result_regs: [u64; 6],
109 is_32bit: bool,
110 },
111 Interrupt {
112 endpoint_id: u32,
113 interrupt_id: u32,
114 },
115 Version {
116 input_version: u32,
117 },
118 VersionOut {
119 output_version: u32,
120 },
121 Features {
122 feat_id: u32,
123 input_properties: u32,
124 },
125 RxAcquire {
126 vm_id: u32,
127 },
128 RxRelease {
129 vm_id: u32,
130 },
131 RxTxMap {
132 tx_addr: u64,
133 rx_addr: u64,
134 page_cnt: u32,
135 is_32bit: bool,
136 },
137 RxTxUnmap {
138 id: u32,
139 },
140 PartitionInfoGet {
141 uuid: Uuid,
142 flags: u32,
143 },
144 IdGet,
145 SpmIdGet,
146 MsgWait,
147 Yield,
148 Run {
149 target_info: u32,
150 },
151 NormalWorldResume,
152 MsgSend2 {
153 sender_vm_id: u32,
154 flags: u32,
155 },
156 MsgSendDirectReq {
157 src_id: u16,
158 dst_id: u16,
159 flags: u32,
160 args: [u64; 5],
161 is_32bit: bool,
162 },
163 MsgSendDirectResp {
164 src_id: u16,
165 dst_id: u16,
166 flags: u32,
167 args: [u64; 5],
168 is_32bit: bool,
169 },
170 MemDonate {
171 total_len: u32,
172 frag_len: u32,
173 address: u64,
174 page_cnt: u32,
175 is_32bit: bool,
176 },
177 MemLend {
178 total_len: u32,
179 frag_len: u32,
180 address: u64,
181 page_cnt: u32,
182 is_32bit: bool,
183 },
184 MemShare {
185 total_len: u32,
186 frag_len: u32,
187 address: u64,
188 page_cnt: u32,
189 is_32bit: bool,
190 },
191 MemRetrieveReq {
192 total_len: u32,
193 frag_len: u32,
194 address: u64,
195 page_cnt: u32,
196 is_32bit: bool,
197 },
198 MemRetrieveResp {
199 total_len: u32,
200 frag_len: u32,
201 },
202 MemRelinquish,
203 MemReclaim {
204 handle: memory_management::Handle,
205 flags: u32,
206 },
207 MemPermGet {
208 base_addr: u64,
209 is_32bit: bool,
210 },
211 MemPermSet {
212 base_addr: u64,
213 page_cnt: u32,
214 mem_perm: u32,
215 is_32bit: bool,
216 },
217 ConsoleLog {
218 char_cnt: u32,
219 char_lists: [u64; 6],
220 is_32bit: bool,
221 },
222}
223
224impl TryFrom<[u64; 8]> for Interface {
Andrew Walbran1e1aef12024-11-25 16:17:32 +0000225 type Error = UnrecognisedFunctionIdError;
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200226
Andrew Walbran1e1aef12024-11-25 16:17:32 +0000227 fn try_from(regs: [u64; 8]) -> Result<Self, UnrecognisedFunctionIdError> {
228 let fid = FuncId::try_from(regs[0] as u32)?;
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200229
230 let msg = match fid {
231 FuncId::Error => Self::Error {
232 target_info: regs[1] as u32,
233 error_code: Error::try_from(regs[2] as i32).unwrap(),
234 },
235 FuncId::Success32 | FuncId::Success64 => {
236 let target_info = regs[1] as u32;
237 let mut result_regs = [regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]];
238 let mut is_32bit = false;
239
240 if fid == FuncId::Success32 {
241 result_regs[0] &= u32::MAX as u64;
242 result_regs[1] &= u32::MAX as u64;
243 result_regs[2] &= u32::MAX as u64;
244 result_regs[3] &= u32::MAX as u64;
245 result_regs[4] &= u32::MAX as u64;
246 result_regs[5] &= u32::MAX as u64;
247 is_32bit = true;
248 }
249
250 Self::Success {
251 target_info,
252 result_regs,
253 is_32bit,
254 }
255 }
256 FuncId::Interrupt => Self::Interrupt {
257 endpoint_id: regs[1] as u32,
258 interrupt_id: regs[2] as u32,
259 },
260 FuncId::Version => Self::Version {
261 input_version: regs[1] as u32,
262 },
263 FuncId::Features => Self::Features {
264 feat_id: regs[1] as u32,
265 input_properties: regs[2] as u32,
266 },
267 FuncId::RxAcquire => Self::RxAcquire {
268 vm_id: regs[1] as u32,
269 },
270 FuncId::RxRelease => Self::RxRelease {
271 vm_id: regs[1] as u32,
272 },
273 FuncId::RxTxMap32 | FuncId::RxTxMap64 => {
274 let mut tx_addr = regs[1];
275 let mut rx_addr = regs[2];
276 let page_cnt = regs[3] as u32;
277 let mut is_32bit = false;
278
279 if fid == FuncId::RxTxMap32 {
280 tx_addr &= u32::MAX as u64;
281 rx_addr &= u32::MAX as u64;
282 is_32bit = true;
283 }
284
285 Self::RxTxMap {
286 tx_addr,
287 rx_addr,
288 page_cnt,
289 is_32bit,
290 }
291 }
292 FuncId::RxTxUnmap => Self::RxTxUnmap { id: regs[1] as u32 },
293 FuncId::PartitionInfoGet => {
294 let uuid_words = [
295 regs[1] as u32,
296 regs[2] as u32,
297 regs[3] as u32,
298 regs[4] as u32,
299 ];
300 let mut bytes: [u8; 16] = [0; 16];
301 for (i, b) in uuid_words.iter().flat_map(|w| w.to_le_bytes()).enumerate() {
302 bytes[i] = b;
303 }
304 Self::PartitionInfoGet {
305 uuid: Uuid::from_bytes(bytes),
306 flags: regs[5] as u32,
307 }
308 }
309 FuncId::IdGet => Self::IdGet,
310 FuncId::SpmIdGet => Self::SpmIdGet,
311 FuncId::MsgWait => Self::MsgWait,
312 FuncId::Yield => Self::Yield,
313 FuncId::Run => Self::Run {
314 target_info: regs[1] as u32,
315 },
316 FuncId::NormalWorldResume => Self::NormalWorldResume,
317 FuncId::MsgSend2 => Self::MsgSend2 {
318 sender_vm_id: regs[1] as u32,
319 flags: regs[2] as u32,
320 },
321 FuncId::MsgSendDirectReq32 | FuncId::MsgSendDirectReq64 => {
322 let src_id = (regs[1] >> 16) as u16;
323 let dst_id = regs[1] as u16;
324 let flags = regs[2] as u32;
325 let mut args = [regs[3], regs[4], regs[5], regs[6], regs[7]];
326 let mut is_32bit = false;
327
328 if fid == FuncId::MsgSendDirectReq32 {
329 args[0] &= u32::MAX as u64;
330 args[1] &= u32::MAX as u64;
331 args[2] &= u32::MAX as u64;
332 args[3] &= u32::MAX as u64;
333 args[4] &= u32::MAX as u64;
334 is_32bit = true;
335 }
336
337 Self::MsgSendDirectReq {
338 src_id,
339 dst_id,
340 flags,
341 args,
342 is_32bit,
343 }
344 }
345 FuncId::MsgSendDirectResp32 | FuncId::MsgSendDirectResp64 => {
346 let src_id = (regs[1] >> 16) as u16;
347 let dst_id = regs[1] as u16;
348 let flags = regs[2] as u32;
349 let mut args = [regs[3], regs[4], regs[5], regs[6], regs[7]];
350 let mut is_32bit = false;
351
352 if fid == FuncId::MsgSendDirectResp32 {
353 args[0] &= u32::MAX as u64;
354 args[1] &= u32::MAX as u64;
355 args[2] &= u32::MAX as u64;
356 args[3] &= u32::MAX as u64;
357 args[4] &= u32::MAX as u64;
358 is_32bit = true;
359 }
360
361 Self::MsgSendDirectResp {
362 src_id,
363 dst_id,
364 flags,
365 args,
366 is_32bit,
367 }
368 }
369 FuncId::MemDonate32 | FuncId::MemDonate64 => {
370 let total_len = regs[1] as u32;
371 let frag_len = regs[2] as u32;
372 let mut address = regs[3];
373 let page_cnt = regs[4] as u32;
374 let mut is_32bit = false;
375
376 if fid == FuncId::MemDonate32 {
377 address &= u32::MAX as u64;
378 is_32bit = true;
379 }
380
381 Self::MemDonate {
382 total_len,
383 frag_len,
384 address,
385 page_cnt,
386 is_32bit,
387 }
388 }
389 FuncId::MemLend32 | FuncId::MemLend64 => {
390 let total_len = regs[1] as u32;
391 let frag_len = regs[2] as u32;
392 let mut address = regs[3];
393 let page_cnt = regs[4] as u32;
394 let mut is_32bit = false;
395
396 if fid == FuncId::MemLend32 {
397 address &= u32::MAX as u64;
398 is_32bit = true;
399 }
400
401 Self::MemLend {
402 total_len,
403 frag_len,
404 address,
405 page_cnt,
406 is_32bit,
407 }
408 }
409 FuncId::MemShare32 | FuncId::MemShare64 => {
410 let total_len = regs[1] as u32;
411 let frag_len = regs[2] as u32;
412 let mut address = regs[3];
413 let page_cnt = regs[4] as u32;
414 let mut is_32bit = false;
415
416 if fid == FuncId::MemShare32 {
417 address &= u32::MAX as u64;
418 is_32bit = true;
419 }
420
421 Self::MemShare {
422 total_len,
423 frag_len,
424 address,
425 page_cnt,
426 is_32bit,
427 }
428 }
429 FuncId::MemRetrieveReq32 | FuncId::MemRetrieveReq64 => {
430 let total_len = regs[1] as u32;
431 let frag_len = regs[2] as u32;
432 let mut address = regs[3];
433 let page_cnt = regs[4] as u32;
434 let mut is_32bit = false;
435
436 if fid == FuncId::MemRetrieveReq32 {
437 address &= u32::MAX as u64;
438 is_32bit = true;
439 }
440
441 Self::MemRetrieveReq {
442 total_len,
443 frag_len,
444 address,
445 page_cnt,
446 is_32bit,
447 }
448 }
449 FuncId::MemRetrieveResp => Self::MemRetrieveResp {
450 total_len: regs[1] as u32,
451 frag_len: regs[2] as u32,
452 },
453 FuncId::MemRelinquish => Self::MemRelinquish,
454 FuncId::MemReclaim => Self::MemReclaim {
455 handle: memory_management::Handle::from([regs[1] as u32, regs[2] as u32]),
456 flags: regs[3] as u32,
457 },
458 FuncId::MemPermGet32 | FuncId::MemPermGet64 => {
459 let mut base_addr = regs[1];
460 let mut is_32bit = false;
461
462 if fid == FuncId::MemPermGet32 {
463 base_addr &= u32::MAX as u64;
464 is_32bit = true;
465 }
466
467 Self::MemPermGet {
468 base_addr,
469 is_32bit,
470 }
471 }
472 FuncId::MemPermSet32 | FuncId::MemPermSet64 => {
473 let mut base_addr = regs[1];
474 let page_cnt = regs[2] as u32;
475 let mem_perm = regs[3] as u32;
476 let mut is_32bit = false;
477
478 if fid == FuncId::MemPermSet32 {
479 base_addr &= u32::MAX as u64;
480 is_32bit = true;
481 }
482
483 Self::MemPermSet {
484 base_addr,
485 page_cnt,
486 mem_perm,
487 is_32bit,
488 }
489 }
490 FuncId::ConsoleLog32 | FuncId::ConsoleLog64 => {
491 let char_cnt = regs[1] as u32;
492 let mut char_lists = [regs[2], regs[3], regs[4], regs[5], regs[6], regs[7]];
493 let mut is_32bit = false;
494
495 if fid == FuncId::ConsoleLog32 {
496 char_lists[0] &= u32::MAX as u64;
497 char_lists[1] &= u32::MAX as u64;
498 char_lists[2] &= u32::MAX as u64;
499 char_lists[3] &= u32::MAX as u64;
500 char_lists[4] &= u32::MAX as u64;
501 char_lists[5] &= u32::MAX as u64;
502 is_32bit = true;
503 }
504
505 Self::ConsoleLog {
506 char_cnt,
507 char_lists,
508 is_32bit,
509 }
510 }
511 };
512
513 Ok(msg)
514 }
515}
516
517impl Interface {
Andrew Walbran0d315812024-11-25 15:36:36 +0000518 /// Returns the function ID for the call, if it has one.
519 pub fn function_id(&self) -> Option<FuncId> {
520 match self {
521 Interface::Error { .. } => Some(FuncId::Error),
522 Interface::Success {
523 is_32bit: false, ..
524 } => Some(FuncId::Success64),
525 Interface::Success { is_32bit: true, .. } => Some(FuncId::Success32),
526 Interface::Interrupt { .. } => Some(FuncId::Interrupt),
527 Interface::Version { .. } => Some(FuncId::Version),
528 Interface::VersionOut { .. } => None,
529 Interface::Features { .. } => Some(FuncId::Features),
530 Interface::RxAcquire { .. } => Some(FuncId::RxAcquire),
531 Interface::RxRelease { .. } => Some(FuncId::RxRelease),
532 Interface::RxTxMap {
533 is_32bit: false, ..
534 } => Some(FuncId::RxTxMap64),
535 Interface::RxTxMap { is_32bit: true, .. } => Some(FuncId::RxTxMap32),
536 Interface::RxTxUnmap { .. } => Some(FuncId::RxTxUnmap),
537 Interface::PartitionInfoGet { .. } => Some(FuncId::PartitionInfoGet),
538 Interface::IdGet => Some(FuncId::IdGet),
539 Interface::SpmIdGet => Some(FuncId::SpmIdGet),
540 Interface::MsgWait => Some(FuncId::MsgWait),
541 Interface::Yield => Some(FuncId::Yield),
542 Interface::Run { .. } => Some(FuncId::Run),
543 Interface::NormalWorldResume => Some(FuncId::NormalWorldResume),
544 Interface::MsgSend2 { .. } => Some(FuncId::MsgSend2),
545 Interface::MsgSendDirectReq {
546 is_32bit: false, ..
547 } => Some(FuncId::MsgSendDirectReq64),
548 Interface::MsgSendDirectReq { is_32bit: true, .. } => Some(FuncId::MsgSendDirectReq32),
549 Interface::MsgSendDirectResp {
550 is_32bit: false, ..
551 } => Some(FuncId::MsgSendDirectResp64),
552 Interface::MsgSendDirectResp { is_32bit: true, .. } => {
553 Some(FuncId::MsgSendDirectResp32)
554 }
555 Interface::MemDonate {
556 is_32bit: false, ..
557 } => Some(FuncId::MemDonate64),
558 Interface::MemDonate { is_32bit: true, .. } => Some(FuncId::MemDonate32),
559 Interface::MemLend {
560 is_32bit: false, ..
561 } => Some(FuncId::MemLend64),
562 Interface::MemLend { is_32bit: true, .. } => Some(FuncId::MemLend32),
563 Interface::MemShare {
564 is_32bit: false, ..
565 } => Some(FuncId::MemShare64),
566 Interface::MemShare { is_32bit: true, .. } => Some(FuncId::MemShare32),
567 Interface::MemRetrieveReq {
568 is_32bit: false, ..
569 } => Some(FuncId::MemRetrieveReq64),
570 Interface::MemRetrieveReq { is_32bit: true, .. } => Some(FuncId::MemRetrieveReq32),
571 Interface::MemRetrieveResp { .. } => Some(FuncId::MemRetrieveResp),
572 Interface::MemRelinquish => Some(FuncId::MemRelinquish),
573 Interface::MemReclaim { .. } => Some(FuncId::MemReclaim),
574 Interface::MemPermGet {
575 is_32bit: false, ..
576 } => Some(FuncId::MemPermGet64),
577 Interface::MemPermGet { is_32bit: true, .. } => Some(FuncId::MemPermGet32),
578 Interface::MemPermSet {
579 is_32bit: false, ..
580 } => Some(FuncId::MemPermSet64),
581 Interface::MemPermSet { is_32bit: true, .. } => Some(FuncId::MemPermSet32),
582 Interface::ConsoleLog {
583 is_32bit: false, ..
584 } => Some(FuncId::ConsoleLog64),
585 Interface::ConsoleLog { is_32bit: true, .. } => Some(FuncId::ConsoleLog32),
586 }
587 }
588
589 /// Returns true if this is a 32-bit call, or false if it is a 64-bit call.
590 pub fn is_32bit(&self) -> bool {
591 match self {
592 Interface::Error { .. }
593 | Interface::Interrupt { .. }
594 | Interface::Version { .. }
595 | Interface::VersionOut { .. }
596 | Interface::Features { .. }
597 | Interface::RxAcquire { .. }
598 | Interface::RxRelease { .. }
599 | Interface::RxTxUnmap { .. }
600 | Interface::PartitionInfoGet { .. }
601 | Interface::IdGet
602 | Interface::SpmIdGet
603 | Interface::MsgWait
604 | Interface::Yield
605 | Interface::Run { .. }
606 | Interface::NormalWorldResume
607 | Interface::MsgSend2 { .. }
608 | Interface::MemRetrieveResp { .. }
609 | Interface::MemRelinquish
610 | Interface::MemReclaim { .. } => true,
611 Interface::Success { is_32bit, .. }
612 | Interface::RxTxMap { is_32bit, .. }
613 | Interface::MsgSendDirectReq { is_32bit, .. }
614 | Interface::MsgSendDirectResp { is_32bit, .. }
615 | Interface::MemDonate { is_32bit, .. }
616 | Interface::MemLend { is_32bit, .. }
617 | Interface::MemShare { is_32bit, .. }
618 | Interface::MemRetrieveReq { is_32bit, .. }
619 | Interface::MemPermGet { is_32bit, .. }
620 | Interface::MemPermSet { is_32bit, .. }
621 | Interface::ConsoleLog { is_32bit, .. } => *is_32bit,
622 }
623 }
624
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200625 pub fn copy_to_array(&self, a: &mut [u64; 8]) {
626 a.fill(0);
Andrew Walbran0d315812024-11-25 15:36:36 +0000627 if let Some(function_id) = self.function_id() {
628 a[0] = function_id as u64;
629 }
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200630
631 match *self {
632 Interface::Error {
633 target_info,
634 error_code,
635 } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200636 a[1] = target_info as u64;
637 a[2] = error_code as u32 as u64;
638 }
639 Interface::Success {
640 target_info,
641 result_regs,
642 is_32bit,
643 } => {
644 a[1] = target_info as u64;
645 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200646 a[2] = result_regs[0] & u32::MAX as u64;
647 a[3] = result_regs[1] & u32::MAX as u64;
648 a[4] = result_regs[2] & u32::MAX as u64;
649 a[5] = result_regs[3] & u32::MAX as u64;
650 a[6] = result_regs[4] & u32::MAX as u64;
651 a[7] = result_regs[5] & u32::MAX as u64;
652 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200653 a[2] = result_regs[0];
654 a[3] = result_regs[1];
655 a[4] = result_regs[2];
656 a[5] = result_regs[3];
657 a[6] = result_regs[4];
658 a[7] = result_regs[5];
659 }
660 }
661 Interface::Interrupt {
662 endpoint_id,
663 interrupt_id,
664 } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200665 a[1] = endpoint_id as u64;
666 a[2] = interrupt_id as u64;
667 }
668 Interface::Version { input_version } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200669 a[1] = input_version as u64;
670 }
671 Interface::VersionOut { output_version } => {
672 a[0] = output_version as u64;
673 }
674 Interface::Features {
675 feat_id,
676 input_properties,
677 } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200678 a[1] = feat_id as u64;
679 a[2] = input_properties as u64;
680 }
681 Interface::RxAcquire { vm_id } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200682 a[1] = vm_id as u64;
683 }
684 Interface::RxRelease { vm_id } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200685 a[1] = vm_id as u64;
686 }
687 Interface::RxTxMap {
688 tx_addr,
689 rx_addr,
690 page_cnt,
691 is_32bit,
692 } => {
693 a[3] = page_cnt as u64;
694 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200695 a[1] = tx_addr & u32::MAX as u64;
696 a[2] = rx_addr & u32::MAX as u64;
697 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200698 a[1] = tx_addr;
699 a[2] = rx_addr;
700 }
701 }
702 Interface::RxTxUnmap { id } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200703 a[1] = id as u64;
704 }
705 Interface::PartitionInfoGet { uuid, flags } => {
706 let bytes = uuid.to_bytes_le();
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200707 a[1] = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as u64;
708 a[2] = u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]) as u64;
709 a[3] = u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]) as u64;
710 a[4] = u32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]) as u64;
711 a[5] = flags as u64;
712 }
Andrew Walbran0d315812024-11-25 15:36:36 +0000713 Interface::IdGet | Interface::SpmIdGet | Interface::MsgWait | Interface::Yield => {}
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200714 Interface::Run { target_info } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200715 a[1] = target_info as u64;
716 }
Andrew Walbran0d315812024-11-25 15:36:36 +0000717 Interface::NormalWorldResume => {}
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200718 Interface::MsgSend2 {
719 sender_vm_id,
720 flags,
721 } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200722 a[1] = sender_vm_id as u64;
723 a[2] = flags as u64;
724 }
725 Interface::MsgSendDirectReq {
726 src_id,
727 dst_id,
728 flags,
729 args,
730 is_32bit,
731 } => {
732 a[1] = (src_id as u64) << 16 | dst_id as u64;
733 a[2] = flags as u64;
734 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200735 a[3] = args[0] & u32::MAX as u64;
736 a[4] = args[1] & u32::MAX as u64;
737 a[5] = args[2] & u32::MAX as u64;
738 a[6] = args[3] & u32::MAX as u64;
739 a[7] = args[4] & u32::MAX as u64;
740 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200741 a[3] = args[0];
742 a[4] = args[1];
743 a[5] = args[2];
744 a[6] = args[3];
745 a[7] = args[4];
746 }
747 }
748 Interface::MsgSendDirectResp {
749 src_id,
750 dst_id,
751 flags,
752 args,
753 is_32bit,
754 } => {
755 a[1] = (src_id as u64) << 16 | dst_id as u64;
756 a[2] = flags as u64;
757 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200758 a[3] = args[0] & u32::MAX as u64;
759 a[4] = args[1] & u32::MAX as u64;
760 a[5] = args[2] & u32::MAX as u64;
761 a[6] = args[3] & u32::MAX as u64;
762 a[7] = args[4] & u32::MAX as u64;
763 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200764 a[3] = args[0];
765 a[4] = args[1];
766 a[5] = args[2];
767 a[6] = args[3];
768 a[7] = args[4];
769 }
770 }
771 Interface::MemDonate {
772 total_len,
773 frag_len,
774 address,
775 page_cnt,
776 is_32bit,
777 } => {
778 a[1] = total_len as u64;
779 a[2] = frag_len as u64;
780 a[4] = page_cnt as u64;
781 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200782 a[3] = address & u32::MAX as u64;
783 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200784 a[3] = address;
785 }
786 }
787 Interface::MemLend {
788 total_len,
789 frag_len,
790 address,
791 page_cnt,
792 is_32bit,
793 } => {
794 a[1] = total_len as u64;
795 a[2] = frag_len as u64;
796 a[4] = page_cnt as u64;
797 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200798 a[3] = address & u32::MAX as u64;
799 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200800 a[3] = address;
801 }
802 }
803 Interface::MemShare {
804 total_len,
805 frag_len,
806 address,
807 page_cnt,
808 is_32bit,
809 } => {
810 a[1] = total_len as u64;
811 a[2] = frag_len as u64;
812 a[4] = page_cnt as u64;
813 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200814 a[3] = address & u32::MAX as u64;
815 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200816 a[3] = address;
817 }
818 }
819 Interface::MemRetrieveReq {
820 total_len,
821 frag_len,
822 address,
823 page_cnt,
824 is_32bit,
825 } => {
826 a[1] = total_len as u64;
827 a[2] = frag_len as u64;
828 a[4] = page_cnt as u64;
829 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200830 a[3] = address & u32::MAX as u64;
831 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200832 a[3] = address;
833 }
834 }
835 Interface::MemRetrieveResp {
836 total_len,
837 frag_len,
838 } => {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200839 a[1] = total_len as u64;
840 a[2] = frag_len as u64;
841 }
Andrew Walbran0d315812024-11-25 15:36:36 +0000842 Interface::MemRelinquish => {}
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200843 Interface::MemReclaim { handle, flags } => {
844 let handle_regs: [u32; 2] = handle.into();
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200845 a[1] = handle_regs[0] as u64;
846 a[2] = handle_regs[1] as u64;
847 a[3] = flags as u64;
848 }
849 Interface::MemPermGet {
850 base_addr,
851 is_32bit,
852 } => {
853 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200854 a[1] = base_addr & u32::MAX as u64;
855 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200856 a[1] = base_addr;
857 }
858 }
859 Interface::MemPermSet {
860 base_addr,
861 page_cnt,
862 mem_perm,
863 is_32bit,
864 } => {
865 a[2] = page_cnt as u64;
866 a[3] = mem_perm as u64;
867
868 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200869 a[1] = base_addr & u32::MAX as u64;
870 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200871 a[1] = base_addr;
872 }
873 }
874 Interface::ConsoleLog {
875 char_cnt,
876 char_lists,
877 is_32bit,
878 } => {
879 a[1] = char_cnt as u64;
880 if is_32bit {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200881 a[2] = char_lists[0] & u32::MAX as u64;
882 a[3] = char_lists[1] & u32::MAX as u64;
883 a[4] = char_lists[2] & u32::MAX as u64;
884 a[5] = char_lists[3] & u32::MAX as u64;
885 a[6] = char_lists[4] & u32::MAX as u64;
886 a[7] = char_lists[5] & u32::MAX as u64;
887 } else {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200888 a[2] = char_lists[0];
889 a[3] = char_lists[1];
890 a[4] = char_lists[2];
891 a[5] = char_lists[3];
892 a[6] = char_lists[4];
893 a[7] = char_lists[5];
894 }
895 }
896 }
897 }
898
899 /// Helper function to create an FFA_SUCCESS interface without any arguments
900 pub fn success32_noargs() -> Self {
901 Self::Success {
902 target_info: 0,
903 result_regs: [0, 0, 0, 0, 0, 0],
904 is_32bit: true,
905 }
906 }
907}
908
Andrew Walbran19970ba2024-11-25 15:35:00 +0000909#[derive(Clone, Copy, Eq, PartialEq)]
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200910pub struct Version(pub u16, pub u16);
911
912impl From<u32> for Version {
913 fn from(val: u32) -> Self {
914 Self((val >> 16) as u16, val as u16)
915 }
916}
917
918impl From<Version> for u32 {
919 fn from(v: Version) -> Self {
920 (v.0 as u32) << 16 | v.1 as u32
921 }
922}
923
Andrew Walbran19970ba2024-11-25 15:35:00 +0000924impl Display for Version {
925 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
926 write!(f, "{}.{}", self.0, self.1)
927 }
928}
929
930impl Debug for Version {
931 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
932 Display::fmt(self, f)
933 }
934}
935
Balint Dobszayc8802492025-01-15 18:11:39 +0100936pub const CONSOLE_LOG_32_MAX_MSG_LEN: usize = 24;
937pub const CONSOLE_LOG_64_MAX_MSG_LEN: usize = 48;
938
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200939pub fn parse_console_log(
940 char_cnt: u32,
941 char_lists: &[u64; 6],
942 is_32bit: bool,
Balint Dobszayc8802492025-01-15 18:11:39 +0100943 log_bytes: &mut [u8],
944) -> Result<(), Error> {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200945 const CHAR_COUNT_MASK: u32 = 0xff;
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200946
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200947 let char_count = (char_cnt & CHAR_COUNT_MASK) as usize;
948 let (max_length, reg_size) = if is_32bit {
Balint Dobszayc8802492025-01-15 18:11:39 +0100949 (CONSOLE_LOG_32_MAX_MSG_LEN, 4)
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200950 } else {
Balint Dobszayc8802492025-01-15 18:11:39 +0100951 (CONSOLE_LOG_64_MAX_MSG_LEN, 8)
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200952 };
953
954 if char_count < 1 || char_count > max_length {
955 return Err(Error::InvalidParameters);
956 }
957
958 for i in 0..=5 {
Balint Dobszayc8802492025-01-15 18:11:39 +0100959 log_bytes[reg_size * i..reg_size * (i + 1)]
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200960 .copy_from_slice(&char_lists[i].to_le_bytes()[0..reg_size]);
961 }
962
Balint Dobszayc8802492025-01-15 18:11:39 +0100963 Ok(())
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200964}