cannon_io/syscalls/
mod.rs

1//! Low level access to syscalls that are understood by the minimal Cannon kernel
2//! Using these can be dangerous. Prefer to use the oracle_reader if possible
3
4use raw::{syscall1, syscall3};
5
6#[cfg(target_arch = "mips")]
7mod raw;
8// Provide a mock non-mips implementation so that rust-analyzer and cargo check work correctly
9#[cfg(not(target_arch = "mips"))]
10mod raw {
11    pub unsafe fn syscall1(_: u32, _: u32) -> u32 {
12        todo!("Crate can only work on MIPS target")
13    }
14    pub unsafe fn syscall3(_: u32, _: u32, _: u32, _: u32) -> Result<u32, i32> {
15        todo!("Crate can only work on MIPS target")
16    }
17}
18
19enum FileDescriptor {
20    StdOut = 1,
21    HintRead = 3,
22    HintWrite = 4,
23    PreimageRead = 5,
24    PreimageWrite = 6,
25}
26enum SyscallNo {
27    Exit = 4246,
28    Read = 4003,
29    Write = 4004,
30}
31
32#[derive(Debug)]
33pub enum SyscallError {
34    Code(u32),
35}
36
37impl From<i32> for SyscallError {
38    fn from(code: i32) -> Self {
39        SyscallError::Code(code as u32)
40    }
41}
42
43type Result<T> = core::result::Result<T, SyscallError>;
44
45pub fn print(s: &str) -> Result<u32> {
46    write(FileDescriptor::StdOut, s.as_bytes())
47}
48
49pub fn write_preimage(key: &[u8]) -> Result<u32> {
50    write(FileDescriptor::PreimageWrite, key)
51}
52
53pub fn read_preimage(out: &mut [u8]) -> Result<u32> {
54    read(FileDescriptor::PreimageRead, out)
55}
56
57pub fn write_hint(key: [u8; 32]) -> Result<u32> {
58    write(FileDescriptor::HintWrite, &key)
59}
60
61pub fn read_hint(out: &mut [u8]) -> Result<u32> {
62    read(FileDescriptor::HintRead, out)
63}
64
65pub fn exit(code: u8) -> ! {
66    unsafe {
67        syscall1(SyscallNo::Exit as u32, code.into());
68        panic!() // just to get the correct never return type
69    }
70}
71
72fn write(fd: FileDescriptor, buf: &[u8]) -> Result<u32> {
73    let result = unsafe {
74        syscall3(
75            SyscallNo::Write as u32,
76            fd as u32,
77            buf.as_ptr() as u32,
78            buf.len() as u32,
79        )
80    };
81    result.map_err(SyscallError::from)
82}
83
84fn read(fd: FileDescriptor, buf: &mut [u8]) -> Result<u32> {
85    let result = unsafe {
86        syscall3(
87            SyscallNo::Read as u32,
88            fd as u32,
89            buf.as_ptr() as u32,
90            buf.len() as u32,
91        )
92    };
93    result.map_err(SyscallError::from)
94}