moto_rt/
error.rs

1//! Common Motor OS error codes.
2pub type ErrorCode = u16;
3
4pub const E_OK: u16 = 0;
5pub const E_UNSPECIFIED: u16 = 1;
6pub const E_UNKNOWN: u16 = 2;
7pub const E_NOT_READY: u16 = 3;
8pub const E_NOT_IMPLEMENTED: u16 = 5;
9pub const E_VERSION_TOO_HIGH: u16 = 6;
10pub const E_VERSION_TOO_LOW: u16 = 7;
11pub const E_INVALID_ARGUMENT: u16 = 8;
12pub const E_OUT_OF_MEMORY: u16 = 9;
13pub const E_NOT_ALLOWED: u16 = 10; // PERMISSION ERROR.
14pub const E_NOT_FOUND: u16 = 11;
15pub const E_INTERNAL_ERROR: u16 = 12;
16pub const E_TIMED_OUT: u16 = 13;
17pub const E_ALREADY_IN_USE: u16 = 14;
18pub const E_UNEXPECTED_EOF: u16 = 15;
19pub const E_INVALID_FILENAME: u16 = 16;
20pub const E_NOT_A_DIRECTORY: u16 = 17;
21pub const E_BAD_HANDLE: u16 = 18;
22pub const E_FILE_TOO_LARGE: u16 = 19;
23pub const E_BUFFER_FULL: u16 = 20;
24pub const E_NOT_CONNECTED: u16 = 21;
25
26pub const E_MAX: u16 = u16::MAX;
27
28#[cfg(not(feature = "base"))]
29pub fn log_to_kernel(msg: &str) {
30    let vdso_log_to_kernel: extern "C" fn(*const u8, usize) = unsafe {
31        core::mem::transmute(
32            super::RtVdsoVtable::get()
33                .log_to_kernel
34                .load(core::sync::atomic::Ordering::Relaxed) as usize as *const (),
35        )
36    };
37
38    let bytes = msg.as_bytes();
39    vdso_log_to_kernel(bytes.as_ptr(), bytes.len());
40}
41
42#[cfg(not(feature = "base"))]
43#[macro_export]
44macro_rules! moto_log {
45    ($($arg:tt)*) => {
46        {
47            extern crate alloc;
48            $crate::error::log_to_kernel(alloc::format!($($arg)*).as_str());
49        }
50    };
51}
52
53/// Log backtrace to rt_fd. If rt_fd is < 0, logs to the kernel log.
54#[cfg(not(feature = "base"))]
55pub fn log_backtrace(rt_fd: crate::RtFd) {
56    let vdso_log_backtrace: extern "C" fn(crate::RtFd) = unsafe {
57        core::mem::transmute(
58            super::RtVdsoVtable::get()
59                .log_backtrace
60                .load(core::sync::atomic::Ordering::Relaxed) as usize as *const (),
61        )
62    };
63
64    vdso_log_backtrace(rt_fd);
65}
66
67#[cfg(not(feature = "base"))]
68pub fn log_panic(info: &core::panic::PanicInfo<'_>) {
69    if moturus_log_panics_to_kernel() {
70        log_to_kernel("PANIC"); // Log w/o allocations.
71        moto_log!("PANIC: {}", info);
72        log_backtrace(-1);
73    } else {
74        #[cfg(not(feature = "rustc-dep-of-std"))]
75        extern crate alloc;
76
77        let _ = crate::fs::write(crate::FD_STDERR, b"PANIC\n"); // Log w/o allocations.
78        let msg = alloc::format!("PANIC: {}\n", info);
79        let _ = crate::fs::write(crate::FD_STDERR, msg.as_bytes());
80        log_backtrace(crate::FD_STDERR);
81    }
82}
83
84#[cfg(not(feature = "base"))]
85#[linkage = "weak"]
86#[no_mangle]
87pub extern "C" fn moturus_log_panics_to_kernel() -> bool {
88    // Normal binaries should log panics to their stderr. But sys-io, sys-tty, and sys-init
89    // don't have stdio, so they will override this function to log via SysMem::log().
90    false
91}
92
93#[cfg(not(feature = "base"))]
94pub fn ok_or_error(val: ErrorCode) -> Result<(), ErrorCode> {
95    if val == E_OK {
96        Ok(())
97    } else {
98        Err(val)
99    }
100}
101
102#[cfg(not(feature = "base"))]
103#[macro_export]
104macro_rules! to_result {
105    ($arg:expr) => {{
106        let res = $arg;
107        if res < 0 {
108            Err((-res) as ErrorCode)
109        } else {
110            Ok(unsafe { res.try_into().unwrap_unchecked() })
111        }
112    }};
113}