-[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