ft(interpreter): impl file-based minix interrupts

This commit is contained in:
2025-07-24 11:42:15 +09:00
parent 75e9df9be9
commit b3a24ade00
4 changed files with 125 additions and 3 deletions

5
Cargo.lock generated
View File

@@ -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"

View File

@@ -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"

View File

@@ -943,6 +943,27 @@ impl Interpreter {
log::info!("<exit({})>", 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!("<read({:#04x}, {:#04x}, {:#04x})>", 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!("<open({:#04x}, {:#04x})>", 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!("<brk({:#04x})>", 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!("<lseek({:#04x}, {:#04x}, {:#04x})>", 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);

View File

@@ -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<String> {
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())
}
}