BIOS: implement get_key_timeout with INT 16h/01h polling + INT 15h/86h delay
Fixes autoboot countdown blocking forever because the default trait impl calls blocking get_key(). Uses non-destructive key check (INT 16h AH=01h) with EDX sentinel to detect key availability without EFLAGS access, and INT 15h AH=86h for 10ms polling intervals.
This commit is contained in:
@@ -219,6 +219,54 @@ impl Os for OsBios {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_key_timeout(&self, milliseconds: usize) -> OsKey {
|
||||||
|
let mut remaining = milliseconds;
|
||||||
|
loop {
|
||||||
|
let mut check = ThunkData::new();
|
||||||
|
check.eax = 0x0100;
|
||||||
|
check.edx = 0xFFFF_FFFF;
|
||||||
|
unsafe {
|
||||||
|
check.with(self.thunk16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if check.edx != 0xFFFF_FFFF || check.eax != 0x0100 {
|
||||||
|
let mut data = ThunkData::new();
|
||||||
|
unsafe {
|
||||||
|
data.with(self.thunk16);
|
||||||
|
}
|
||||||
|
return match (data.eax >> 8) as u8 {
|
||||||
|
0x4B => OsKey::Left,
|
||||||
|
0x4D => OsKey::Right,
|
||||||
|
0x48 => OsKey::Up,
|
||||||
|
0x50 => OsKey::Down,
|
||||||
|
0x0E => OsKey::Backspace,
|
||||||
|
0x53 => OsKey::Delete,
|
||||||
|
0x1C => OsKey::Enter,
|
||||||
|
_ => match data.eax as u8 {
|
||||||
|
0 => OsKey::Other,
|
||||||
|
b => OsKey::Char(b as char),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if remaining == 0 {
|
||||||
|
return OsKey::Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
let step = 10.min(remaining);
|
||||||
|
|
||||||
|
let mut wait = ThunkData::new();
|
||||||
|
wait.eax = 0x8600;
|
||||||
|
wait.ecx = 0;
|
||||||
|
wait.edx = (step * 1000) as u32;
|
||||||
|
unsafe {
|
||||||
|
wait.with(self.thunk15);
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining -= step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn clear_text(&self) {
|
fn clear_text(&self) {
|
||||||
let mut vga = VGA.lock();
|
let mut vga = VGA.lock();
|
||||||
vga.clear();
|
vga.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user