ft(interpreter): impl file-based minix interrupts
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -152,6 +152,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"env",
|
"env",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -187,9 +188,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.172"
|
version = "0.2.174"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ edition = "2024"
|
|||||||
clap = { version = "4.5.37", features = ["derive"] }
|
clap = { version = "4.5.37", features = ["derive"] }
|
||||||
env = "1.0.1"
|
env = "1.0.1"
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.8"
|
||||||
|
libc = "0.2.174"
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
|
|||||||
@@ -943,6 +943,27 @@ impl Interpreter {
|
|||||||
log::info!("<exit({})>", status);
|
log::info!("<exit({})>", status);
|
||||||
exit(status.into())
|
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()
|
// WRITE()
|
||||||
0x04 => {
|
0x04 => {
|
||||||
let data = Mess1::new(&data);
|
let data = Mess1::new(&data);
|
||||||
@@ -962,8 +983,67 @@ impl Interpreter {
|
|||||||
// TODO: save messages as pointer to remove this hack
|
// TODO: save messages as pointer to remove this hack
|
||||||
self.computer.write(len.into(), (bx + 2).into())?;
|
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 => {
|
0x11 => {
|
||||||
|
// TODO: use mess struct
|
||||||
let bx = self.computer.regs.bx.read();
|
let bx = self.computer.regs.bx.read();
|
||||||
let addr = self.computer.read((bx + 10).into())?;
|
let addr = self.computer.read((bx + 10).into())?;
|
||||||
log::info!("<brk({:#04x})>", addr);
|
log::info!("<brk({:#04x})>", addr);
|
||||||
@@ -976,6 +1056,23 @@ impl Interpreter {
|
|||||||
self.computer
|
self.computer
|
||||||
.write(ImmediateOperand::Word(0), (bx + 2).into())?;
|
.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()
|
// IOCTL()
|
||||||
0x36 => {
|
0x36 => {
|
||||||
let data = Mess2::new(&data);
|
let data = Mess2::new(&data);
|
||||||
|
|||||||
@@ -62,4 +62,27 @@ impl Memory {
|
|||||||
log::debug!("Read raw byte {b1:#04x} and {b2:#04x}, starting at addr {addr:#04x}");
|
log::debug!("Read raw byte {b1:#04x} and {b2:#04x}, starting at addr {addr:#04x}");
|
||||||
Ok(Word::from_le_bytes([b1, b2]))
|
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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user