summaryrefslogtreecommitdiff
path: root/src/bootloader
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootloader')
-rw-r--r--src/bootloader/bios_disk.asm149
-rw-r--r--src/bootloader/bios_functions/bios_disk.asm40
-rw-r--r--src/bootloader/bios_functions/print.asm58
-rw-r--r--src/bootloader/bootloader.asm95
-rw-r--r--src/bootloader/cpu_check.asm28
-rw-r--r--src/bootloader/enter_kernel.asm72
-rw-r--r--src/bootloader/gdt.asm6
-rw-r--r--src/bootloader/print.asm21
-rw-r--r--src/bootloader/video.asm4
9 files changed, 267 insertions, 206 deletions
diff --git a/src/bootloader/bios_disk.asm b/src/bootloader/bios_disk.asm
new file mode 100644
index 0000000..5992920
--- /dev/null
+++ b/src/bootloader/bios_disk.asm
@@ -0,0 +1,149 @@
+bios_disk:
+.init:
+mov [boot_device], dl
+mov ah, 0x8
+int 0x13
+;TODO defaults
+
+jc .init_use_defaults
+
+mov [max_head], dh
+mov [max_sector], cl
+and WORD [max_sector], 0x3f
+
+mov [max_cylinder], cl
+shl WORD [max_cylinder], 8
+or [max_cylinder], ch
+and WORD [max_cylinder], 0x3ff
+
+ret
+
+.init_use_defaults:
+mov BYTE [max_sector], 63
+mov WORD [max_head], 15
+mov BYTE [max_cylinder], 1023
+
+ret
+
+; Return:
+; CH = low eight bits of maximum cylinder number
+; CL = maximum sector number (bits 5-0), high two bits of maximum cylinder number (bits 7-6)
+; DH = maximum head number
+
+.load_sectors_v2:
+;AH = 02h
+;AL = number of sectors to read (must be nonzero)
+;CH = low eight bits of cylinder number
+;CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7)
+;DH = head number
+;DL = drive number (bit 7 set for hard disk)
+;ES:BX -> data buffer
+
+; I don't understand i8086. The base pointer needs to be above the stack pointer,
+; yet the stack grows down,
+; and we can't address using sp, or by subtraction.
+; it's like it's forcing us to use the whole push/pop thing.
+
+sub sp, 16
+mov bp, sp
+
+; sector: rbp + 0 (uint8_t)
+; head: rbp + 1 (uint8_t)
+; cylinder: rbp + 2 (uint16_t)
+; sector_cnt: rbp + 4 (uint16_t)
+; destination: rbp + 6 (uint32_t)
+
+; set up variables ______________________________________________
+
+;destination to stack
+mov [bp + 6], edi
+
+; find init chs ________________________________________________
+
+; divide sector_start / max_sectors
+; TODO test for overflow
+mov ax, si
+shr esi, 16
+mov dx, si
+
+;find sector
+div DWORD [max_sector]
+inc dx
+mov [bp], edx ; remainder is sector variable
+
+;find head and cylinder
+mov dx, 0
+div DWORD [max_head]
+mov [bp + 1], dx ; head
+mov [bp + 2], ax ; cylinder
+
+.sector_for_loop:
+mov [bp + 4], cx
+
+; do bios call ___________________________________________________
+mov ah, 2
+mov al, 1
+; sets up ch and cl
+mov cx, [bp + 2]
+xchg ch, cl
+shl cl, 6
+or cl, [bp]
+
+mov dh, [bp + 1]
+mov dl, [boot_device]
+mov bx, 0x500 ; where we store the sector temporarily
+
+int 0x13
+jc .read_failed
+
+; mempcy __________________________________________________________
+
+; we move it to the place at edi, which I don't think changes
+mov esi, 0x500
+mov ecx, 512
+a32 rep movsb
+
+; recalc chs ______________________________________________________
+
+; need to test for more overflows I think
+inc WORD [bp]
+mov al, [bp]; increase the sector we're on
+cmp al, [max_sector]
+jbe .continue_loop
+mov WORD [bp], 1
+
+inc WORD [bp + 1]
+mov al, [bp + 1]
+cmp al, [max_head]
+jbe .continue_loop
+mov WORD [bp + 1], 0
+inc DWORD [bp + 2]
+
+; loopin back ____________________________________________________
+.continue_loop:
+mov cx, [bp + 4]
+
+
+loop .sector_for_loop
+add bp, 16
+mov sp, bp
+
+
+ret
+
+
+
+
+.read_failed:
+mov bx, .loadsectors_error
+call bios_print
+cli
+hlt
+
+.loadsectors_error: db "Error loading required sector!", 0
+
+boot_device: db 0
+max_sector: db 0
+max_cylinder: dw 0
+max_head: db 0
+
diff --git a/src/bootloader/bios_functions/bios_disk.asm b/src/bootloader/bios_functions/bios_disk.asm
deleted file mode 100644
index 195057a..0000000
--- a/src/bootloader/bios_functions/bios_disk.asm
+++ /dev/null
@@ -1,40 +0,0 @@
-bios_disk:
-.load_sectors:
-pusha
-mov es, dx
-
-; TODO when our kernel gets to big to fit in one track, we need to just switch over to LHS with extended bios functions.
-
-mov ah, 0x02 ; read disc sectors
-mov ch, 0x00 ; track 0
-mov dh, 0x00 ; head 0
-mov dl, [stage0.boot_device]
-
-int 0x13
-
-jc .failed
-
-mov ah, 0
-popa
-ret
-
-.failed:
-debug:
-mov bx, .loadsectors_error
-mov cx, 0
-call bios_print
-
-push 0
-mov al, ah
-mov ah, 0 ; you need to clean up the bios print function!
-push ax
-mov cx, 1
-mov bx, sp
-call bios_print
-
-
-mov ah, 1
-popa
-ret
-
-.loadsectors_error: db "Error loading sectors: ", 0
diff --git a/src/bootloader/bios_functions/print.asm b/src/bootloader/bios_functions/print.asm
deleted file mode 100644
index 303fa8f..0000000
--- a/src/bootloader/bios_functions/print.asm
+++ /dev/null
@@ -1,58 +0,0 @@
-;TODO fix null problem, allow passing value insted of pointer
-bios_print:
-pusha
-mov ah, 0x0e
-
-.print_loop:
-mov al, [bx]
-cmp al, 0
-je .fini
-
-test cx, cx ; if cx is zero, ascii, otherwise hex string
-jne .print_hex
-int 0x10
-.print_hex_ret:
-inc bx
-jmp .print_loop
-
-.fini:
-mov al, 0xd
-int 0x10
-mov al, 0xa
-int 0x10
-popa
-ret
-
-
-.print_hex:
-mov al, '0'
-int 0x10
-
-mov al, 'x'
-int 0x10
-
-mov al, [bx]
-shr al, 4
-call .bios_print_nibble
-
-mov al, [bx]
-and al, 0x0f
-call .bios_print_nibble
-
-mov al, ' '
-int 0x10
-
-jmp .print_hex_ret
-
-
-.bios_print_nibble:
-cmp al, 9
-ja .print_hex_letter
-add al, 0x30
-int 0x10
-ret
-
-.print_hex_letter:
-add al, 0x57
-int 0x10
-ret
diff --git a/src/bootloader/bootloader.asm b/src/bootloader/bootloader.asm
index 3ac10f3..f912e49 100644
--- a/src/bootloader/bootloader.asm
+++ b/src/bootloader/bootloader.asm
@@ -1,11 +1,11 @@
[bits 16]
-[extern _kernel_size]
+[extern _kernel_sector_size]
[extern _bootloader_stage1_size]
-[extern _kernel_loc]
+[extern _kernel_s1_loc]
jmp stage0
-times 3-($-$$) db 0x90 ; a temporary dirty fix to emulate a floppy disk insted of a hard risk
-times 59 db 0 ; (TODO support hard disks)
+times 3-($-$$) db 0x90
+times 59 db 0
stage0:
@@ -14,43 +14,48 @@ jmp 0:.entry
mov ax, 0
mov ds, ax
-mov bp, ax
-
-mov ds, ax
mov es, ax
-mov ax, 0x8fc0
+;stack segments
+mov ax, 0x7000
mov ss, ax
-mov ax, 0xfffe
+mov ax, 0xfff0
mov sp, ax
+mov bp, 0
mov al, 0x92
or al, 2
out 0x92, al
-mov [.boot_device], dl
+
+call bios_disk.init
+
mov bx, .loadstage2_msg
-mov cx, 0
call bios_print
-; TODO put in an error message and a maximum fail count
.load_stage1:
-mov al, _bootloader_stage1_size
-mov cl, 0x2 ; read sector 2
-mov dx, 0x0 ; dest segment 0
-mov bx, 0x7e00 ; dest offst 0
-call bios_disk.load_sectors
+;TODO LOAD STAGE ONE HERE
+
+; we start on 0x100000
+; esi: sector start
+; cx: sector count
+; edi: memory desination
+
+mov esi, 1 ; 2nt sector
+mov ecx, _bootloader_stage1_size
+mov edi, 0x7e00 ; desination
+call bios_disk.load_sectors_v2
+
jmp mbr_end.entry
-.boot_device: db 0
.loadstage2_msg: db "Loading (stage 2) bootloader...", 0
-%include "bootloader/bios_functions/bios_disk.asm"
-%include "bootloader/bios_functions/print.asm"
+%include "bootloader/bios_disk.asm"
+%include "bootloader/print.asm"
times 510 - ($-$$) db 0
dw 0xaa55
@@ -66,15 +71,12 @@ boot_msg:
mbr_end:
.entry:
+cli
; entering unreal mode
mov bx, boot_msg.stage2_loaded
-mov cx, 0
call bios_print
-cli
-push ds
-
lgdt [protected_gdt.descriptor]
mov eax, cr0
@@ -83,52 +85,29 @@ mov cr0, eax
jmp $+2
-mov bx, 0x10 ; descriptor 2, the data descriptor
-mov ds, bx ; put it into the segment register
-mov es, bx ;
+mov bx, 0x10
+mov ds, bx
+mov es, bx
and al, 0xfe
mov cr0, eax
-pop ds
+mov bx, 0
+mov ds, bx
+mov es, bx
sti
-;we are now in unreal mode
-
-mov cl, 5
-mov edi, _kernel_loc
-.loop:
-mov al, 0x1 ; sector count
-mov dx, 0x0 ; dest addr segment
-mov bx, 0x500 ; dest addr offset
-call bios_disk.load_sectors
-
-
-inc cl
-
-push cx
-
-mov esi, 0x500
-mov ecx, 512
-a32 rep movsb
-nop
-
-pop cx
-
-cmp cl, _kernel_size+2
-je .loop_end
-
-jmp .loop
-
-.loop_end:
+mov esi, _bootloader_stage1_size
+mov edi, 0x100000
+mov ecx, _kernel_sector_size
+call bios_disk.load_sectors_v2
mov bx, boot_msg.kernel_loaded
-mov cx, 0
call bios_print
call detect_arch
-call vbe_init
+;call vbe_init
done:
call enter_longmode
diff --git a/src/bootloader/cpu_check.asm b/src/bootloader/cpu_check.asm
index 0fa6ddf..ec5ee7b 100644
--- a/src/bootloader/cpu_check.asm
+++ b/src/bootloader/cpu_check.asm
@@ -1,4 +1,4 @@
-[extern _meminfo_loc]
+[extern _meminfo]
detect_arch:
; detect CPUID
@@ -19,6 +19,7 @@ cpuid
and edx, 0x0020000000
jz .print_long_error
+
; APIC
mov eax, 0x00000001
cpuid
@@ -31,14 +32,13 @@ jz .print_sse_error
mov bx, .no_error
-mov cx, 0
call bios_print
; get memory mappings
mov ax, 0
mov es, ax
-mov ax, _meminfo_loc
+mov ax, _meminfo
mov di, ax
mov eax, 0xe820
@@ -64,50 +64,50 @@ je .mem_detected
jmp .mem_detect_loop
.mem_detected:
+add di,24
+mov ecx, 24
+mov al, 0
+rep stosb
+
ret
.print_cpuid_error:
mov bx, .cpuid_error
-mov cx, 0
call bios_print
jmp $
.print_long_error:
mov bx, .arch_error
-mov cx, 0
call bios_print
jmp $
.print_apic_error:
mov bx, .apic_error
-mov cx, 0
call bios_print
jmp $
.print_mem_error:
mov bx, .mem_error
-mov cx, 0
call bios_print
jmp $
.print_sse_error:
mov bx, .sse_error
-mov cx, 0
call bios_print
jmp $
.cpuid_error:
- db "No CPUID capabilitity", 0x0
+ db "Somehow, your CPU doesn't even support the ability to detect its abilities. I'm gonna go out on a limb and say your cpu is too old to run this OS.", 0x0
.arch_error:
- db "This operating system was compiled to run in 64 bit mode!", 0x0
+ db "This operating system requires a x64 processor.", 0x0
.apic_error:
- db "No apic support", 0x0
+ db "No APIC support.", 0x0
.mem_error:
- db "Could not get information on memory!", 0x0
+ db "Couldn't obtain memory map.", 0x0
.sse_error:
- db "This OS requires SSE", 0x0
+ db "This OS requires the SSE instruction set.", 0x0
.no_error:
- db "CPU info gathered!", 0x0
+ db "CPU meets requirements to boot!", 0x0
diff --git a/src/bootloader/enter_kernel.asm b/src/bootloader/enter_kernel.asm
index d3933cf..ef2cd71 100644
--- a/src/bootloader/enter_kernel.asm
+++ b/src/bootloader/enter_kernel.asm
@@ -1,14 +1,14 @@
[extern main]
[extern _kernel_stack_loc]
-[extern _stage1_pagetable]
+[extern _kernel_page_size]
enter_longmode:
cli
-; TODO check if a20 is already set
mov al, 0x92
or al, 2
out 0x92, al
+;enter 32 bit mode
lgdt [protected_gdt.descriptor]
mov eax, cr0
or eax, 0x1
@@ -30,44 +30,56 @@ mov es, ax
mov fs, ax
mov gs, ax
-mov edi, _stage1_pagetable ; 0x3000
-mov cr3, edi
-mov eax, 0
-mov ecx, 0xc00 ; 0x1000
-rep stosd
-mov edi, cr3
+mov edi, 0x10000
+mov cr3, edi
-mov DWORD [edi], _stage1_pagetable + 0x1003 ; pml4e[0] = pdpe
-add edi, 0x1000
-mov DWORD [edi], _stage1_pagetable + 0x2003 ; pdpe[0] = pde
-add edi, 0x1000
-mov DWORD [edi], 0x83 ; pde[0] = pte
+mov eax, 0
+mov ecx, 0x1800 ; bzero 6 pages
+rep stosd
-mov eax, cr4
-or eax, 0x620
-mov cr4, eax
+mov DWORD [0x10000], 0x11003 ; pml4e[0] = pdpe
+mov DWORD [0x11000], 0x12003 ; pdpe[0] = pde
+mov DWORD [0x12000], 0x83 ; pde[0] = pte
+
+mov DWORD [0x10ff8], 0x13003
+mov DWORD [0x13ff0], 0x14003
+mov DWORD [0x14000], 0x15003
+
+mov eax, 0x100003
+mov ebx, 0
+mov ecx, _kernel_page_size
+.kernel_load_loop:
+mov DWORD [0x15000 + ebx], eax
+add ebx, 8
+add eax, 0x1000
+loop .kernel_load_loop
-;end of setting up pages
-mov ecx, 0xc0000080
-rdmsr
-or eax, 1 << 8
-wrmsr
-mov eax, cr0
-or eax, 1 << 31 | 1 << 0 ; this is where we set paging and protected mode (respectively)!
-mov cr0, eax
+mov eax, cr4
+; PAE, OSFXSR, OSXMMEXCPT
+or eax, 1 << 5 | 1 << 9 | 1 << 10
+mov cr4, eax
+;end of setting up pages
+;testing to see if NX bit is available.
+;If it's not and we enable it, it will cause pagefaults on read
+mov eax, 0x80000001
+cpuid
+and edx, 1 << 20
+shr edx, 9
+
mov ecx, 0xc0000080
rdmsr
-or eax, 1 << 8
+or eax, 1 << 8 | 1 << 11
+or eax, edx
wrmsr
mov eax, cr0
-and ax, 0xfffb
-or eax, 0x80000002
+or eax, 1 << 31 | 1 << 0;
+and ax, ~(1 << 2)
mov cr0, eax
@@ -76,8 +88,10 @@ lgdt [long_gdt.descriptor]
jmp LONG_CODE_SEGMENT:enter_kernel
enter_kernel:
bits 64
-mov rbp, _kernel_stack_loc
+mov rbp, 0
mov rsp, _kernel_stack_loc
-call main ; where we actually call the kernel
+mov rax, QWORD main
+;push QWORD 0
+jmp rax
jmp $
ret
diff --git a/src/bootloader/gdt.asm b/src/bootloader/gdt.asm
index 0ba0a44..0e6d89b 100644
--- a/src/bootloader/gdt.asm
+++ b/src/bootloader/gdt.asm
@@ -45,8 +45,8 @@ db 0
dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!)
dw 0 ; base address 15:00
db 0 ; base address 23:16
-db 10011010b ;1st flags and type. The first four bits (1010) are type, and the last are flags. See https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf
-db 10101111b ;1111 is segment limit continued. 0: available, 0: 64 bit (change?), 1: 32 bit segment, 1: granularity (shifts 3 hex didgets to get all of memory)
+db 10011010b
+db 00100000b
db 0
.gdt_data:
@@ -54,7 +54,7 @@ dw 0
dw 0
db 0
db 10010010b
-db 00000000b
+db 00100000b
db 0
.gdt_end: ; later calculates offset in defs below
diff --git a/src/bootloader/print.asm b/src/bootloader/print.asm
new file mode 100644
index 0000000..29769f5
--- /dev/null
+++ b/src/bootloader/print.asm
@@ -0,0 +1,21 @@
+;TODO fix null problem, allow passing value insted of pointer
+bios_print:
+pusha
+mov ah, 0x0e
+
+.print_loop:
+mov al, [bx]
+cmp al, 0
+je .fini
+
+int 0x10
+inc bx
+jmp .print_loop
+
+.fini:
+mov al, 0xd
+int 0x10
+mov al, 0xa
+int 0x10
+popa
+ret
diff --git a/src/bootloader/video.asm b/src/bootloader/video.asm
index 5b292c2..e47c1dc 100644
--- a/src/bootloader/video.asm
+++ b/src/bootloader/video.asm
@@ -151,25 +151,21 @@ ret
.vbe_unsupported:
mov bx, .unsupported_msg
-mov cx, 0
call bios_print
jmp $
.vbe_generic_error:
mov bx, .lazyerror_msg
-mov cx, 0
call bios_print
jmp $
.edid_error:
mov bx, .ediderror_msg
-mov cx, 0
call bios_print
jmp $
.res_unsupported:
mov bx, .res_unsupported_msg
-mov cx, 0
call bios_print
jmp $