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) {
|
||||
let mut vga = VGA.lock();
|
||||
vga.clear();
|
||||
|
||||
Reference in New Issue
Block a user