]> git.dujemihanovic.xyz Git - nameless-os.git/commitdiff
Restructure the bootloader
authorDuje Mihanović <duje.mihanovic@skole.hr>
Thu, 9 Sep 2021 09:13:53 +0000 (11:13 +0200)
committerDuje Mihanović <duje.mihanovic@skole.hr>
Thu, 9 Sep 2021 09:13:53 +0000 (11:13 +0200)
.gitignore
Makefile
boot/x86/a20.s [new file with mode: 0644]
boot/x86/boot [new file with mode: 0644]
boot/x86/boot.s [new file with mode: 0644]
boot/x86/protected.s [moved from boot.s with 64% similarity]

index 988eea0815e309be4450f1064b2b3ca2610542b0..a5ea5282718f9708b265e61716fb07f9f32bc39f 100644 (file)
@@ -1,5 +1,4 @@
 toolchain/
-boot
 boot.img
 **/*.o
 **/*.bin
index a4c88b392be52822dea6e890cacc9b200b7acdcd..9d1c34475a160d1bb3af2d6fd2ff3f28feb0169e 100644 (file)
--- 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 (file)
index 0000000..f6a292b
--- /dev/null
@@ -0,0 +1,49 @@
+; Some routines for managing the A20 line
+
+; Check if A20 is enabled
+; Based on <https://wiki.osdev.org/A20_Line#Testing_the_A20_line>, 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 (file)
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 (file)
index 0000000..be6c653
--- /dev/null
@@ -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
similarity index 64%
rename from boot.s
rename to boot/x86/protected.s
index 6181a73528610dcaf7c18ea6beb51dbf03865ffe..d1c7eea34df31ac1a191c26bc2abeb6bb45924d6 100644 (file)
--- a/boot.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