moto_rt/
error.rs

1//! Common Motor OS error codes.
2pub type ErrorCode = u16;
3
4/// Motor OS system error.
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6#[repr(u16)]
7pub enum Error {
8    Ok = 0,
9    Unspecified = 1,
10    Unknown = 2,
11    NotReady = 3, // Main async error, similar to E_WOULD_BLOCK in Linux.
12    NotImplemented = 4,
13    VersionTooHigh = 5,
14    VersionTooLow = 6,
15    InvalidArgument = 7,
16    OutOfMemory = 8,
17    NotAllowed = 9,
18    NotFound = 10,
19    InternalError = 11,
20    TimedOut = 12,
21    AlreadyInUse = 13,
22    UnexpectedEof = 14,
23    InvalidFilename = 15,
24    NotADirectory = 16,
25    BadHandle = 17,
26    FileTooLarge = 18,
27    NotConnected = 19,
28    StorageFull = 20,
29    InvalidData = 21,
30
31    // Keep this value as the last one.
32    Max,
33}
34
35pub type Result<T> = core::result::Result<T, Error>;
36
37impl core::fmt::Display for Error {
38    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
39        core::fmt::Debug::fmt(self, f)
40    }
41}
42
43impl From<Error> for ErrorCode {
44    fn from(val: Error) -> ErrorCode {
45        val as ErrorCode
46    }
47}
48
49impl From<u16> for Error {
50    fn from(val: u16) -> Self {
51        if val < Error::Max.into() {
52            // Safety: safe because Error is repr(u16).
53            unsafe { core::mem::transmute::<u16, Error>(val) }
54        } else {
55            Error::Unknown
56        }
57    }
58}
59
60pub const E_OK: u16 = Error::Ok as u16;
61pub const E_UNSPECIFIED: u16 = Error::Unspecified as u16;
62pub const E_UNKNOWN: u16 = Error::Unknown as u16;
63pub const E_NOT_READY: u16 = Error::NotReady as u16;
64pub const E_NOT_IMPLEMENTED: u16 = Error::NotImplemented as u16;
65pub const E_VERSION_TOO_HIGH: u16 = Error::VersionTooHigh as u16;
66pub const E_VERSION_TOO_LOW: u16 = Error::VersionTooLow as u16;
67pub const E_INVALID_ARGUMENT: u16 = Error::InvalidArgument as u16;
68pub const E_OUT_OF_MEMORY: u16 = Error::OutOfMemory as u16;
69pub const E_NOT_ALLOWED: u16 = Error::NotAllowed as u16;
70pub const E_NOT_FOUND: u16 = Error::NotFound as u16;
71pub const E_INTERNAL_ERROR: u16 = Error::InternalError as u16;
72pub const E_TIMED_OUT: u16 = Error::TimedOut as u16;
73pub const E_ALREADY_IN_USE: u16 = Error::AlreadyInUse as u16;
74pub const E_UNEXPECTED_EOF: u16 = Error::UnexpectedEof as u16;
75pub const E_INVALID_FILENAME: u16 = Error::InvalidFilename as u16;
76pub const E_NOT_A_DIRECTORY: u16 = Error::NotADirectory as u16;
77pub const E_BAD_HANDLE: u16 = Error::BadHandle as u16;
78pub const E_FILE_TOO_LARGE: u16 = Error::FileTooLarge as u16;
79pub const E_NOT_CONNECTED: u16 = Error::NotConnected as u16;
80pub const E_STORAGE_FULL: u16 = Error::StorageFull as u16;
81pub const E_INVALID_DATA: u16 = Error::InvalidData as u16;
82
83pub const E_MAX: u16 = u16::MAX;
84
85#[cfg(not(feature = "base"))]
86pub fn log_to_kernel(msg: &str) {
87    let vdso_log_to_kernel: extern "C" fn(*const u8, usize) = unsafe {
88        core::mem::transmute(
89            super::RtVdsoVtable::get()
90                .log_to_kernel
91                .load(core::sync::atomic::Ordering::Relaxed) as usize as *const (),
92        )
93    };
94
95    let bytes = msg.as_bytes();
96    vdso_log_to_kernel(bytes.as_ptr(), bytes.len());
97}
98
99#[cfg(not(feature = "base"))]
100#[macro_export]
101macro_rules! moto_log {
102    ($($arg:tt)*) => {
103        {
104            #[allow(unused_extern_crates)]
105            extern crate alloc;
106            $crate::error::log_to_kernel(alloc::format!($($arg)*).as_str());
107        }
108    };
109}
110
111/// Log backtrace to rt_fd. If rt_fd is < 0, logs to the kernel log.
112#[cfg(not(feature = "base"))]
113pub fn log_backtrace(rt_fd: crate::RtFd) {
114    let vdso_log_backtrace: extern "C" fn(crate::RtFd) = unsafe {
115        core::mem::transmute(
116            super::RtVdsoVtable::get()
117                .log_backtrace
118                .load(core::sync::atomic::Ordering::Relaxed) as usize as *const (),
119        )
120    };
121
122    vdso_log_backtrace(rt_fd);
123}
124
125#[cfg(not(feature = "base"))]
126pub fn log_panic(info: &core::panic::PanicInfo<'_>) {
127    if crate::fs::is_terminal(crate::FD_STDERR) {
128        #[cfg(not(feature = "rustc-dep-of-std"))]
129        extern crate alloc;
130
131        let _ = crate::fs::write(crate::FD_STDERR, b"PANIC\n"); // Log w/o allocations.
132        let msg = alloc::format!("PANIC: {info}\n");
133        let _ = crate::fs::write(crate::FD_STDERR, msg.as_bytes());
134        log_backtrace(crate::FD_STDERR);
135    } else {
136        log_to_kernel("PANIC"); // Log w/o allocations.
137        moto_log!("PANIC: {}", info);
138        log_backtrace(-1);
139    }
140}
141
142#[cfg(not(feature = "base"))]
143pub fn into_result(val: ErrorCode) -> Result<()> {
144    if val == Error::Ok.into() {
145        Ok(())
146    } else {
147        Err(val.into())
148    }
149}
150
151#[cfg(not(feature = "base"))]
152#[macro_export]
153macro_rules! to_result {
154    ($arg:expr) => {{
155        let res = $arg;
156        if res < 0 {
157            Err(((-res) as ErrorCode).into())
158        } else {
159            Ok(unsafe { res.try_into().unwrap_unchecked() })
160        }
161    }};
162}