]> git.lizzy.rs Git - nyax.git/commitdiff
VESA support
authorElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 24 Aug 2022 00:21:23 +0000 (02:21 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 24 Aug 2022 00:21:23 +0000 (02:21 +0200)
Makefile
bios_print.asm [new file with mode: 0644]
boot.asm [deleted file]
main.asm
mbr.asm [new file with mode: 0644]
setup.asm [new file with mode: 0644]

index 193a19b187b547d189a1f06a351289d11072d8f3..850f293e338f4d09349b9a2a6fdcdf4addca5875 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,19 @@
 OBJS = main.o framebuffer.o memory.o
+DEV=/dev/sdb
 
-nyax.img: boot.out main.out
-       cat boot.out main.out > nyax.img
+nyax.img: stage1.out stage2.out stage3.out
+       cat stage{1,2,3}.out > nyax.img
 
-boot.out: boot.asm main.out
-       nasm -f bin boot.asm -o boot.out -dMAIN_SIZE=$$(stat -c%s main.out)
+stage1.out: mbr.asm stage2.out stage3.out
+       nasm -f bin mbr.asm -o stage1.out \
+               -dKSIZE=$$(du -cb stage{2,3}.out | tail -n1 | cut -f1)
 
-main.out: $(OBJS)
-       ld -o main.out -Ttext 0xD000 --oformat binary $(OBJS)
+stage2.out: setup.asm
+       nasm -f bin setup.asm -o stage2.out
+
+stage3.out: $(OBJS) stage2.out
+       ld -o stage3.out --oformat binary $(OBJS) \
+               -Ttext $$(printf "%x\n" $$(echo $$(du -b stage2.out | cut -f1)+32256 | bc))
 
 %.o: %.asm
        nasm -f elf64 $< -o $@
@@ -19,3 +25,6 @@ run: nyax.img
 .PHONY: clean
 clean:
        rm -rf *.o *.out *.img
+
+flash: nyax.img
+       dd if=./nyax.img of=$(DEV)
diff --git a/bios_print.asm b/bios_print.asm
new file mode 100644 (file)
index 0000000..3505eb6
--- /dev/null
@@ -0,0 +1,12 @@
+; uses eax, ebx
+print_str:
+       mov ah, 0x0E
+.print:
+       mov al, [ebx]
+       cmp al, 0
+       je .return
+       int 0x10
+       inc ebx
+       jmp .print
+.return:
+       ret
diff --git a/boot.asm b/boot.asm
deleted file mode 100644 (file)
index 415449e..0000000
--- a/boot.asm
+++ /dev/null
@@ -1,140 +0,0 @@
-[org 0x7C00]
-
-%define PAGETABLE 0x1000
-%define KERNEL 0xD000
-%define STACK 0x7E00
-
-boot:
-       xor ax, ax
-       mov ds, ax
-       mov es, ax
-       mov fs, ax
-       mov gs, ax
-       mov ss, ax
-
-       mov bp, STACK
-       mov sp, bp
-
-       mov ax, booting_msg
-       call print_str
-
-       mov bx, KERNEL
-       mov cl, 2
-       mov al, (MAIN_SIZE + 511) / 512
-       call load_disk
-
-       mov di, PAGETABLE+0x0000
-.clr_buf:
-       mov byte[di], 0
-       inc di
-       cmp di, PAGETABLE+0x4000
-       jne .clr_buf
-
-       mov dword[PAGETABLE+0x0000], PAGETABLE+0x1003
-       mov dword[PAGETABLE+0x1000], PAGETABLE+0x2003
-       mov dword[PAGETABLE+0x2000], PAGETABLE+0x3003
-
-       mov eax, 3
-       mov di, PAGETABLE+0x3000
-.build_pt:
-       mov [di], eax
-       add eax, 0x1000
-       add di, 8
-       cmp eax, 0x100000
-       jb .build_pt
-
-       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]
-
-       jmp 0x0008:long_mode
-
-load_disk:
-       push ax
-       mov ah, 0x02
-       xor ch, ch
-       xor dh, dh
-       int 0x13
-       jc disk_error
-       pop cx
-       cmp al, cl
-       jne disk_error
-       ret
-
-disk_error:
-       mov ax, disk_error_msg
-       call print_str
-       jmp $
-
-print_str:
-       push ax
-       push bx
-       mov bx, ax
-       mov ah, 0x0E
-.print:
-       mov al, [bx]
-       cmp al, 0
-       je .return
-       int 0x10
-       inc bx
-       jmp .print
-.return:
-       pop bx
-       pop ax
-       ret
-
-booting_msg: db 10, 13, "Loading NyaX...", 10, 10, 13, 0
-disk_error_msg: db "Disk is bwoken, cant boot ;-;", 10, 13, 0
-
-GDT:
-       dq 0
-       dq 0x00209A0000000000
-       dq 0x0000920000000000
-       dw 0
-.pointer:
-       dw $ - GDT - 1
-       dd GDT
-
-IDT:
-       dw 0
-       dd 0
-
-[bits 64]
-
-long_mode:
-       mov ax, 0x0010
-       mov ds, ax
-       mov es, ax
-       mov fs, ax
-       mov gs, ax
-       mov ss, ax
-
-       jmp KERNEL
-
-times 510-($-$$) db 0
-dw 0xAA55
index 64b9dd1e5d189ebe080493dd4d9def07db01009a..a3276281b2ff9a1cdc68dee7fb75557c1e471479 100644 (file)
--- a/main.asm
+++ b/main.asm
@@ -1,24 +1,27 @@
-global main
+global _start
 extern print_str, print_num, print_chr, clear_screen
 
 section .data
 
+headline: db "nyax stage3", 10, 10, 0
+
 disclaimer: db \
-       "NyanX", 10, \
+       "NyaX", 10, \
        "(C) 2022 Flecken-chan", 10, \
        "Dis progwam comes with ABSOLUTELY NO WAWWANTY", 10, \
        "Dis iz fwee software, and your'e welcome to redistwibute it", 10, "  under certain conditions", 10, 0
 
-greeting: db "Good morning Senpai UwU", 10, 0
-
 section .text
 
-main:
+_start:
        call clear_screen
-       mov rdi, disclaimer
+
+       mov rdi, headline
        call print_str
-       mov rdi, greeting
+
+       mov rdi, disclaimer
        call print_str
+
        xor rdi, rdi
        .loop:
        push rdi
diff --git a/mbr.asm b/mbr.asm
new file mode 100644 (file)
index 0000000..6434276
--- /dev/null
+++ b/mbr.asm
@@ -0,0 +1,61 @@
+[org 0x7C00]
+
+%define KSTART 0x7E00
+%define KSECTORS (KSIZE + 511) / 512
+
+boot:
+       ; init segment registers
+       xor ax, ax
+       mov ds, ax
+       mov es, ax
+       mov fs, ax
+       mov gs, ax
+       mov ss, ax
+
+       ; init stack
+       mov bp, KSTART ; stack grows down, overwriting MBR
+       mov sp, bp
+
+       ; print message
+       mov ebx, .msg
+       call print_str
+
+       ; load stage2 and stage3
+       call load_stages
+
+       ; jump into stage2
+       jmp KSTART
+
+.msg: db 10, 13, "nyax stage1", 10, 13, 0
+
+
+load_stages:
+       mov ebx, .msg
+       call print_str
+
+       mov ah, 0x02     ; read sectors from drive
+       mov al, KSECTORS ; number of sectors
+       xor ch, ch       ; cylinder=0
+       mov cl, 2        ; sector=2
+       xor dh, dh       ; head=0
+       mov bx, KSTART   ; buffer
+       int 0x13
+       jc .fail         ; CF set on error
+       cmp al, KSECTORS ; check read sectors count
+       jne .fail
+
+       ret
+
+.fail:
+       mov ebx, .fail_msg
+       call print_str
+       jmp $
+
+.msg: db "loading stage2 and stage3 from disk", 10, 13, 0
+.fail_msg: db "disk failure, try rebooting", 10, 13, 0
+
+
+%include "bios_print.asm"
+
+times 510-($-$$) db 0
+dw 0xAA55
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