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",
|
||||
"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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user