refactor + wip bios call from protected mode
This commit is contained in:
1 parent
121e13165b
commit
766a9c981c
8 files changed
+388
-135
No files matched your search
@@ -3,7 +3,7 @@
|
|||||||
; --------------------------------------------------------------------
|
; --------------------------------------------------------------------
|
||||||
; R | 0x000000 - 0x000400: real-mode interrupt vector table
|
; R | 0x000000 - 0x000400: real-mode interrupt vector table
|
||||||
; R | 0x000400 - 0x000500: bios data area
|
; R | 0x000400 - 0x000500: bios data area
|
||||||
; U | 0x000500 - 0x004000: stack
|
; U | 0x000500 - 0x004000: main stack
|
||||||
; U | 0x004000 - 0x006a00: globals
|
; U | 0x004000 - 0x006a00: globals
|
||||||
; U | 0x006a00 - 0x007c00: memory map
|
; U | 0x006a00 - 0x007c00: memory map
|
||||||
; U | 0x007c00 - 0x007e00: boot sector
|
; U | 0x007c00 - 0x007e00: boot sector
|
||||||
|
|||||||
@@ -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
|
||||||
+13
-90
@@ -1,4 +1,5 @@
|
|||||||
%include "defines.s"
|
%include "defines.s"
|
||||||
|
%include "ps2.s"
|
||||||
|
|
||||||
[bits 16]
|
[bits 16]
|
||||||
|
|
||||||
@@ -7,6 +8,12 @@ extern boot1_bin_sectors
|
|||||||
extern boot1_magic
|
extern boot1_magic
|
||||||
extern _start
|
extern _start
|
||||||
|
|
||||||
|
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 .prelude
|
section .prelude
|
||||||
|
|
||||||
%macro copy_stack_var_to_globals 2
|
%macro copy_stack_var_to_globals 2
|
||||||
@@ -335,22 +342,22 @@ prelude_main:
|
|||||||
cli
|
cli
|
||||||
|
|
||||||
; Load our flat-address-space GDT.
|
; Load our flat-address-space GDT.
|
||||||
lgdt [flat_gdt_slice]
|
lgdt [gdt_flat_slice]
|
||||||
|
|
||||||
; Set the protected-mode bit in cr0.
|
; Set the protected-mode bit in cr0.
|
||||||
mov eax, cr0
|
mov eax, cr0
|
||||||
or al, 0x01
|
or al, 0x01
|
||||||
mov cr0, eax
|
mov cr0, eax
|
||||||
|
|
||||||
; Long jump to set the code segment to flat_gdt.segment_code, and to clear the instruction
|
; Long jump to set the code segment to gdt_flat.segment_code, and to clear the instruction
|
||||||
; pipeline.
|
; pipeline.
|
||||||
jmp (flat_gdt.segment_code_32 - flat_gdt):.protected_mode
|
jmp GDT_FLAT_IDX_CODE_32:.protected_mode_32
|
||||||
|
|
||||||
[bits 32]
|
[bits 32]
|
||||||
.protected_mode:
|
.protected_mode_32:
|
||||||
|
|
||||||
; Set the data segments to flat_gdt.segment_data.
|
; Set the data segments to gdt_flat.segment_data.
|
||||||
mov eax, (flat_gdt.segment_data - flat_gdt)
|
mov eax, GDT_FLAT_IDX_DATA
|
||||||
mov ds, eax
|
mov ds, eax
|
||||||
mov es, eax
|
mov es, eax
|
||||||
mov fs, eax
|
mov fs, eax
|
||||||
@@ -363,87 +370,3 @@ prelude_main:
|
|||||||
|
|
||||||
jmp _start
|
jmp _start
|
||||||
jmp panic_simple
|
jmp panic_simple
|
||||||
|
|
||||||
|
|
||||||
section .data
|
|
||||||
flat_gdt_slice:
|
|
||||||
dw FLAT_GDT_LEN
|
|
||||||
dd flat_gdt
|
|
||||||
|
|
||||||
; 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
|
|
||||||
flat_gdt:
|
|
||||||
; First GDT entry must be 0.
|
|
||||||
.segment_null:
|
|
||||||
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
|
|
||||||
|
|
||||||
FLAT_GDT_LEN equ ($ - flat_gdt)
|
|
||||||
+54
-8
@@ -5,9 +5,9 @@ fn main() {
|
|||||||
.expect("OUT_DIR not set");
|
.expect("OUT_DIR not set");
|
||||||
let out_dir = PathBuf::from(out_dir);
|
let out_dir = PathBuf::from(out_dir);
|
||||||
|
|
||||||
let path = SearchPath::load();
|
let search_path = SearchPath::load();
|
||||||
|
|
||||||
let nasm_path = path.search("nasm")
|
let nasm_path = search_path.search("nasm")
|
||||||
.next()
|
.next()
|
||||||
.expect("failed to find nasm in PATH");
|
.expect("failed to find nasm in PATH");
|
||||||
let nasm = Nasm::new(nasm_path);
|
let nasm = Nasm::new(nasm_path);
|
||||||
@@ -38,13 +38,42 @@ fn link_obj(path: &Path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn build_asm(nasm: &Nasm, out_dir: &Path) {
|
fn build_asm(nasm: &Nasm, out_dir: &Path) {
|
||||||
let prelude_obj_path = out_dir.join("prelude.o");
|
let asm_srcs = fs::read_dir("asm")
|
||||||
|
.expect("failed to get asm sources");
|
||||||
|
|
||||||
|
for asm_src in asm_srcs {
|
||||||
|
let asm_src = asm_src.expect("failed to get asm source");
|
||||||
|
|
||||||
|
let ty = asm_src.file_type().expect("failed to get file type");
|
||||||
|
if !ty.is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let src_path = asm_src.path();
|
||||||
|
|
||||||
|
let is_asm = src_path
|
||||||
|
.extension()
|
||||||
|
.map(|ext| ext == "s")
|
||||||
|
.unwrap_or(false);
|
||||||
|
if !is_asm {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let out_filename = src_path
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.apply(PathBuf::from)
|
||||||
|
.with_extension("o");
|
||||||
|
let out_path = out_dir.join(out_filename);
|
||||||
|
|
||||||
nasm.assemble(
|
nasm.assemble(
|
||||||
&prelude_obj_path,
|
&out_path,
|
||||||
&["asm/prelude.s".as_ref()],
|
&[&src_path],
|
||||||
&["../include".as_ref()],
|
&["../include".as_ref()]
|
||||||
).unwrap();
|
).expect("failed to assemble");
|
||||||
link_obj(&prelude_obj_path);
|
|
||||||
|
link_obj(&out_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Nasm {
|
struct Nasm {
|
||||||
@@ -165,3 +194,20 @@ enum CmdErrorKind {
|
|||||||
Status(process::Output),
|
Status(process::Output),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Apply: Sized {
|
||||||
|
fn apply<T, F>(self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(Self) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<U> Apply for U
|
||||||
|
where
|
||||||
|
U: Sized,
|
||||||
|
{
|
||||||
|
fn apply<T, F>(self, f: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(Self) -> T
|
||||||
|
{
|
||||||
|
f(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
-22
@@ -8,35 +8,31 @@ const VGA_HEIGHT: usize = 25;
|
|||||||
const VGA_SIZE: usize = VGA_WIDTH * VGA_HEIGHT;
|
const VGA_SIZE: usize = VGA_WIDTH * VGA_HEIGHT;
|
||||||
const VGA_ADDR: usize = 0xb8000;
|
const VGA_ADDR: usize = 0xb8000;
|
||||||
|
|
||||||
const STR: &[u8] = b"the quick brown fox jumps over the lazy dog";
|
const STR: &[u8] = b"sphinx of black quartz, judge my vow";
|
||||||
|
|
||||||
// extern "C" {
|
#[repr(C)]
|
||||||
// fn prelude() -> !;
|
#[derive(Clone, Debug)]
|
||||||
// }
|
struct BiosIntr {
|
||||||
|
eax: u32,
|
||||||
|
ebx: u32,
|
||||||
|
ecx: u32,
|
||||||
|
edx: u32,
|
||||||
|
esi: u32,
|
||||||
|
edi: u32,
|
||||||
|
ds: u16,
|
||||||
|
es: u16,
|
||||||
|
eflags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
unsafe fn bios_call(intr: u32, args: *mut BiosIntr);
|
||||||
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &PanicInfo) -> ! {
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
hlt()
|
hlt()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ```asm
|
|
||||||
// 00000000 E800000000 call 0x5 ; call / pop gadget to load eip into ecx
|
|
||||||
// 00000005 59 pop ecx
|
|
||||||
// 00000006 81C15F000000 add ecx,0x5f
|
|
||||||
// 0000000C 31C0 xor eax,eax
|
|
||||||
// 0000000E 8D89D4FFFFFF lea ecx,[ecx-0x2c] ; length of string is 0x2b
|
|
||||||
// 00000014 0FB611 movzx edx,byte [ecx]
|
|
||||||
// 00000017 81CA001F0000 or edx,0x1f00
|
|
||||||
// 0000001D 6689940000800B00 mov [eax+eax+0xb8000],dx
|
|
||||||
// 00000025 40 inc eax
|
|
||||||
// 00000026 41 inc ecx
|
|
||||||
// 00000027 83F82B cmp eax,byte +0x2b
|
|
||||||
// 0000002A 75E8 jnz 0x14
|
|
||||||
// 0000002C 66C70500800B0002 mov word [dword 0xb8000],0x1f02
|
|
||||||
// -1F
|
|
||||||
// 00000035 F4 hlt
|
|
||||||
// 00000036 EBFD jmp short 0x35
|
|
||||||
// ```
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() -> ! {
|
||||||
let vga_buf: &'static mut [u16; VGA_SIZE] = unsafe { &mut *(VGA_ADDR as *mut [u16; VGA_SIZE]) };
|
let vga_buf: &'static mut [u16; VGA_SIZE] = unsafe { &mut *(VGA_ADDR as *mut [u16; VGA_SIZE]) };
|
||||||
@@ -45,6 +41,26 @@ pub extern "C" fn _start() -> ! {
|
|||||||
vga_buf[i] = 0x1f00 | u16::from(b);
|
vga_buf[i] = 0x1f00 | u16::from(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut args = BiosIntr {
|
||||||
|
eax: 0xe820,
|
||||||
|
ebx: 0,
|
||||||
|
ecx: 24,
|
||||||
|
edx: 0x534d4150,
|
||||||
|
esi: 0,
|
||||||
|
edi: 0x6a00,
|
||||||
|
ds: 0,
|
||||||
|
es: 0,
|
||||||
|
eflags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
bios_call(0x15, &raw mut args);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, b) in STR.iter().copied().enumerate() {
|
||||||
|
vga_buf[i + VGA_WIDTH] = 0x1f00 | u16::from(b);
|
||||||
|
}
|
||||||
|
|
||||||
hlt()
|
hlt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,20 +19,6 @@
|
|||||||
%define VGA_WIDTH 80
|
%define VGA_WIDTH 80
|
||||||
%define VGA_HEIGHT 25
|
%define VGA_HEIGHT 25
|
||||||
|
|
||||||
%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
|
|
||||||
|
|
||||||
; ASCII string "SMAP", which is used by e820 as a magic number argument and return value.
|
; ASCII string "SMAP", which is used by e820 as a magic number argument and return value.
|
||||||
%define E820_MAGIC 0x534d4150
|
%define E820_MAGIC 0x534d4150
|
||||||
; Size of entry returned by e820. This is less than MEMMAP_ENT_SIZE because we add some fields of
|
; Size of entry returned by e820. This is less than MEMMAP_ENT_SIZE because we add some fields of
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in new issue
Block a user