refactor + wip bios call from protected mode
parent
121e13165b
commit
766a9c981c
@ -0,0 +1,169 @@
|
||||
%include "defines.s"
|
||||
|
||||
extern gdt_flat_slice
|
||||
extern gdt_flat
|
||||
extern GDT_FLAT_IDX_CODE_32
|
||||
extern GDT_FLAT_IDX_CODE_16
|
||||
extern GDT_FLAT_IDX_DATA
|
||||
|
||||
|
||||
section .text
|
||||
|
||||
[bits 32]
|
||||
|
||||
; FIXME: use a separate stack for real mode
|
||||
bios_call:
|
||||
.PARAMS_START equ 36
|
||||
.PARAM_BIOS_INTR_NUM equ .PARAMS_START
|
||||
.PARAM_BIOS_INTR_ARGS_PTR equ .PARAMS_START + 4
|
||||
|
||||
pushad
|
||||
mov ebp, esp
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
push ss
|
||||
|
||||
; Push cr0, the GDT and the IDT to the stack so we can restore them once we're finished with real mode.
|
||||
mov eax, cr0
|
||||
push eax
|
||||
sub esp, 8
|
||||
sidt [esp]
|
||||
sub esp, 8
|
||||
sgdt [esp]
|
||||
|
||||
; Load the address of the `int` instruction we want to run, and store it on the stack for later.
|
||||
mov eax, [ebp + .PARAM_BIOS_INTR_NUM]
|
||||
lea eax, [int_fns + (3 * eax)]
|
||||
push eax
|
||||
|
||||
; Copy the BIOS call arguments provided by the caller onto the stack, for us to pop later.
|
||||
sub esp, 28
|
||||
mov ecx, 28
|
||||
mov esi, [ebp + .PARAM_BIOS_INTR_ARGS_PTR]
|
||||
mov edi, esp
|
||||
rep movsb
|
||||
|
||||
; Switch to a 16-bit code segment, but remain in protected mode.
|
||||
jmp GDT_FLAT_IDX_CODE_16:.protected_mode_16
|
||||
|
||||
[bits 16]
|
||||
.protected_mode_16:
|
||||
|
||||
; Disable paging and protected mode.
|
||||
mov eax, cr0
|
||||
and eax, 0x7ffffffe
|
||||
mov cr0, eax
|
||||
|
||||
jmp 0:.real_mode
|
||||
|
||||
.real_mode:
|
||||
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
; Load the caller-provided register values off the stack.
|
||||
pop eax
|
||||
pop ebx
|
||||
pop ecx
|
||||
pop edx
|
||||
pop esi
|
||||
pop edi
|
||||
pop ds
|
||||
pop es
|
||||
|
||||
; Call the function which runs the correct `int` instruction.
|
||||
push bp
|
||||
mov bp, sp
|
||||
call [bp + 2]
|
||||
pop bp
|
||||
|
||||
; TODO: return resulting registers to the caller
|
||||
|
||||
; Reset the segment registers that were changed to the caller-provided values.
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
; Reload the GDT in case the BIOS call changed it.
|
||||
mov bx, sp
|
||||
lgdt [bx]
|
||||
add sp, 8
|
||||
|
||||
mov bx, sp
|
||||
lidt [bx]
|
||||
add sp, 8
|
||||
|
||||
; Restore cr0, re-enabling protected mode.
|
||||
pop eax
|
||||
mov cr0, eax
|
||||
|
||||
jmp GDT_FLAT_IDX_CODE_32:.protected_mode_32
|
||||
|
||||
[bits 32]
|
||||
.protected_mode_32:
|
||||
|
||||
pop ss
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popad
|
||||
ret
|
||||
|
||||
global bios_call
|
||||
|
||||
|
||||
%macro int_fn 1
|
||||
int %1
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
|
||||
int_fns:
|
||||
int_fn 0x00
|
||||
int_fn 0x01
|
||||
int_fn 0x02
|
||||
int_fn 0x03
|
||||
int_fn 0x04
|
||||
int_fn 0x05
|
||||
int_fn 0x06
|
||||
int_fn 0x07
|
||||
int_fn 0x08
|
||||
int_fn 0x09
|
||||
int_fn 0x0a
|
||||
int_fn 0x0b
|
||||
int_fn 0x0c
|
||||
int_fn 0x0d
|
||||
int_fn 0x0e
|
||||
int_fn 0x0f
|
||||
int_fn 0x10
|
||||
int_fn 0x11
|
||||
int_fn 0x12
|
||||
int_fn 0x13
|
||||
int_fn 0x14
|
||||
int_fn 0x15
|
||||
int_fn 0x16
|
||||
int_fn 0x17
|
||||
int_fn 0x18
|
||||
int_fn 0x19
|
||||
int_fn 0x1a
|
||||
int_fn 0x1b
|
||||
int_fn 0x1c
|
||||
int_fn 0x1d
|
||||
int_fn 0x1e
|
||||
int_fn 0x1f
|
||||
|
||||
|
||||
section .rodata
|
||||
|
||||
idt_real:
|
||||
dw 0x3ff
|
||||
dd 0
|
||||
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
section .rodata
|
||||
|
||||
gdt_flat_slice:
|
||||
dw GDT_FLAT_LEN
|
||||
dd gdt_flat
|
||||
|
||||
global gdt_flat_slice
|
||||
|
||||
; Segment descriptor layout
|
||||
; | Range (bits) | Field |
|
||||
; |--------------|---------------|
|
||||
; | 0-16 | limit |
|
||||
; | 16-32 | base |
|
||||
; | 32-40 | base cont. |
|
||||
; | 40-48 | access |
|
||||
; | 48-52 | limit cont. |
|
||||
; | 52-56 | flags |
|
||||
; | 56-64 | base cont. |
|
||||
;
|
||||
; Flags
|
||||
; - 0: reserved
|
||||
; - 1: long-mode code segment
|
||||
; - 2: size
|
||||
; - unset: 16-bit
|
||||
; - set: 32-bit
|
||||
; - 3: granularity
|
||||
; - unset: limit is measured in bytes
|
||||
; - set: limit is measured in 4KiB pages
|
||||
;
|
||||
; Access
|
||||
; - 0: accessed
|
||||
; - unset: CPU will set it when the segment is accessed
|
||||
; - 1: readable / writable
|
||||
; - data segments: is segment writable (data segments are always readable)
|
||||
; - code segments: is segment readable (code segments are never writable)
|
||||
; - 2: direction / conforming
|
||||
; - data segments: whether segment grows down
|
||||
; - code segments: whether this can be executed from a lower-privilege ring
|
||||
; - 3: executable
|
||||
; - unset: this is a data segment
|
||||
; - set: this is a code segment
|
||||
; - 4: descriptor type
|
||||
; - unset: this is a task state segment
|
||||
; - set: this is a data or code segment
|
||||
; - 5-6: privilege level (ring number)
|
||||
; - 7: present (must be set)
|
||||
;
|
||||
align 8
|
||||
gdt_flat:
|
||||
; First GDT entry must be 0.
|
||||
dq 0
|
||||
|
||||
; 32-bit code segment.
|
||||
; Bytes 0x0000 - 0xffff.
|
||||
.segment_code_32:
|
||||
db 0xff, 0xff, \
|
||||
0x00, 0x00, \
|
||||
0x00, \
|
||||
10011011b, \
|
||||
01000000b, \
|
||||
0x00
|
||||
|
||||
; 16-bit code segment, to use if we want to switch back to real mode.
|
||||
; Bytes 0x0000 - 0xffff.
|
||||
.segment_code_16:
|
||||
db 0xff, 0xff, \
|
||||
0x00, 0x00, \
|
||||
0x00, \
|
||||
10011011b, \
|
||||
00000000b, \
|
||||
0x00
|
||||
|
||||
; Data segment.
|
||||
; Pages 0x000000 - 0x0fffff, which covers the entire 32-bit address space (start of 0xfffff-th page
|
||||
; is 0xfffff * 4096 = 0xfffff000, end of page exclusive is 0xfffff000 + 4096 = 0x100000000).
|
||||
.segment_data:
|
||||
db 0xff, 0xff, \
|
||||
0x00, 0x00, \
|
||||
0x00, \
|
||||
10010011b, \
|
||||
11001111b, \
|
||||
0x00
|
||||
|
||||
global gdt_flat
|
||||
|
||||
GDT_FLAT_LEN equ ($ - gdt_flat)
|
||||
|
||||
GDT_FLAT_IDX_CODE_32 equ (gdt_flat.segment_code_32 - gdt_flat)
|
||||
global GDT_FLAT_IDX_CODE_32
|
||||
|
||||
GDT_FLAT_IDX_CODE_16 equ (gdt_flat.segment_code_16 - gdt_flat)
|
||||
global GDT_FLAT_IDX_CODE_16
|
||||
|
||||
GDT_FLAT_IDX_DATA equ (gdt_flat.segment_data - gdt_flat)
|
||||
global GDT_FLAT_IDX_DATA
|
||||
@ -0,0 +1,18 @@
|
||||
%ifndef BOOT_PS2_H
|
||||
%define BOOT_PS2_H
|
||||
|
||||
%define INTEL_8042_IO_DATA 0x60
|
||||
%define INTEL_8042_IN_STATUS 0x64
|
||||
%define INTEL_8042_OUT_CMD 0x64
|
||||
|
||||
%define INTEL_8042_STATUS_BIT_OBUF 0
|
||||
%define INTEL_8042_STATUS_BIT_IBUF 1
|
||||
%define INTEL_8042_STATUS_MASK_OBUF (1 << INTEL_8042_STATUS_BIT_OBUF)
|
||||
%define INTEL_8042_STATUS_MASK_IBUF (1 << INTEL_8042_STATUS_BIT_IBUF)
|
||||
|
||||
%define INTEL_8042_CMD_PS2_1_DISABLE 0xad
|
||||
%define INTEL_8042_CMD_PS2_1_ENABLE 0xae
|
||||
%define INTEL_8042_CMD_CONTROLLER_OUT_PORT_READ 0xd0
|
||||
%define INTEL_8042_CMD_CONTROLLER_OUT_PORT_WRITE 0xd1
|
||||
|
||||
%endif
|
||||
Loading…
Reference in New Issue