From b3a24ade0040ab5ba4d824fc163d1673dbc5bf9b Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Thu, 24 Jul 2025 11:42:15 +0900 Subject: [PATCH] ft(interpreter): impl file-based minix interrupts --- Cargo.lock | 5 +- Cargo.toml | 1 + src/interpreter/interpreter.rs | 99 +++++++++++++++++++++++++++++++++- src/interpreter/memory.rs | 23 ++++++++ 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1af0f32..aa03f86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,6 +152,7 @@ dependencies = [ "clap", "env", "env_logger", + "libc", "log", ] @@ -187,9 +188,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "log" diff --git a/Cargo.toml b/Cargo.toml index 462b4b0..ac2a15e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2024" clap = { version = "4.5.37", features = ["derive"] } env = "1.0.1" env_logger = "0.11.8" +libc = "0.2.174" log = "0.4.27" diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index 21d99ae..0526042 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -943,6 +943,27 @@ impl Interpreter { log::info!("", status); exit(status.into()) } + // READ() + 0x03 => { + let data = Mess1::new(&data); + let fd = data.i1; + let len = data.i2 as usize; + let addr = data.p1 as usize; + + log::debug!("Reading from fd {fd}"); + + log::info!("", fd, addr, len); + + let buf: &mut _ = &mut self.computer.memory.raw[addr..addr + len]; + + let _ = unsafe { + libc::read(fd as i32, buf.as_mut_ptr() as *mut libc::c_void, len) + }; + + // m_type response + // TODO: save messages as pointer to remove this hack + self.computer.write(len.into(), (bx + 2).into())?; + } // WRITE() 0x04 => { let data = Mess1::new(&data); @@ -962,8 +983,67 @@ impl Interpreter { // TODO: save messages as pointer to remove this hack self.computer.write(len.into(), (bx + 2).into())?; } - // TODO: BRK + // OPEN() + 0x05 => { + let data = Mess1::new(&data); + let _len = data.i1; + let flag = data.i2; + #[allow(unused_assignments)] + let mut ret = 0; + + fn minix_open(computer: &mut Computer, flag: Word, addr: Word) -> i32 { + log::info!("", addr, flag); + + let path = computer.memory.read_c_string(addr as usize).unwrap(); + + log::debug!("Read string from memory: {path}"); + + let c_path = std::ffi::CString::new(path).unwrap(); + + log::debug!("Path is: {c_path:?}"); + + let fd = unsafe { libc::open(c_path.as_ptr(), flag.into()) }; + + log::debug!("fd is {fd}"); + + fd + } + + // O_CREAT + if flag == 00100 { + log::debug!("O_CREAT"); + let _mode = data.i3; + let addr = data.p1; + ret = minix_open(&mut self.computer, flag, addr); + } else { + // let addr = if len <= 14 { + // self.computer.regs.bx.read() + 10 + // } else { + let addr = data.i3; + // }; + ret = minix_open(&mut self.computer, flag, addr); + } + + // m_type response + // TODO: save messages as pointer to remove this hack + if ret == -1 { + self.computer + .write(ImmediateOperand::Word(0), (bx + 2).into())?; + } else { + log::debug!("Writing fd {} into reply", ret as Word); + self.computer + .write(ImmediateOperand::Word(ret as Word), (bx + 2).into())?; + } + } + // CLOSE() + 0x06 => { + let data = Mess1::new(&data); + let fd = data.i1; + let _ = unsafe { libc::close(fd.into()) }; + } + // BRK 0x11 => { + // TODO: use mess struct let bx = self.computer.regs.bx.read(); let addr = self.computer.read((bx + 10).into())?; log::info!("", addr); @@ -976,6 +1056,23 @@ impl Interpreter { self.computer .write(ImmediateOperand::Word(0), (bx + 2).into())?; } + // LSEEK() + 0x13 => { + let data = Mess2::new(&data); + let fd = data.i1; + let offset = data.l1; + let whence = data.i2; + log::info!("", fd, offset, whence); + let ret = unsafe { libc::lseek(fd.into(), offset.into(), whence.into()) }; + // m_type response + // TODO: save messages as pointer to remove this hack + self.computer + .write(ImmediateOperand::Word(0), (bx + 2).into())?; + if ret == -1 { + self.computer + .write(ImmediateOperand::Word(ret as Word), (bx + 10).into())?; + } + } // IOCTL() 0x36 => { let data = Mess2::new(&data); diff --git a/src/interpreter/memory.rs b/src/interpreter/memory.rs index ced6d78..8b19f40 100644 --- a/src/interpreter/memory.rs +++ b/src/interpreter/memory.rs @@ -62,4 +62,27 @@ impl Memory { log::debug!("Read raw byte {b1:#04x} and {b2:#04x}, starting at addr {addr:#04x}"); Ok(Word::from_le_bytes([b1, b2])) } + + /// Try to read C null-terminated string from memory location + /// BUG: This does not use segment registers for indexing! + pub fn read_c_string(&self, addr: usize) -> Option { + let mem = &self.raw; + + if addr >= mem.len() { + return None; + } + + let raw = &mem[addr..]; + + log::debug!("Raw is {:?}", &raw[..=16]); + + let nul_pos = raw.iter().position(|&b| b == 0)?; + + log::debug!("Starting to read at {addr} until {nul_pos}"); + + let c_slice = &raw[..=nul_pos]; + let c_str = std::ffi::CStr::from_bytes_with_nul(c_slice).ok()?; + + c_str.to_str().ok().map(|s| s.to_owned()) + } }