mini_loader/
lib.rs

1#![no_std]
2extern crate alloc;
3
4use alloc::string::ToString;
5use core::{ffi::c_int, fmt};
6use syscalls::{Sysno, raw_syscall};
7mod arch;
8
9/// Converts a raw syscall return value to a result.
10#[inline(always)]
11fn from_ret(value: usize, msg: &str) -> Result<usize, &str> {
12    if value > -4096isize as usize {
13        // Truncation of the error value is guaranteed to never occur due to
14        // the above check. This is the same check that musl uses:
15        // https://git.musl-libc.org/cgit/musl/tree/src/internal/syscall_ret.c?h=v1.1.15
16        return Err(msg);
17    }
18    Ok(value)
19}
20
21#[inline]
22pub fn print_char(c: char) {
23    // 将 char 转换为 UTF-8 字节序列(最多 4 字节)
24    let mut buffer = [0u8; 4];
25    let encoded = c.encode_utf8(&mut buffer);
26    let bytes = encoded.as_bytes();
27
28    unsafe {
29        from_ret(
30            raw_syscall!(Sysno::write, 1, bytes.as_ptr(), bytes.len()),
31            "print char failed",
32        )
33        .unwrap();
34    }
35}
36
37#[macro_export]
38macro_rules! println {
39    ($fmt: literal $(, $($arg: tt)+)?) => {
40        $crate::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?))
41    }
42}
43
44pub fn print(args: fmt::Arguments) {
45    let s = &args.to_string();
46    print_str(s);
47}
48
49#[inline]
50pub fn print_str(s: &str) {
51    unsafe {
52        from_ret(
53            raw_syscall!(Sysno::write, 1, s.as_ptr(), s.len()),
54            "print failed",
55        )
56        .unwrap();
57    }
58}
59
60pub fn exit(status: c_int) -> ! {
61    unsafe {
62        from_ret(raw_syscall!(Sysno::exit, status), "exit failed").unwrap();
63    }
64    unreachable!()
65}