From: Duje Mihanović Date: Thu, 9 Sep 2021 09:13:53 +0000 (+0200) Subject: Restructure the bootloader X-Git-Tag: 0.1.0~20 X-Git-Url: http://git.dujemihanovic.xyz/%22http:/www.sics.se/static/%7B%7B%20%24.Site.BaseURL%20%7D%7Dposts/index.xml?a=commitdiff_plain;h=63853960825f007827a79f704d291c372c807096;p=nameless-os.git Restructure the bootloader --- diff --git a/.gitignore b/.gitignore index 988eea0..a5ea528 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ toolchain/ -boot boot.img **/*.o **/*.bin diff --git a/Makefile b/Makefile index a4c88b3..9d1c344 100644 --- a/Makefile +++ b/Makefile @@ -6,12 +6,12 @@ KERNEL_OBJ = kernel/entry.o kernel/arch/x86/tty/tty.o kernel/kernel.o all: boot.img -boot.img: boot kernel/kernel.bin - cat boot kernel/kernel.bin > $@ +boot.img: boot/x86/boot kernel/kernel.bin + cat boot/x86/boot kernel/kernel.bin > $@ truncate -s1440K $@ -boot: boot.s - $(AS) -f bin boot.s -o $@ +boot/x86/boot: boot/x86/boot.s boot/x86/a20.s boot/x86/protected.s + $(AS) -f bin boot/x86/boot.s -o $@ kernel/kernel.bin: ${KERNEL_OBJ} $(LD) -o $@ -T kernel/linker.ld ${KERNEL_OBJ} --oformat=binary @@ -26,6 +26,6 @@ kernel/kernel.o: kernel/kernel.c $(CC) -g -o $@ -Iinclude/arch/x86 -ffreestanding -c kernel/kernel.c clean: - rm boot kernel/kernel.bin ${KERNEL_OBJ} boot.img + rm boot/x86/boot kernel/kernel.bin ${KERNEL_OBJ} boot.img .PHONY: all clean diff --git a/boot/x86/a20.s b/boot/x86/a20.s new file mode 100644 index 0000000..f6a292b --- /dev/null +++ b/boot/x86/a20.s @@ -0,0 +1,49 @@ +; Some routines for managing the A20 line + +; Check if A20 is enabled +; Based on , slightly modified +check_a20 + pushf ; save EFLAGS + ; save segment and index registers + push ds + push es + push di + push si + + cli ; disable interrupts + xor ax, ax ; ax = 0 + mov es, ax ; es = 0 + + not ax ; ax = FFFFh + mov ds, ax ; ds = FFFFh + + mov di, 500h + mov si, 510h + + mov al, [es:di] ; preserve contents of 0:500h + mov ah, [ds:si] ; preserve contents of FFFFh:510h + push ax ; push all that to stack + + mov byte [es:di], 0 ; set 0:500h to 0 + mov byte [ds:si], 0FFh ; set FFFFh:510h to FFh + + cmp byte [es:di], 0FFh ; compare 0:500h with FFh + ; if A20 is enabled, this will not be equal, but if A20 is disabled it will be + + pop ax ; pop old contents of the 2 addresses + mov [ds:si], ah ; restore contents of FFFFh:510h + mov [es:di], al ; restore contents of 0:500h + + xor ax, ax ; clear ax + je .exit ; if A20 is disabled, return 0 + mov ax, 1 ; otherwise return 1 + +.exit + pop si + pop di + pop es + pop ds + popf + sti + ret + diff --git a/boot/x86/boot b/boot/x86/boot new file mode 100644 index 0000000..a708651 Binary files /dev/null and b/boot/x86/boot differ diff --git a/boot/x86/boot.s b/boot/x86/boot.s new file mode 100644 index 0000000..be6c653 --- /dev/null +++ b/boot/x86/boot.s @@ -0,0 +1,53 @@ + bits 16 ; boot sectors run in real mode + org 7C00h ; BIOS loads us at 0x7c00 + +KERNEL_OFFSET equ 1000h ; where we will load our kernel + + mov [BOOT_DRIVE], dl ; BIOS puts the number of our boot drive in dl, so we will want to remember this + + mov bp, 9000h ; initialize stack at a spot sufficiently distanced from this code + mov sp, bp + + mov di, 0 + + xor ax, ax ; clear accumulator + int 13h ; BIOS disk services, with a cleared accumulator this will reset the disk controller + jc reset_error ; halt if controller reset fails + + mov ah, 2 ; instruct BIOS's interrupt 13h to read sectors + mov al, 10 ; load 10 sectors, might be excessive (for now) but it's still good to do so + xor ch, ch ; read from 1st cylinder + mov cl, 2 ; start reading from 2nd sector, right after the boot sector + xor dh, dh ; read from 1st head + xor bx, bx ; clear B register + mov es, bx ; clear extended segment + mov bx, KERNEL_OFFSET ; put the sectors in our desired offset + ; dl holds the number of the drive to read from, but BIOS already filled this in + int 13h ; do the read + jc read_error ; halt if read fails + cmp al, 10 ; make sure we actually read 10 sectors + jl read_error ; halt if we didn't + jmp switch_to_pm ; if all is good, begin the switch to 32-bit protected mode + +reset_error + mov bx, 0B800h + mov es, bx + mov byte [es:di], '1' + jmp halt + +read_error + mov bx, 0B800h + mov es, bx + mov byte [es:di], '2' + jmp halt + +halt + jmp $ + +%include "a20.s" +%include "protected.s" + +BOOT_DRIVE db 0 ; reserve a spot in RAM for our boot drive variable + + times 510-($-$$) db 0 + dw 0AA55h ; MBR signature diff --git a/boot.s b/boot/x86/protected.s similarity index 64% rename from boot.s rename to boot/x86/protected.s index 6181a73..d1c7eea 100644 --- a/boot.s +++ b/boot/x86/protected.s @@ -1,50 +1,6 @@ - bits 16 ; boot sectors run in real mode - org 7C00h ; BIOS loads us at 0x7c00 +; Everything between real mode and the C kernel -KERNEL_OFFSET equ 1000h ; where we will load our kernel - - mov [BOOT_DRIVE], dl ; BIOS puts the number of our boot drive in dl, so we will want to remember this - - mov bp, 9000h ; initialize stack at a spot sufficiently distanced from this code - mov sp, bp - - mov di, 0 - - xor ax, ax ; clear accumulator - int 13h ; BIOS disk services, with a cleared accumulator this will reset the disk controller - jc reset_error ; halt if controller reset fails - - mov ah, 2 ; instruct BIOS's interrupt 13h to read sectors - mov al, 10 ; load 10 sectors, might be excessive (for now) but it's still good to do so - xor ch, ch ; read from 1st cylinder - mov cl, 2 ; start reading from 2nd sector, right after the boot sector - xor dh, dh ; read from 1st head - xor bx, bx ; clear B register - mov es, bx ; clear extended segment - mov bx, KERNEL_OFFSET ; put the sectors in our desired offset - ; dl holds the number of the drive to read from, but BIOS already filled this in - int 13h ; do the read - jc read_error ; halt if read fails - cmp al, 10 ; make sure we actually read 10 sectors - jl read_error ; halt if we didn't - jmp switch_to_pm ; if all is good, begin the switch to 32-bit protected mode - -reset_error - mov bx, 0B800h - mov es, bx - mov byte [es:di], '1' - jmp halt - -read_error - mov bx, 0B800h - mov es, bx - mov byte [es:di], '2' - jmp halt - - call switch_to_pm - -halt - jmp $ + bits 16 switch_to_pm mov bx, 0B800h @@ -143,7 +99,3 @@ gdt_desc CODE_SEG equ code_seg - gdt_start DATA_SEG equ data_seg - gdt_start -BOOT_DRIVE db 0 ; reserve a spot in RAM for our boot drive variable - - times 510-($-$$) db 0 - dw 0AA55h ; MBR signature