Thunking to real mode for interrupts
This commit is contained in:
+59
-2
@@ -1,8 +1,12 @@
|
||||
#![no_std]
|
||||
#![feature(asm)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(llvm_asm)]
|
||||
|
||||
use core::slice;
|
||||
use core::{
|
||||
ptr,
|
||||
slice,
|
||||
};
|
||||
|
||||
mod panic;
|
||||
|
||||
@@ -32,8 +36,61 @@ pub enum VgaTextColor {
|
||||
White = 15,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(packed)]
|
||||
pub struct ThunkData {
|
||||
di: u16,
|
||||
si: u16,
|
||||
bp: u16,
|
||||
sp: u16,
|
||||
bx: u16,
|
||||
dx: u16,
|
||||
cx: u16,
|
||||
ax: u16,
|
||||
}
|
||||
|
||||
impl ThunkData {
|
||||
pub const STACK: usize = 0x7C00;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
di: 0,
|
||||
si: 0,
|
||||
bp: 0,
|
||||
sp: Self::STACK as u16,
|
||||
bx: 0,
|
||||
dx: 0,
|
||||
cx: 0,
|
||||
ax: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn save(&self) {
|
||||
ptr::write((Self::STACK - 16) as *mut ThunkData, *self);
|
||||
}
|
||||
|
||||
pub unsafe fn load(&mut self) {
|
||||
*self = ptr::read((Self::STACK - 16) as *const ThunkData);
|
||||
}
|
||||
|
||||
pub unsafe fn with(&mut self, f: extern "C" fn()) {
|
||||
self.save();
|
||||
f();
|
||||
self.load();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kstart() -> ! {
|
||||
pub unsafe extern "C" fn kstart(
|
||||
thunk10: extern "C" fn(),
|
||||
thunk13: extern "C" fn(),
|
||||
) -> ! {
|
||||
{
|
||||
let mut data = ThunkData::new();
|
||||
data.ax = 0x03;
|
||||
data.with(thunk10);
|
||||
}
|
||||
|
||||
let vga = slice::from_raw_parts_mut(
|
||||
0xb8000 as *mut VgaTextBlock,
|
||||
80 * 25
|
||||
|
||||
+32
-6
@@ -10,12 +10,12 @@ startup_arch:
|
||||
mov cr0, eax
|
||||
|
||||
; far jump to load CS with 32 bit segment
|
||||
jmp gdt.kernel_code:protected_mode
|
||||
jmp gdt.pm32_code:protected_mode
|
||||
|
||||
USE32
|
||||
protected_mode:
|
||||
; load all the other segments with 32 bit data segments
|
||||
mov eax, gdt.kernel_data
|
||||
mov eax, gdt.pm32_data
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
@@ -25,6 +25,10 @@ protected_mode:
|
||||
mov esp, 0x800000 - 128
|
||||
|
||||
; entry point
|
||||
mov eax, thunk.int13
|
||||
push eax
|
||||
mov eax, thunk.int10
|
||||
push eax
|
||||
mov eax, [args.kernel_base]
|
||||
call [eax + 0x18]
|
||||
.halt:
|
||||
@@ -32,6 +36,8 @@ protected_mode:
|
||||
hlt
|
||||
jmp .halt
|
||||
|
||||
%include "thunk.asm"
|
||||
|
||||
gdtr:
|
||||
dw gdt.end + 1 ; size
|
||||
dd gdt ; offset
|
||||
@@ -40,23 +46,43 @@ gdt:
|
||||
.null equ $ - gdt
|
||||
dq 0
|
||||
|
||||
.kernel_code equ $ - gdt
|
||||
.pm32_code equ $ - gdt
|
||||
istruc GDTEntry
|
||||
at GDTEntry.limitl, dw 0xFFFF
|
||||
at GDTEntry.basel, dw 0
|
||||
at GDTEntry.basem, db 0
|
||||
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code | attrib.readable
|
||||
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||
at GDTEntry.flags__limith, db 0xF | flags.granularity | flags.default_operand_size
|
||||
at GDTEntry.baseh, db 0
|
||||
iend
|
||||
|
||||
.kernel_data equ $ - gdt
|
||||
.pm32_data equ $ - gdt
|
||||
istruc GDTEntry
|
||||
at GDTEntry.limitl, dw 0xFFFF
|
||||
at GDTEntry.basel, dw 0
|
||||
at GDTEntry.basem, db 0
|
||||
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
|
||||
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||
at GDTEntry.flags__limith, db 0xF | flags.granularity | flags.default_operand_size
|
||||
at GDTEntry.baseh, db 0
|
||||
iend
|
||||
|
||||
.pm16_code equ $ - gdt
|
||||
istruc GDTEntry
|
||||
at GDTEntry.limitl, dw 0xFFFF
|
||||
at GDTEntry.basel, dw 0
|
||||
at GDTEntry.basem, db 0
|
||||
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code | attrib.readable
|
||||
at GDTEntry.flags__limith, db 0xF
|
||||
at GDTEntry.baseh, db 0
|
||||
iend
|
||||
|
||||
.pm16_data equ $ - gdt
|
||||
istruc GDTEntry
|
||||
at GDTEntry.limitl, dw 0xFFFF
|
||||
at GDTEntry.basel, dw 0
|
||||
at GDTEntry.basem, db 0
|
||||
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
|
||||
at GDTEntry.flags__limith, db 0xF
|
||||
at GDTEntry.baseh, db 0
|
||||
iend
|
||||
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
USE32
|
||||
thunk:
|
||||
.int10:
|
||||
mov dword [.func], .int10_real
|
||||
jmp .enter
|
||||
|
||||
.int13:
|
||||
mov dword [.func], .int13_real
|
||||
jmp .enter
|
||||
|
||||
.func: dd 0
|
||||
.esp: dd 0
|
||||
.cr0: dd 0
|
||||
|
||||
.enter:
|
||||
; save flags
|
||||
pushfd
|
||||
|
||||
; save registers
|
||||
pushad
|
||||
|
||||
; save esp
|
||||
mov [.esp], esp
|
||||
|
||||
; far jump to protected mode 16-bit
|
||||
jmp gdt.pm16_code:.pm16
|
||||
|
||||
.exit:
|
||||
; set segment selectors to 32-bit protected mode
|
||||
mov eax, gdt.pm32_data
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ss, eax
|
||||
|
||||
; restore esp
|
||||
mov esp, [.esp]
|
||||
|
||||
; restore registers
|
||||
popad
|
||||
|
||||
; restore flags
|
||||
popfd
|
||||
|
||||
; return
|
||||
ret
|
||||
|
||||
USE16
|
||||
.int10_real:
|
||||
sti
|
||||
int 0x10
|
||||
cli
|
||||
; ret
|
||||
|
||||
.int13_real:
|
||||
sti
|
||||
int 0x13
|
||||
cli
|
||||
ret
|
||||
|
||||
.pm16:
|
||||
; set segment selectors to protected mode 16-bit
|
||||
mov eax, gdt.pm16_data
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ss, eax
|
||||
|
||||
; save cr0
|
||||
mov eax, cr0
|
||||
mov [.cr0], eax
|
||||
|
||||
; disable paging and protected mode
|
||||
and eax, 0x7FFFFFFE
|
||||
mov cr0, eax
|
||||
|
||||
; far jump to real mode
|
||||
jmp 0:.real
|
||||
|
||||
.real:
|
||||
; set segment selectors to real mode
|
||||
mov eax, 0
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ss, eax
|
||||
|
||||
; set stack
|
||||
mov esp, 0x7C00 - 16
|
||||
|
||||
; load registers
|
||||
popa
|
||||
|
||||
; call real mode function
|
||||
call [.func]
|
||||
|
||||
; save registers
|
||||
pusha
|
||||
|
||||
; restore cr0, will enable protected mode
|
||||
mov eax, [.cr0]
|
||||
mov cr0, eax
|
||||
|
||||
; far jump to protected mode 32-bit
|
||||
jmp gdt.pm32_code:.exit
|
||||
+1
-1
@@ -48,7 +48,7 @@ unreal_gdt:
|
||||
at GDTEntry.basel, dw 0x0
|
||||
at GDTEntry.basem, db 0x0
|
||||
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
|
||||
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||
at GDTEntry.flags__limith, db 0xF | flags.granularity | flags.default_operand_size
|
||||
at GDTEntry.baseh, db 0x0
|
||||
iend
|
||||
.end equ $ - unreal_gdt
|
||||
|
||||
Reference in New Issue
Block a user