sel4_microkit_simple_ipc/
lib.rs

1//
2// Copyright 2025, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7#![no_std]
8
9use core::error::Error;
10use core::fmt;
11
12use serde::{Deserialize, Serialize};
13use zerocopy::IntoBytes;
14
15use sel4_microkit_base::{
16    Channel, MessageInfo, MessageLabel, MessageRegisterValue, with_msg_regs, with_msg_regs_mut,
17};
18
19const MAX_MESSAGE_LABEL: MessageLabel =
20    !0 >> (size_of::<MessageInfo>() * 8 - MessageInfo::label_width());
21
22pub const UNSPECIFIED_ERROR_MESSAGE_LABEL: MessageLabel = MAX_MESSAGE_LABEL;
23
24pub fn send_unspecified_error() -> MessageInfo {
25    MessageInfo::new(UNSPECIFIED_ERROR_MESSAGE_LABEL, 0)
26}
27
28pub fn try_send<T: Serialize>(val: T) -> Result<MessageInfo, postcard::Error> {
29    with_msg_regs_mut(|buf| {
30        let used = postcard::to_slice(&val, buf.as_mut_bytes())?;
31        let count = bytes_to_words(used.len());
32        Ok(MessageInfo::new(0, count))
33    })
34}
35
36pub fn send<T: Serialize>(val: T) -> MessageInfo {
37    try_send(val).unwrap()
38}
39
40pub fn recv<T: for<'a> Deserialize<'a>>(msg_info: MessageInfo) -> Result<T, RecvError> {
41    let label = msg_info.label();
42    if label != 0 {
43        return Err(RecvError::UnexpectedLabel { label });
44    }
45    with_msg_regs(|buf| postcard::from_bytes(buf.as_bytes()).map_err(RecvError::PostcardError))
46}
47
48pub fn try_call<T: Serialize, U: for<'a> Deserialize<'a>>(
49    channel: Channel,
50    val: T,
51) -> Result<U, TryCallError> {
52    let req_msg_info = try_send(val).map_err(TryCallError::SendError)?;
53    let resp_msg_info = channel.pp_call(req_msg_info);
54    recv(resp_msg_info).map_err(TryCallError::RecvError)
55}
56
57pub fn call<T: Serialize, U: for<'a> Deserialize<'a>>(
58    channel: Channel,
59    val: T,
60) -> Result<U, RecvError> {
61    try_call(channel, val).map_err(|err| match err {
62        TryCallError::SendError(err) => panic!("send error: {err}"),
63        TryCallError::RecvError(err) => err,
64    })
65}
66
67#[derive(Clone, Debug)]
68pub enum RecvError {
69    UnexpectedLabel { label: MessageLabel },
70    PostcardError(postcard::Error),
71}
72
73impl fmt::Display for RecvError {
74    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75        match self {
76            Self::UnexpectedLabel { label } => write!(f, "unexpected label: {label}"),
77            Self::PostcardError(err) => write!(f, "postcard error: {err}"),
78        }
79    }
80}
81
82impl Error for RecvError {}
83
84#[derive(Clone, Debug)]
85pub enum TryCallError {
86    SendError(postcard::Error),
87    RecvError(RecvError),
88}
89
90impl fmt::Display for TryCallError {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        match self {
93            Self::SendError(err) => write!(f, "send error: {err}"),
94            Self::RecvError(err) => write!(f, "recv error: {err}"),
95        }
96    }
97}
98
99impl Error for TryCallError {}
100
101// // //
102
103fn bytes_to_words(num_bytes: usize) -> usize {
104    let d = size_of::<MessageRegisterValue>();
105    num_bytes.next_multiple_of(d) / d
106}