aboutsummaryrefslogtreecommitdiffstats
path: root/src/boot
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot')
-rw-r--r--src/boot/boot.common.asm0
-rw-r--r--src/boot/boot.stage1.asm64
-rw-r--r--src/boot/boot.stage1.print.asm21
-rw-r--r--src/boot/boot.stage2.a20.asm147
-rw-r--r--src/boot/boot.stage2.asm11
-rw-r--r--src/boot/boot.stage2.gdt32.asm29
-rw-r--r--src/boot/boot.stage2.pm.asm12
7 files changed, 284 insertions, 0 deletions
diff --git a/src/boot/boot.common.asm b/src/boot/boot.common.asm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/boot/boot.common.asm
diff --git a/src/boot/boot.stage1.asm b/src/boot/boot.stage1.asm
new file mode 100644
index 0000000..801860e
--- /dev/null
+++ b/src/boot/boot.stage1.asm
@@ -0,0 +1,64 @@
+ ;; boot.stage1.asm
+
+ %include "boot.common.asm"
+ %include "boot.stage1.print.asm"
+ [org 0x7c00]
+ [bits 16]
+
+ %define READ_SECTORS_NUM 64
+ %define BOOT_LOAD_ADDR 0x7c00
+ %define SECTOR_SIZE 512
+
+ global _start
+
+_start:
+ ;; Disable interrupts
+ cli
+
+ ;; Setup segment registers
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+ ;; Adjust Stack
+ mov sp, _start
+
+ clc
+
+ mov si, disk_addr_packet
+ mov ah, 0x42 ; BIOS extended read function
+ mov dl, 0x80 ; Drive number
+ int 0x13 ; BIOS disk services
+ jc _disk_read_err
+
+ mov si, disk_read_success_msg
+ call _print_string
+
+ jmp 0x0000:0x7e00
+
+_disk_read_err:
+ mov si, disk_read_err_msg
+ call _print_string
+
+ hlt
+ jmp _disk_read_err
+
+_end:
+ hlt
+ jmp _end
+
+disk_read_err_msg: db "Failed to read disk", 13, 10, 0
+disk_read_success_msg: db "Read the disk successfully", 13, 10, 0
+disk_addr_packet:
+ db 0x10
+ db 0x00
+ dw READ_SECTORS_NUM
+ dw 0x0000
+ dw 0x7e00
+ dq 1
+
+ ;; Padding and magic number
+ times 510 - ($ - $$) db 0
+ dw 0xaa55
+
diff --git a/src/boot/boot.stage1.print.asm b/src/boot/boot.stage1.print.asm
new file mode 100644
index 0000000..aff2e0d
--- /dev/null
+++ b/src/boot/boot.stage1.print.asm
@@ -0,0 +1,21 @@
+ ;; boot.stage1.print.asm
+
+ [bits 16]
+_print_string:
+ pusha
+ mov ah, 0x0e
+
+_print_string_loop:
+ cmp byte [bx], 0
+ je _print_string_return
+
+ mov al, [bx]
+ int 0x10
+
+ inc bx
+ jmp _print_string_loop
+
+_print_string_return:
+ popa
+ ret
+ align 4
diff --git a/src/boot/boot.stage2.a20.asm b/src/boot/boot.stage2.a20.asm
new file mode 100644
index 0000000..6a9c250
--- /dev/null
+++ b/src/boot/boot.stage2.a20.asm
@@ -0,0 +1,147 @@
+ ;; boot.stage2.a20.asm
+
+_enable_a20:
+ call _check_a20
+ test ax, ax
+ jnz .end
+
+ call _enable_a20_bios
+ call _check_a20
+ test ax, ax
+ jnz .end
+
+ call _enable_a20_keyb
+ call _check_a20
+ test ax, ax
+ jnz .end
+
+ call _enable_a20_io92
+ call _check_a20
+ test ax, ax
+ jnz .end
+
+ .halt: hlt
+ jmp .halt
+ .end
+ ret
+
+_check_a20:
+ pushf
+ push ds
+ push es
+ push di
+ push si
+ cli ; Clear Interrupts
+
+ xor ax, ax
+ mov es, ax
+ not ax
+ mov ds, ax
+ ;; 0500 and 0510 are guaranteed to be free
+ mov di, 0x0500
+ mov si, 0x0510
+
+ ;; Save the original values
+ mov dl, byte [es:di]
+ push dx
+ mov dl, byte [ds:si]
+ push dx
+
+ mov byte [es:di], 0x00
+ mov byte [ds:si], 0xFF
+ cmp byte [es:di], 0xFF
+
+ mov ax, 0 ; The A20 is disabled
+ je .a20_disabled
+ mov ax, 1 ; The A20 is enabled
+ .a20_disabled:
+ pop dx
+ mov byte [ds:si], dl
+ pop dx
+ mov byte [es:di], dl
+
+ pop si
+ pop di
+ pop es
+ pop ds
+ popf
+ sti ; Enable interrupts again
+ ret
+
+_enable_a20_bios:
+ mov ax, 0x2401
+ int 0x15
+ jc .fast_gate
+ test ah, ah
+ jnz .failed
+ call _check_a20
+ test ax, ax
+ jnz .done
+
+ .fast_gate:
+ in al, 0x92
+ test al, 2
+ jnz .done
+
+ or al, 2
+ and al, 0xfe
+ out 0x92, al
+
+ call _check_a20
+ test ax, ax
+ jnz .done
+
+ .done:
+ mov ax, 1
+ ret
+
+ .failed:
+ mov ax, 0
+ ret
+
+_enable_a20_keyb:
+ cli
+ call .wait_io1
+ mov al, 0xad
+ out 0x64, al
+
+ call .wait_io1
+ mov al, 0x0d0
+ out 0x64, al
+
+ call .wait_io2
+ in al, 0x60
+ push eax
+
+ call .wait_io1
+ mov al, 0xd1
+ out 0x64, al
+
+ call .wait_io1
+ mov al, 0xae
+ out 0x64, al
+
+ sti
+ ret
+
+ .wait_io1:
+ in al, 0x64
+ test al, 2
+ jnz .wait_io1
+ ret
+
+ .wait_io2:
+ in al, 0x64
+ test al, 1
+ jz .wait_io2
+ ret
+
+_enable_a20_io92:
+ in al, 0x92 ; Read from port 0x92
+ test al, 2 ; Check if bit 1
+ jnz .end
+ or al, 2
+ and al, 0xfe
+ out 0x92, al
+ .end
+ ret
diff --git a/src/boot/boot.stage2.asm b/src/boot/boot.stage2.asm
new file mode 100644
index 0000000..56ab73a
--- /dev/null
+++ b/src/boot/boot.stage2.asm
@@ -0,0 +1,11 @@
+ ;; boot.stage2.asm
+
+ [bits 16]
+ [org 0x7e00]
+
+ %include "boot.stage2.a20.asm"
+ %include "boot.stage2.pm.asm"
+_s2_entry:
+ call _enable_a20
+ call _enter_pm
+ [bits 32]
diff --git a/src/boot/boot.stage2.gdt32.asm b/src/boot/boot.stage2.gdt32.asm
new file mode 100644
index 0000000..f9f27a5
--- /dev/null
+++ b/src/boot/boot.stage2.gdt32.asm
@@ -0,0 +1,29 @@
+y ;; boot.stage2.gdt32.asm
+
+
+GDT32:
+ .null:
+ dd 0x0
+ dd 0x0
+ .code:
+ dw 0xffff
+ dw 0x0000
+ db 0x00
+ db 10011010b
+ db 11001111b
+ db 0x00
+ .data:
+ dw 0xffff
+ dw 0x0000
+ db 0x00
+ db 10010010b
+ db 11001111b
+ db 0x00
+GDT32_end:
+
+GDT32_ptr:
+ .limit: dw GDT32_end - GDT32 - 1
+ .base: dd GDT32
+
+ CODE_SEG32 equ gdt32_code_segment - gdt32_start
+ DATA_SEG32 equ gdt32_data_segment - gdt32_start
diff --git a/src/boot/boot.stage2.pm.asm b/src/boot/boot.stage2.pm.asm
new file mode 100644
index 0000000..77f5f61
--- /dev/null
+++ b/src/boot/boot.stage2.pm.asm
@@ -0,0 +1,12 @@
+ ;; boot.stage2.pm.asm
+
+
+ [bits 16]
+ %include "boot.stage2.gdt32.asm"
+
+_
+ cli
+ lgdt [GDT32_ptr]
+
+
+ ;; Enable Protected Mode