stage1: support 32-bit registers for BIOS calls
This commit is contained in:
parent
bbe3375b8a
commit
68f56352ad
2 changed files with 49 additions and 43 deletions
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
/* fn __do_bios_int(regs: &mut BiosIntRegs) -> u8 */
|
||||
GLOBL __do_bios_int
|
||||
pushal // '1 v
|
||||
pushal // '1 (4 -> 36)
|
||||
|
||||
/*
|
||||
* Move the `regs` parameter into %ebp. `call` pushes one longword
|
||||
|
@ -18,21 +18,24 @@ GLOBL __do_bios_int
|
|||
*/
|
||||
mov 36(%esp), %ebp
|
||||
/* now load all registers with their desired values */
|
||||
mov (%ebp), %ax
|
||||
mov 2(%ebp), %cx
|
||||
mov 4(%ebp), %dx
|
||||
mov 6(%ebp), %bx
|
||||
mov 8(%ebp), %si
|
||||
mov 10(%ebp), %di
|
||||
mov 24(%ebp), %eax
|
||||
push %eax /* %ds and %es */ // '2 (36 -> 40)
|
||||
mov (%ebp), %eax
|
||||
mov 4(%ebp), %ecx
|
||||
mov 8(%ebp), %edx
|
||||
mov 12(%ebp), %ebx
|
||||
mov 16(%ebp), %esi
|
||||
mov 20(%ebp), %edi
|
||||
|
||||
push %ebp // '2 v
|
||||
|
||||
push %eax // '3 v
|
||||
push %edx // '4 v
|
||||
push %eax // '3 (40 -> 44)
|
||||
push %edx // '4 (44 -> 48)
|
||||
call prot_to_real
|
||||
.code16
|
||||
pop %edx // '4 ^
|
||||
pop %eax // '3 ^
|
||||
pop %edx // '4 (44 <- 48)
|
||||
pop %eax // '3 (40 <- 44)
|
||||
|
||||
pop %es // '2 (38 <- 40)
|
||||
pop %ds // '2 (36 <- 38)
|
||||
|
||||
/* call that polymorphism! */
|
||||
.byte 0xcd /* opcode for `int imm8` */
|
||||
|
@ -41,27 +44,34 @@ GLOBL __bios_int_number, object
|
|||
|
||||
/* be careful not to touch EFLAGS now because that's our return value */
|
||||
|
||||
push %eax // '3 v
|
||||
push %edx // '4 v
|
||||
pushfl // '5 v
|
||||
push %ds // '2 (36 -> 38)
|
||||
push %es // '2 (38 -> 40)
|
||||
|
||||
push %eax // '3 (40 -> 44)
|
||||
push %edx // '4 (44 -> 48)
|
||||
pushfl // '5 (48 -> 52)
|
||||
call real_to_prot
|
||||
.code32
|
||||
popfl // '5 ^
|
||||
pop %edx // '4 ^
|
||||
pop %eax // '3 ^
|
||||
popfl // '5 (48 <- 52)
|
||||
pop %edx // '4 (44 <- 48)
|
||||
pop %eax // '3 (40 <- 44)
|
||||
|
||||
pop %ebp // '2 ^
|
||||
/* the BIOS call might have trashed %ebp, restore it */
|
||||
mov 40(%esp), %ebp
|
||||
|
||||
mov %ax, (%ebp)
|
||||
mov %cx, 2(%ebp)
|
||||
mov %dx, 4(%ebp)
|
||||
mov %bx, 6(%ebp)
|
||||
mov %si, 8(%ebp)
|
||||
mov %di, 10(%ebp)
|
||||
mov %eax, (%ebp)
|
||||
pop %eax // '2 (36 <- 40)
|
||||
mov %eax, 24(%ebp)
|
||||
mov %ecx, 4(%ebp)
|
||||
mov %edx, 8(%ebp)
|
||||
mov %ebx, 12(%ebp)
|
||||
mov %esi, 16(%ebp)
|
||||
mov %edi, 20(%ebp)
|
||||
|
||||
popal // '1 ^
|
||||
popal // '1 (4 <- 36)
|
||||
setc %al
|
||||
/* this is not really required, but just in case */
|
||||
movzbl %al, %eax
|
||||
ret
|
||||
|
||||
ret //'0 (0 <- 4)
|
||||
END __do_bios_int
|
||||
|
|
|
@ -18,11 +18,6 @@ include_asm!("common.s");
|
|||
|
||||
// stage1 header containing its magic, size, checksum, and entry point
|
||||
include_asm!("header.s");
|
||||
extern "C" {
|
||||
pub static _stage1_magic: u16;
|
||||
pub static _stage1_len: u16;
|
||||
pub static _stage1_csum: u32;
|
||||
}
|
||||
|
||||
// main bootstrap routine that calls the rust entry point
|
||||
include_asm!("boot.s");
|
||||
|
@ -53,21 +48,22 @@ extern "C" {
|
|||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct BiosIntRegs {
|
||||
pub ax: u16,
|
||||
pub cx: u16,
|
||||
pub dx: u16,
|
||||
pub bx: u16,
|
||||
pub si: u16,
|
||||
pub di: u16,
|
||||
pub eax: u32,
|
||||
pub ecx: u32,
|
||||
pub edx: u32,
|
||||
pub ebx: u32,
|
||||
pub esi: u32,
|
||||
pub edi: u32,
|
||||
pub ds: u16,
|
||||
pub es: u16,
|
||||
}
|
||||
|
||||
pub type BiosResult = Result<BiosIntRegs, BiosIntRegs>;
|
||||
|
||||
/// Temporarily return to Real Mode and do a BIOS interrupt with the
|
||||
/// specified register values. Returns `Ok` if the carry flag was
|
||||
/// clear after the interrupt, and `Err` if it was set. In either
|
||||
/// case, the wrapped value contains the state of the registers after
|
||||
/// the interrupt.
|
||||
/// specified register values. Returns `Ok` if the carry flag was clear
|
||||
/// after the interrupt, and `Err` if it was set. In either case, the
|
||||
/// wrapped value contains the state of the registers after the interrupt.
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue