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    /// The operation completed successfully
36    Ok = 0,
37    /// An error was encountered, with the exact error stored in $a1
38    Error = 1,
39    /// A slice with the offset in $a1 and the length in $a2
40    MemoryRange = 3,
41    /// A `u32` connection ID stored in $a1
42    ConnectionId = 7,
43    /// A message was received
44    Message = 9,
45    /// A `u32` thread id stored in $a1
46    ThreadId = 10,
47    /// One scalar value, stored in $a1
48    Scalar1 = 14,
49    /// Two scalar values, stored in $a1 and $a2
50    Scalar2 = 15,
51    /// Memory that was returned from a syscall, with return values in $a1 and $a2
52    MemoryReturned = 18,
53    /// Five scalar values, stored in $a1..=$a5
54    Scalar5 = 20,
55}
56
57#[derive(Copy, Clone)]
58/// A list of all known errors that may be returned by the Xous kernel.
59#[repr(usize)]
60pub enum Error {
61    NoError = 0,
62    BadAlignment = 1,
63    BadAddress = 2,
64    OutOfMemory = 3,
65    MemoryInUse = 4,
66    InterruptNotFound = 5,
67    InterruptInUse = 6,
68    InvalidString = 7,
69    ServerExists = 8,
70    ServerNotFound = 9,
71    ProcessNotFound = 10,
72    ProcessNotChild = 11,
73    ProcessTerminated = 12,
74    Timeout = 13,
75    InternalError = 14,
76    ServerQueueFull = 15,
77    ThreadNotAvailable = 16,
78    UnhandledSyscall = 17,
79    InvalidSyscall = 18,
80    ShareViolation = 19,
81    InvalidThread = 20,
82    InvalidPid = 21,
83    UnknownError = 22,
84    AccessDenied = 23,
85    UseBeforeInit = 24,
86    DoubleFree = 25,
87    DebugInProgress = 26,
88    InvalidLimit = 27,
89    /// For lookups that result in not found (e.g., searching for keys, resources, names)
90    NotFound = 28,
91    /// Used when try_from/try_into can't map a number into a smaller number of options
92    InvalidCoding = 29,
93    /// Used for ECC errors, glitches, power failures, etc.
94    HardwareError = 30,
95    /// Used when buffers & messages fail to serialize or deserialize
96    SerializationError = 31,
97    /// Used when a call is correct but its arguments are out of bounds, invalid, or otherwise poorly
98    /// specified
99    InvalidArgument = 32,
100    /// Catch-all for networking related problems (unreachable network, etc.)
101    NetworkError = 33,
102    /// Catch-all for storage related problems (particularly write/read ECC errors)
103    StorageError = 34,
104    /// Catch-all for resources that are busy or already allocated
105    Unavailable = 35,
106    /// For failed parsing attempts
107    ParseError = 36,
108    /// Invalid core number on multi-core APIs
109    InvalidCore = 37,
110    /// Reports when verification/check steps fail. Thrown when correctly functioning algorithms determine
111    /// that an object is invalid.
112    VerificationError = 38,
113    /// Used to report higher-severity system security/integrity issues, such as glitch attacks, ECC errors,
114    /// memory violations, bad states for hardened bools. Note that bad passwords/credentials should use
115    /// "AccessDenied"
116    SecurityError = 39,
117}
118
119impl From<usize> for Error {
120    // Marking this function as "cold" ensures this error path
121    // does not get inlined.
122    #[cold]
123    fn from(src: usize) -> Self {
124        match src {
125            0 => Self::NoError,
126            1 => Self::BadAlignment,
127            2 => Self::BadAddress,
128            3 => Self::OutOfMemory,
129            4 => Self::MemoryInUse,
130            5 => Self::InterruptNotFound,
131            6 => Self::InterruptInUse,
132            7 => Self::InvalidString,
133            8 => Self::ServerExists,
134            9 => Self::ServerNotFound,
135            10 => Self::ProcessNotFound,
136            11 => Self::ProcessNotChild,
137            12 => Self::ProcessTerminated,
138            13 => Self::Timeout,
139            14 => Self::InternalError,
140            15 => Self::ServerQueueFull,
141            16 => Self::ThreadNotAvailable,
142            17 => Self::UnhandledSyscall,
143            18 => Self::InvalidSyscall,
144            19 => Self::ShareViolation,
145            20 => Self::InvalidThread,
146            21 => Self::InvalidPid,
147            // 22 is UnknownError
148            23 => Self::AccessDenied,
149            24 => Self::UseBeforeInit,
150            25 => Self::DoubleFree,
151            26 => Self::DebugInProgress,
152            27 => Self::InvalidLimit,
153            28 => Self::NotFound,
154            29 => Self::InvalidCoding,
155            30 => Self::HardwareError,
156            31 => Self::SerializationError,
157            32 => Self::InvalidArgument,
158            33 => Self::NetworkError,
159            34 => Self::StorageError,
160            35 => Self::Unavailable,
161            36 => Self::ParseError,
162            37 => Self::InvalidCore,
163            38 => Self::VerificationError,
164            39 => Self::SecurityError,
165            _ => Self::UnknownError,
166        }
167    }
168}
169
170impl From<i32> for Error {
171    #[cold]
172    fn from(src: i32) -> Self {
173        let Ok(src) = core::convert::TryInto::<usize>::try_into(src) else {
174            return Self::UnknownError;
175        };
176        src.into()
177    }
178}
179
180impl core::fmt::Display for Error {
181    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182        write!(
183            f,
184            "{}",
185            match self {
186                Error::NoError => "no error occurred",
187                Error::BadAlignment => "memory was not properly aligned",
188                Error::BadAddress => "an invalid address was supplied",
189                Error::OutOfMemory => "the process or service has run out of memory",
190                Error::MemoryInUse => "the requested address is in use",
191                Error::InterruptNotFound =>
192                    "the requested interrupt does not exist on this platform",
193                Error::InterruptInUse => "the requested interrupt is currently in use",
194                Error::InvalidString => "the specified string was not formatted correctly",
195                Error::ServerExists => "a server with that address already exists",
196                Error::ServerNotFound => "the requetsed server could not be found",
197                Error::ProcessNotFound => "the target process does not exist",
198                Error::ProcessNotChild =>
199                    "the requested operation can only be done on child processes",
200                Error::ProcessTerminated => "the target process has crashed",
201                Error::Timeout => "the requested operation timed out",
202                Error::InternalError => "an internal error occurred",
203                Error::ServerQueueFull => "the server has too many pending messages",
204                Error::ThreadNotAvailable => "the specified thread does not exist",
205                Error::UnhandledSyscall => "the kernel did not recognize that syscall",
206                Error::InvalidSyscall => "the syscall had incorrect parameters",
207                Error::ShareViolation => "an attempt was made to share memory twice",
208                Error::InvalidThread => "tried to resume a thread that was not ready",
209                Error::InvalidPid => "kernel attempted to use a pid that was not valid",
210                Error::AccessDenied => "no permission to perform the requested operation",
211                Error::UseBeforeInit => "attempt to use a service before initialization finished",
212                Error::DoubleFree => "the requested resource was freed twice",
213                Error::DebugInProgress => "kernel attempted to activate a thread being debugged",
214                Error::InvalidLimit => "process attempted to adjust an invalid limit",
215                Error::NotFound => "resource or name not found",
216                Error::InvalidCoding => "can't map argument onto a valid coding",
217                Error::HardwareError => "hardware error",
218                Error::SerializationError => "can't (de)serialize buffer or struct",
219                Error::InvalidArgument => "invalid, out of bounds, or poorly specified argument(s)",
220                Error::NetworkError => "network error",
221                Error::StorageError => "storage error",
222                Error::Unavailable => "resources busy or already allocated",
223                Error::ParseError => "parse error",
224                Error::InvalidCore => "invalid core",
225                Error::VerificationError => "verification or integrity check failure on object",
226                Error::SecurityError => "security or system integrity error",
227                Error::UnknownError => "an unknown error occurred",
228            }
229        )
230    }
231}
232
233impl core::fmt::Debug for Error {
234    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
235        write!(f, "{}", self)
236    }
237}
238
239impl core::error::Error for Error {}
240
241/// Indicates the type of Message that is sent when making a `SendMessage` syscall.
242pub enum InvokeType {
243    /// Mutably lend the buffer to the server
244    LendMut = 1,
245    /// Immutably lend
246    Lend = 2,
247    #[cfg(feature = "unstable_mem")]
248    /// Move the buffer from this process into the server
249    Move = 3,
250    /// Send a scalar message to the server without blocking
251    Scalar = 4,
252    /// Send a scalar message to the server and wait for a reply
253    BlockingScalar = 5,
254}
255
256#[derive(Debug, Copy, Clone)]
257/// A representation of a connection to a Xous service.
258pub struct Connection(pub(crate) u32);
259
260impl From<u32> for Connection {
261    fn from(src: u32) -> Connection {
262        Connection(src)
263    }
264}
265
266impl TryFrom<usize> for Connection {
267    type Error = core::num::TryFromIntError;
268    fn try_from(src: usize) -> Result<Self, Self::Error> {
269        Ok(Connection(src.try_into()?))
270    }
271}
272
273impl Into<u32> for Connection {
274    fn into(self) -> u32 {
275        self.0
276    }
277}
278
279impl TryInto<usize> for Connection {
280    type Error = core::num::TryFromIntError;
281    fn try_into(self) -> Result<usize, Self::Error> {
282        self.0.try_into()
283    }
284}
285
286#[derive(Debug)]
287/// The specified Server address could not be parsed
288pub enum ServerAddressError {
289    /// the length was not 16 bytes
290    InvalidLength,
291}
292
293pub struct ServerAddress(pub(crate) [u32; 4]);
294
295impl TryFrom<&str> for ServerAddress {
296    type Error = ServerAddressError;
297    fn try_from(value: &str) -> Result<Self, Self::Error> {
298        let b = value.as_bytes();
299        if b.len() == 0 || b.len() > 16 {
300            return Err(Self::Error::InvalidLength);
301        }
302
303        let mut this_temp = [0u8; 16];
304        for (dest, src) in this_temp.iter_mut().zip(b.iter()) {
305            *dest = *src;
306        }
307
308        let mut this = [0u32; 4];
309        for (dest, src) in this.iter_mut().zip(this_temp.chunks_exact(4)) {
310            *dest = u32::from_le_bytes(src.try_into().unwrap());
311        }
312        Ok(ServerAddress(this))
313    }
314}
315
316impl Into<[u32; 4]> for ServerAddress {
317    fn into(self) -> [u32; 4] {
318        self.0
319    }
320}
321
322#[derive(Debug, Copy, Clone)]
323pub struct ThreadId(usize);
324
325impl From<usize> for ThreadId {
326    fn from(src: usize) -> ThreadId {
327        ThreadId(src)
328    }
329}
330
331impl Into<usize> for ThreadId {
332    fn into(self) -> usize {
333        self.0
334    }
335}
336
337#[derive(Copy, Clone)]
338#[repr(usize)]
339/// Limits that can be passed to `AdjustLimit`
340pub enum Limits {
341    HeapMaximum = 1,
342    HeapSize = 2,
343}