From 9b22a6965579ea1867aea291d910c96f386b518b Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Tue, 24 Aug 2021 14:09:29 -0500 Subject: major backup 8.24.21 --- src/bootloader/bios_disk.asm | 149 ++++++++++++++++++++++++++++ src/bootloader/bios_functions/bios_disk.asm | 40 -------- src/bootloader/bios_functions/print.asm | 58 ----------- src/bootloader/bootloader.asm | 95 +++++++----------- src/bootloader/cpu_check.asm | 28 +++--- src/bootloader/enter_kernel.asm | 72 ++++++++------ src/bootloader/gdt.asm | 6 +- src/bootloader/print.asm | 21 ++++ src/bootloader/video.asm | 4 - 9 files changed, 267 insertions(+), 206 deletions(-) create mode 100644 src/bootloader/bios_disk.asm delete mode 100644 src/bootloader/bios_functions/bios_disk.asm delete mode 100644 src/bootloader/bios_functions/print.asm create mode 100644 src/bootloader/print.asm (limited to 'src/bootloader') 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: @@ -13,44 +13,49 @@ jmp 0:.entry .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 $ -- cgit v1.2.3