]> git.lizzy.rs Git - nyax.git/blobdiff - setup.asm
VESA support
[nyax.git] / setup.asm
diff --git a/setup.asm b/setup.asm
new file mode 100644 (file)
index 0000000..0351501
--- /dev/null
+++ b/setup.asm
@@ -0,0 +1,357 @@
+[org 0x7E00]
+
+%define PAGETABLE 0x1000
+%define VESAINFO  0x0500
+%define VESAMODE VESAINFO+512
+%define OWNMODE  VESAMODE+256
+%define GFXINFO 0x500
+
+setup:
+       ; print message
+       mov ebx, .msg
+       call print_str
+
+       ; setup VESA
+       call vesa
+
+       ; get extended memory map
+       call mmap
+
+       ; build page table
+       call paging
+
+       ; jump into long mode
+       jmp 0x0008:long_mode
+
+.msg:
+       db 10, 13, "nyax stage2", 10, 13, 0
+
+
+vesa:
+       ; print message
+       mov ebx, .msg
+       call print_str
+
+       ; get vesa bios info
+       mov eax, dword[.vbe2]
+       mov dword[VESAINFO], eax ; move "VBE2" to start of vesainfo struct
+       mov ax, 0x4F00           ; get VESA BIOS information
+       mov di, VESAINFO         ; struct buffer
+       int 0x10
+
+       cmp ax, 0x004F           ; check ax for correct magic number
+       jne .fail_getinfo
+
+       mov eax, dword[.vesa]
+       cmp dword[VESAINFO], eax ; check if "VESA" is at start of stuct
+       jne .fail_getinfo
+
+       ; print select message
+       mov ebx, .select_msg
+       call print_str
+
+       ; get segment:offset pointer to video modes into gs:ebx
+       movzx ebx, word[VESAINFO+14]
+       mov    ax, word[VESAINFO+16]
+       mov gs, ax
+
+       ; convert modes to own structure
+
+       xor esi, esi        ; number of avail modes
+
+.mode_loop:
+       ; get mode info
+       mov cx, [gs:ebx]    ; video mode into cx
+       cmp cx, 0xFFFF      ; 0xFFFF is terminator, no suitable mode has been found
+       je .mode_done
+       mov ax, 0x4F01      ; get VESA mode information
+       mov di, VESAMODE    ; vesa mode info struct buffer
+       int 0x10
+
+       cmp ax, 0x004F      ; check ax for correct magic number
+       jne .fail_modeinfo
+
+       mov al, byte[VESAMODE] ; get attributes
+       and al, 0b10000000     ; extract bit 7, indicates linear framebuffer support
+       jz .mode_next
+
+       mov al, byte[VESAMODE+25] ; get bpp (bits per pixel)
+       cmp al, 32
+       jne .mode_next
+
+       push ebx ; print_num and print_str modify ebx
+
+       mov eax, esi
+       mov ebx, 12
+       mul ebx
+       mov edi, eax
+       add edi, OWNMODE
+
+       mov [edi+10], cx ; copy mode
+
+       mov eax, edi
+       call print_num
+
+       ; print selector
+       mov al, '['
+       call print_chr
+
+       mov eax, esi
+       add eax, 'a'
+       call print_chr
+
+       mov al, ']'
+       call print_chr
+
+       mov al, ' '
+       call print_chr
+
+       mov ax, [VESAMODE+16] ; copy pitch
+       mov [edi+0], ax
+
+       movzx eax, word[VESAMODE+18] ; copy width
+       mov [edi+2], ax
+       call print_num
+
+       mov al, 'x'
+       call print_chr
+
+       movzx eax, word[VESAMODE+20] ; copy height
+       mov [edi+4], ax
+       call print_num
+       call newline
+
+       mov eax, [VESAMODE+40] ; copy framebuffer
+       mov [edi+6], eax
+
+       pop ebx
+
+       inc esi
+       cmp esi, 'z'-'a'   ; only print up to z
+       jg .mode_done
+
+.mode_next:
+       add ebx, 2         ; increase mode pointer
+       jmp .mode_loop     ; loop
+
+.mode_done:
+       cmp esi, 0
+       je .fail_nomode
+
+.input:
+       mov ebx, .select_prompt
+       call print_str
+
+       mov ah, 0x00   ; get keypress, blocking
+       int 0x16
+
+       call print_chr ; echo user input
+
+       movzx edi, al  ; backup al
+       call newline
+
+       sub edi, 'a'
+       cmp edi, esi
+       jb .valid      ; check validity
+
+       mov ebx, .invalid
+       call print_str
+
+       jmp .input
+
+.valid:
+       mov eax, edi
+       call print_num
+       call newline
+
+       ; convert selected number to address
+       mov eax, edi
+       mov ebx, 12
+       mul ebx
+       add eax, OWNMODE
+
+       ; copy to final gfx info location
+       mov ebx, [eax]
+       mov [GFXINFO], ebx
+
+       mov ebx, [eax+4]
+       mov [GFXINFO+4], ebx
+
+       mov bx, [eax+6]
+       mov [GFXINFO+6], bx
+
+       ; set mode
+       mov bx, [eax+10]           ; video mode in bx (first 13 bits)
+       or  bx, 0b0100000000000000 ; set bit 14: enable linear frame buffer
+       and bx, 0b0111111111111111 ; clear deprecated bit 15
+       mov ax, 0x4F02             ; set VBE mode
+       int 0x10
+
+       ret
+
+.msg: db "setting up vesa", 10, 13, 0
+.vbe2: db "VBE2"
+.vesa: db "VESA"
+.select_msg: db "avaliable video modes:", 10, 13, 0
+.select_prompt: db "select video mode: ", 0
+.invalid: db "invalid input", 10, 13, 0
+
+.fail_getinfo:
+       mov ebx, .fail_getinfo_msg
+       jmp .fail
+
+.fail_modeinfo:
+       mov ebx, .fail_modeinfo_msg
+       jmp .fail
+
+.fail_nomode:
+       mov ebx, .fail_nomode_msg
+       jmp .fail
+
+.fail_getinfo_msg: db "failed getting vesa bios info", 10, 13, 0
+.fail_modeinfo_msg: db "failed getting video mode info", 10, 13, 0
+.fail_nomode_msg: db "no suitable video modes available", 10, 13, 0
+
+.fail:
+       call print_str
+       jmp $
+
+
+mmap:
+       mov ebx, .msg
+       call print_str
+
+       ret
+
+.msg: db "getting extended memory map", 10, 13, 0
+
+
+paging:
+       ; print message
+       mov ebx, .msg
+       call print_str
+
+       ; clear 4 levels of page maps
+       mov di, PAGETABLE+0x0000
+.clr_buf:
+       mov byte[di], 0
+       inc di
+       cmp di, PAGETABLE+0x4000
+       jne .clr_buf
+
+       ; init 3 page map levels
+       mov dword[PAGETABLE+0x0000], PAGETABLE+0x1003
+       mov dword[PAGETABLE+0x1000], PAGETABLE+0x2003
+       mov dword[PAGETABLE+0x2000], PAGETABLE+0x3003
+
+       ; fill up level 4 page map
+       mov eax, 3
+       mov di, PAGETABLE+0x3000
+.build_pt:
+       mov [di], eax
+       add eax, 0x1000
+       add di, 8
+       cmp eax, 0x100000
+       jb .build_pt
+
+       ; enable paging and long mode
+
+       mov di, PAGETABLE
+
+       mov al, 0xFF
+       out 0xA1, al
+       out 0x21, al
+
+       nop
+       nop
+
+       lidt [.idt]
+
+       mov eax, 0b10100000
+       mov cr4, eax
+
+       mov edx, edi
+       mov cr3, edx
+
+       mov ecx, 0xC0000080
+       rdmsr
+
+       or eax, 0x00000100
+       wrmsr
+
+       mov ebx, cr0
+       or ebx, 0x80000001
+       mov cr0, ebx
+
+       lgdt [.gdt_pointer]
+
+       ret
+
+.gdt:
+       dq 0
+       dq 0x00209A0000000000
+       dq 0x0000920000000000
+       dw 0
+
+.gdt_pointer:
+       dw $ - .gdt - 1
+       dd .gdt
+
+.idt:
+       dw 0
+       dd 0
+
+.msg:
+       db "building page table", 10, 13, 0
+
+
+%include "bios_print.asm"
+
+; uses eax, ebx, ecx, edx
+print_num:
+       mov ebx, 10
+       xor ecx, ecx
+.convert:
+       inc ecx
+       xor edx, edx
+       div ebx
+       add dl, '0'
+       push dx
+       cmp eax, 0
+       jne .convert
+.print:
+       cmp ecx, 0
+       je .return
+       dec ecx
+       pop ax
+       mov ah, 0x0E
+       int 0x10
+       jmp .print
+.return:
+       ret
+
+
+newline:
+       mov al, 10
+       call print_chr
+
+       mov al, 13
+       call print_chr
+
+       ret
+
+print_chr:
+       mov ah, 0x0E
+       int 0x10
+       ret
+
+[bits 64]
+
+long_mode:
+       ; setup segment registers
+       mov ax, 0x0010
+       mov ds, ax
+       mov es, ax
+       mov fs, ax
+       mov gs, ax
+       mov ss, ax