Skip to main content

xous_sys/definitions/
mod.rs

1#[cfg(feature = "unstable_mem")]
2mod memoryflags;
3
4#[cfg(feature = "unstable_mem")]
5pub use memoryflags::*;
6
7/// Indicates a particular syscall number as used by the Xous kernel.
8#[derive(Copy, Clone)]
9#[repr(usize)]
10pub enum Syscall {
11    MapMemory = 2,
12    Yield = 3,
13    UpdateMemoryFlags = 12,
14    ReceiveMessage = 15,
15    SendMessage = 16,
16    Connect = 17,
17    CreateThread = 18,
18    UnmapMemory = 19,
19    ReturnMemory = 20,
20    TerminateProcess = 22,
21    TrySendMessage = 24,
22    TryConnect = 25,
23    GetThreadId = 32,
24    Disconnect = 35,
25    JoinThread = 36,
26    AdjustProcessLimit = 38,
27    ReturnScalar = 40,
28}
29
30/// Copies of these invocation types here for when we're running
31/// in environments without libxous.
32#[derive(Copy, Clone)]
33#[repr(usize)]
34pub enum SyscallResult {
35    Ok = 0,
36    Error = 1,
37    MemoryRange = 3,
38    ConnectionId = 7,
39    Message = 9,
40    ThreadId = 10,
41    Scalar1 = 14,
42    Scalar2 = 15,
43    MemoryReturned = 18,
44    Scalar5 = 20,
45}
46
47#[derive(Copy, Clone)]
48/// A list of all known errors that may be returned by the Xous kernel.
49#[repr(usize)]
50pub enum Error {
51    NoError = 0,
52    BadAlignment = 1,
53    BadAddress = 2,
54    OutOfMemory = 3,
55    MemoryInUse = 4,
56    InterruptNotFound = 5,
57    InterruptInUse = 6,
58    InvalidString = 7,
59    ServerExists = 8,
60    ServerNotFound = 9,
61    ProcessNotFound = 10,
62    ProcessNotChild = 11,
63    ProcessTerminated = 12,
64    Timeout = 13,
65    InternalError = 14,
66    ServerQueueFull = 15,
67    ThreadNotAvailable = 16,
68    UnhandledSyscall = 17,
69    InvalidSyscall = 18,
70    ShareViolation = 19,
71    InvalidThread = 20,
72    InvalidPid = 21,
73    UnknownError = 22,
74    AccessDenied = 23,
75    UseBeforeInit = 24,
76    DoubleFree = 25,
77    DebugInProgress = 26,
78    InvalidLimit = 27,
79}
80
81impl From<usize> for Error {
82    // Marking this function as "cold" ensures this error path
83    // does not get inlined.
84    #[cold]
85    fn from(src: usize) -> Self {
86        match src {
87            0 => Self::NoError,
88            1 => Self::BadAlignment,
89            2 => Self::BadAddress,
90            3 => Self::OutOfMemory,
91            4 => Self::MemoryInUse,
92            5 => Self::InterruptNotFound,
93            6 => Self::InterruptInUse,
94            7 => Self::InvalidString,
95            8 => Self::ServerExists,
96            9 => Self::ServerNotFound,
97            10 => Self::ProcessNotFound,
98            11 => Self::ProcessNotChild,
99            12 => Self::ProcessTerminated,
100            13 => Self::Timeout,
101            14 => Self::InternalError,
102            15 => Self::ServerQueueFull,
103            16 => Self::ThreadNotAvailable,
104            17 => Self::UnhandledSyscall,
105            18 => Self::InvalidSyscall,
106            19 => Self::ShareViolation,
107            20 => Self::InvalidThread,
108            21 => Self::InvalidPid,
109            23 => Self::AccessDenied,
110            24 => Self::UseBeforeInit,
111            25 => Self::DoubleFree,
112            26 => Self::DebugInProgress,
113            27 => Self::InvalidLimit,
114            22 | _ => Self::UnknownError,
115        }
116    }
117}
118
119impl From<i32> for Error {
120    #[cold]
121    fn from(src: i32) -> Self {
122        let Ok(src) = core::convert::TryInto::<usize>::try_into(src) else {
123            return Self::UnknownError;
124        };
125        src.into()
126    }
127}
128
129impl core::fmt::Display for Error {
130    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
131        write!(
132            f,
133            "{}",
134            match self {
135                Error::NoError => "no error occurred",
136                Error::BadAlignment => "memory was not properly aligned",
137                Error::BadAddress => "an invalid address was supplied",
138                Error::OutOfMemory => "the process or service has run out of memory",
139                Error::MemoryInUse => "the requested address is in use",
140                Error::InterruptNotFound =>
141                    "the requested interrupt does not exist on this platform",
142                Error::InterruptInUse => "the requested interrupt is currently in use",
143                Error::InvalidString => "the specified string was not formatted correctly",
144                Error::ServerExists => "a server with that address already exists",
145                Error::ServerNotFound => "the requetsed server could not be found",
146                Error::ProcessNotFound => "the target process does not exist",
147                Error::ProcessNotChild =>
148                    "the requested operation can only be done on child processes",
149                Error::ProcessTerminated => "the target process has crashed",
150                Error::Timeout => "the requested operation timed out",
151                Error::InternalError => "an internal error occurred",
152                Error::ServerQueueFull => "the server has too many pending messages",
153                Error::ThreadNotAvailable => "the specified thread does not exist",
154                Error::UnhandledSyscall => "the kernel did not recognize that syscall",
155                Error::InvalidSyscall => "the syscall had incorrect parameters",
156                Error::ShareViolation => "an attempt was made to share memory twice",
157                Error::InvalidThread => "tried to resume a thread that was not ready",
158                Error::InvalidPid => "kernel attempted to use a pid that was not valid",
159                Error::AccessDenied => "no permission to perform the requested operation",
160                Error::UseBeforeInit => "attempt to use a service before initialization finished",
161                Error::DoubleFree => "the requested resource was freed twice",
162                Error::DebugInProgress => "kernel attempted to activate a thread being debugged",
163                Error::InvalidLimit => "process attempted to adjust an invalid limit",
164                Error::UnknownError => "an unknown error occurred",
165            }
166        )
167    }
168}
169
170impl core::fmt::Debug for Error {
171    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172        write!(f, "{}", self)
173    }
174}
175
176impl core::error::Error for Error {}
177
178/// Indicates the type of Message that is sent when making a `SendMessage` syscall.
179pub enum InvokeType {
180    LendMut = 1,
181    Lend = 2,
182    #[cfg(feature = "unstable_mem")]
183    Move = 3,
184    Scalar = 4,
185    BlockingScalar = 5,
186}
187
188#[derive(Debug, Copy, Clone)]
189/// A representation of a connection to a Xous service.
190pub struct Connection(pub(crate) u32);
191
192impl From<u32> for Connection {
193    fn from(src: u32) -> Connection {
194        Connection(src)
195    }
196}
197
198impl TryFrom<usize> for Connection {
199    type Error = core::num::TryFromIntError;
200    fn try_from(src: usize) -> Result<Self, Self::Error> {
201        Ok(Connection(src.try_into()?))
202    }
203}
204
205impl Into<u32> for Connection {
206    fn into(self) -> u32 {
207        self.0
208    }
209}
210
211impl TryInto<usize> for Connection {
212    type Error = core::num::TryFromIntError;
213    fn try_into(self) -> Result<usize, Self::Error> {
214        self.0.try_into()
215    }
216}
217
218#[derive(Debug)]
219pub enum ServerAddressError {
220    InvalidLength,
221}
222
223pub struct ServerAddress(pub(crate) [u32; 4]);
224
225impl TryFrom<&str> for ServerAddress {
226    type Error = ServerAddressError;
227    fn try_from(value: &str) -> Result<Self, Self::Error> {
228        let b = value.as_bytes();
229        if b.len() == 0 || b.len() > 16 {
230            return Err(Self::Error::InvalidLength);
231        }
232
233        let mut this_temp = [0u8; 16];
234        for (dest, src) in this_temp.iter_mut().zip(b.iter()) {
235            *dest = *src;
236        }
237
238        let mut this = [0u32; 4];
239        for (dest, src) in this.iter_mut().zip(this_temp.chunks_exact(4)) {
240            *dest = u32::from_le_bytes(src.try_into().unwrap());
241        }
242        Ok(ServerAddress(this))
243    }
244}
245
246impl Into<[u32; 4]> for ServerAddress {
247    fn into(self) -> [u32; 4] {
248        self.0
249    }
250}
251
252#[derive(Debug, Copy, Clone)]
253pub struct ThreadId(usize);
254
255impl From<usize> for ThreadId {
256    fn from(src: usize) -> ThreadId {
257        ThreadId(src)
258    }
259}
260
261impl Into<usize> for ThreadId {
262    fn into(self) -> usize {
263        self.0
264    }
265}
266
267#[derive(Copy, Clone)]
268#[repr(usize)]
269/// Limits that can be passed to `AdjustLimit`
270pub enum Limits {
271    HeapMaximum = 1,
272    HeapSize = 2,
273}