From d336c4af7d295dc04a2c01794353359577b5c055 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Fri, 14 Mar 2025 21:33:00 +0100 Subject: [PATCH] more syscalls --- src/main.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index ecf03be..3178e89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,9 +54,37 @@ fn ecall_handler( let nr = xreg[Reg::A7.0 as usize]; let arg0 = xreg[Reg::A0.0 as usize]; + let arg1 = xreg[Reg::A1.0 as usize]; + let arg2 = xreg[Reg::A2.0 as usize]; // https://jborza.com/post/2021-05-11-riscv-linux-syscalls/ + // https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/unistd.h match nr { + // ioctl + 29 => { + let fd = arg0; + let request = arg1; + + match request { + // TIOCGWINSZ + 0x5413 => { + let wsz_ptr = xreg[Reg::A2.0 as usize]; + + let mut wsz: libc::winsize = unsafe { std::mem::zeroed() }; + + let r = unsafe { libc::ioctl(fd as i32, libc::TIOCGWINSZ, &mut wsz) }; + + xreg[Reg::A0.0 as usize] = r as u32; + if r >= 0 { + mem.store_u16(wsz_ptr, wsz.ws_row)?; + mem.store_u16(wsz_ptr + 2, wsz.ws_col)?; + mem.store_u16(wsz_ptr + 4, wsz.ws_xpixel)?; + mem.store_u16(wsz_ptr + 6, wsz.ws_ypixel)?; + } + } + _ => todo!("unknown ioctl: {request}"), + } + } // read 63 => { let fd = arg0; @@ -91,8 +119,39 @@ fn ecall_handler( xreg[Reg::A0.0 as usize] = ret; } - // exit - 93 => { + // https://man7.org/linux/man-pages/man3/writev.3p.html + 66 => { + let fd = arg0; + let iovec = arg1; + let iovcnt = arg2; + + let mut written = 0; + + for i in 0..iovcnt { + let iov_ptr = mem.load_u32(iovec + i * 8)?; + let iov_len = mem.load_u32(iovec + i * 8 + 4)?; + + let data = mem.slice(iov_ptr, iov_len)?; + + let len = unsafe { libc::write(fd as i32, data.as_ptr().cast(), data.len()) }; + let ret = if len < 0 { + (-std::io::Error::last_os_error().raw_os_error().unwrap_or(1)) as u32 + } else { + len as u32 + }; + + if (ret as i32) < 0 { + xreg[Reg::A0.0 as usize] = ret; + return Ok(()); + } else { + written += ret; + } + } + + xreg[Reg::A0.0 as usize] = written; + } + // exit | exit_group + 93 | 94 => { return Err(emu::Status::Exit { code: xreg[Reg::A0.0 as usize] as i32, }); @@ -104,6 +163,14 @@ fn ecall_handler( xreg[Reg::A0.0 as usize] = 1; // thread ID } + // ppoll - called for some stdin/stdout/stderr check. + 414 => { + // musl uses ppoll to batch check whether FDs 0,1,2 are invalid, + // and opens /dev/null for them if they are. + // They're always valid here, so just get out. + + xreg[Reg::A0.0 as usize] = 0; + } _ => { todo!("unkonwn syscall: {nr}"); }