moto_sys/
lib.rs

1#![no_std]
2#![feature(core_intrinsics)]
3#![feature(naked_functions)]
4#![allow(internal_features)]
5
6// Syscalls.
7pub mod caps;
8pub mod stats;
9pub mod syscalls;
10pub use syscalls::SysHandle;
11
12#[cfg(feature = "userspace")]
13pub mod time;
14
15#[cfg(not(feature = "rustc-dep-of-std"))]
16extern crate alloc;
17use alloc::string::String;
18
19// Kernel/usperspace shared memory.
20mod shared_mem;
21pub use shared_mem::*;
22
23#[cfg(feature = "userspace")]
24pub fn align_up(addr: u64, align: u64) -> u64 {
25    assert!(align.is_power_of_two(), "`align` must be a power of two");
26    let align_mask = align - 1;
27    if addr & align_mask == 0 {
28        addr // already aligned
29    } else {
30        (addr | align_mask) + 1
31    }
32}
33
34// #[cfg(not(feature = "rustc-dep-of-std"))]
35pub fn url_encode(url: &str) -> String {
36    // Replace ':' with '&col'; '=' with '&eq'; '&' with '&'.
37    let amps = url.replace('&', "&");
38    let cols = amps.replace(':', "&col;");
39
40    cols.replace('=', "&eq;")
41}
42
43#[cfg(not(feature = "rustc-dep-of-std"))]
44pub fn url_decode(encoded: &str) -> String {
45    let eqs = encoded.replace("&eq;", "=");
46    let cols = eqs.replace("&col;", ":");
47
48    cols.replace("&", "&")
49}
50
51/*
52#[cfg(feature = "userspace")]
53pub fn utid() -> u64 {
54    let mut fsbase: u64;
55    unsafe {
56        core::arch::asm!("rdfsbase {}", out(reg) fsbase, options(nostack, preserves_flags));
57    }
58
59    fsbase
60}
61*/
62
63#[cfg(feature = "userspace")]
64pub fn __utid() -> u64 {
65    shared_mem::UserThreadControlBlock::__utid()
66}
67
68#[cfg(feature = "userspace")]
69pub fn current_cpu() -> u32 {
70    shared_mem::UserThreadControlBlock::get().current_cpu
71}
72
73#[cfg(feature = "userspace")]
74pub fn num_cpus() -> u32 {
75    KernelStaticPage::get().num_cpus
76}
77
78// Most system-level APIs (syscalls, IO drivers) return 16-bit error codes
79// to make things simple (errno works well enough in Linux/POSIX).
80// Applications that want to use more sophisticated errors are free to do that.
81#[repr(u16)]
82#[derive(Clone, Copy, Debug, PartialEq, Eq)]
83pub enum ErrorCode {
84    Ok = 0,
85    UnspecifiedError = 1, // A generic error.
86    UnknownError = 2,     // Should only be used in from_u16() below.
87    NotReady = 3,
88    NotImplemented = 5,
89    VersionTooHigh = 6,
90    VersionTooLow = 7,
91    InvalidArgument = 8,
92    OutOfMemory = 9,
93    NotAllowed = 10, // Permission error.
94    NotFound = 11,
95    InternalError = 12,
96    TimedOut = 13,
97    AlreadyInUse = 14,
98    UnexpectedEof = 15,
99    InvalidFilename = 16,
100    NotADirectory = 17,
101    BadHandle = 18,
102    FileTooLarge = 19,
103
104    MaxKernelError, // Must be last, so that from_u16() below works.
105}
106
107impl ErrorCode {
108    pub fn is_ok(&self) -> bool {
109        *self == ErrorCode::Ok
110    }
111
112    pub fn is_err(&self) -> bool {
113        *self != ErrorCode::Ok
114    }
115
116    pub fn from_u16(val: u16) -> Self {
117        if val >= Self::MaxKernelError as u16 {
118            Self::UnknownError
119        } else {
120            unsafe { core::mem::transmute(val) }
121        }
122    }
123}
124
125impl From<ErrorCode> for u16 {
126    fn from(value: ErrorCode) -> Self {
127        value as u16
128    }
129}
130
131impl From<u16> for ErrorCode {
132    fn from(value: u16) -> Self {
133        Self::from_u16(value)
134    }
135}