test: dropping to 32bit protected mode
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 4 Jul 2022 05:43:18 +0000 (08:43 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 4 Jul 2022 05:43:18 +0000 (08:43 +0300)
Makefile
efitest.asm

index a2b0638..1f4e102 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,11 +22,11 @@ clean:
 
 .PHONY: run
 run: disk.img
-       qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -hda $<
+       qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -hda $< -net none -serial stdio
 
 .PHONY: debug
 debug: disk.img
-       qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -S -s -hda $<
+       qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -S -s -hda $< -net none -serial stdio
 
 
 disasm: bootx64.efi
index 2cc79a2..26d29d1 100644 (file)
@@ -1,74 +1,29 @@
 ; vi:ft=nasm:
        bits 64
        org 100000h
-       default rel
-
-       ; EFI_SYSTEM_TABLE offsets
-SIMPLE_TEXT_OUTPUT     equ 64
-BOOT_SERVICES          equ 80
-
-       ; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL function offsets
-TEXT_OUT_STRING                equ 8
-TEXT_SET_ATTR          equ 40
-TEXT_CLEAR_SCREEN      equ 48
-
-       ; EFI_BOOT_SERVICES function offsets
-BOOT_GET_MEMORY_MAP    equ 56
-BOOT_EXIT_BOOT_SERVICES        equ 232
-
 
 start:
-       mov [efihandle], rcx
-       mov [systab], rdx
-
-       mov rax, [rdx + BOOT_SERVICES]
-       mov [bootsrv], rax
-       sub rsp, 32                     ; leave space for shadow area
-       and rsp, 0xfffffffffffffff0     ; make sure sp is 16-byte aligned
-
-       mov rcx, [rdx + SIMPLE_TEXT_OUTPUT]
-       mov rdx, 0x0c
-       call [rcx + TEXT_SET_ATTR]
-
-       mov rax, [systab]
-       mov rcx, [rax + SIMPLE_TEXT_OUTPUT]
-       call [rcx + TEXT_CLEAR_SCREEN]
-
-       mov rax, [systab]
-       mov rcx, [rax + SIMPLE_TEXT_OUTPUT]
-       lea rdx, [str_hello]
-       call [rcx + TEXT_OUT_STRING]
-
-       
-       mov rax, [systab]
-       mov rcx, [rax + SIMPLE_TEXT_OUTPUT]
-       mov rdx, 0x07
-       call [rcx + TEXT_SET_ATTR]
-
        call get_rip
-       mov rdi, rax
-       call printhex64
-       call newline
-
-       ; retrieve memory map
-       ; args: RCX, RDX, R8, and R9.
-       lea rcx, [mmap_size]
-       lea rdx, [mmapbuf]
-       lea r8, [mmap_key]
-       lea r9, [mmap_descsz]
-       lea rax, [mmap_descver]
-       push rax
-       push rax
-       mov rax, [systab]
-       mov rbx, [rax + BOOT_SERVICES]
-       call [rbx + BOOT_GET_MEMORY_MAP]
-       add rsp, 16
-
-       mov rcx, [efihandle]
-       mov rdx, [mmap_key]
-       mov rax, [systab]
-       mov rbx, [rax + BOOT_SERVICES]
-       call [rbx + BOOT_EXIT_BOOT_SERVICES]
+.after_call:
+       sub rax, .after_call - start
+       mov rsi, rax    ; source address
+       mov rdi, start  ; destination
+       mov rcx, end - start
+       shr rcx, 2      ; dwords
+       cld
+       rep movsd       ; copy code to make it absolute
+
+       mov rax, .abs
+       jmp rax
+.abs:
+       call setup_serial
+
+       ; switch to 32-bit compatibility long mode
+       lgdt [gdtlim]
+       push word 8
+       push qword start32
+       retfq
+
 
 .hang: jmp .hang
 
@@ -76,53 +31,112 @@ get_rip:
        mov rax, [rsp]
        ret
 
-       ; expects number in rdi
-printhex64:
-       mov rcx, 16
-       lea rbx, [hexbuf]
-.loop: rol rdi, 4
-       mov rax, rdi
-       and rax, 0xf
-       lea rdx, [hexdig]
-       shl rax, 1
-       add rdx, rax
-       mov ax, [rdx]
-       mov [rbx], ax
-       add rbx, 2
-       dec rcx
-       jnz .loop
-       mov word [rbx], 0
-       lea rdi, [hexbuf]
-
-       ; expects string in rdi
-printstr:
-       mov rcx, [systab]
-       mov rcx, [rcx + SIMPLE_TEXT_OUTPUT]
-       mov rdx, rdi
-       sub rsp, 32
-       call [rcx + TEXT_OUT_STRING]
-       add rsp, 32
+
+UART_DATA              equ 0x3f8
+UART_DIVLO             equ 0x3f8
+UART_DIVHI             equ 0x3f9
+UART_FIFO              equ 0x3fa
+UART_LCTL              equ 0x3fb
+UART_MCTL              equ 0x3fc
+UART_LSTAT             equ 0x3fd
+DIV_9600               equ 115200 / 9600
+LCTL_8N1               equ 0x03
+LCTL_DLAB              equ 0x80
+FIFO_ENABLE_CLEAR      equ 0x07
+MCTL_DTR_RTS_OUT2      equ 0x0b
+LST_TREG_EMPTY         equ 0x20
+
+       ; serial port setup
+setup_serial:
+       ; set clock divisor
+       mov al, LCTL_DLAB
+       mov dx, UART_LCTL
+       out dx, al
+       mov ax, DIV_9600
+       mov dx, UART_DIVLO
+       out dx, al
+       mov al, ah
+       mov dx, UART_DIVHI
+       out dx, al
+       ; set format 8n1
+       mov al, LCTL_8N1
+       mov dx, UART_LCTL
+       out dx, al
+       ; clear and enable fifo
+       mov al, FIFO_ENABLE_CLEAR
+       mov dx, UART_FIFO
+       out dx, al
+       ; assert RTS and DTR
+       mov al, MCTL_DTR_RTS_OUT2
+       mov dx, UART_MCTL
+       out dx, al
        ret
 
-newline:
-       lea rdi, [str_hello + 18]
-       jmp printstr
+str_hello db 'hello!',13,10,0
 
-hexdig dw __utf16__ "0123456789abcdef"
-hexbuf: times 40 db 0
+       align 4
+gdtlim dw 23
+gdtbase        dq gdt
 
        align 8
-efihandle dq 0
-systab dq 0
-bootsrv dq 0
-str_hello dw __utf16__(`qurashee!\r\n`),0
+gdt:   ; 0: null segment
+       dd 0, 0
+       ; 1: code - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:code/non-conf/rd
+       dd 0x0000ffff
+       dd 0x00cf9a00
+       ; 2: data - base:0, lim:4g, G:4k, 32bit, avl, pres|app, dpl:0, type:data/rw
+       dd 0x0000ffff
+       dd 0x00cf9200
+
+
+       bits 32
+start32:
+       mov ax, 10h
+       mov ds, ax
+       mov ss, ax
+       mov es, ax
+       mov gs, ax
+       mov fs, ax
+
+       ; disable paging to deactivate long mode
+       mov eax, cr0
+       and eax, 7fffffffh
+       mov cr0, eax
+
+       ; disable long mode (EFER.LME = 0)
+       ; TODO: EFER is MSR c0000080, LME is bit 8
+       mov ecx, 0c0000080h
+       rdmsr
+       and eax, 0fffffeffh
+       wrmsr
+
+       mov esi, str_hello
+       call ser_putstr
+
+.hang: hlt
+       jmp .hang
 
-       align 8
-; memory map data
-mmap_size dq 0
-mmap_key dq 0
-mmap_descsz dq 0
-mmap_descver dq 0
-
-       align 4096
-mmapbuf: times 4096 db 0
+       
+ser_putchar:
+       mov ah, al
+       ; wait until transmit register is empty
+       mov dx, UART_LSTAT
+.wait: in al, dx
+       and al, LST_TREG_EMPTY
+       jz .wait
+       mov dx, UART_DATA
+       mov al, ah
+       out dx, al
+       ret
+
+ser_putstr:
+       mov al, [esi]
+       test al, al
+       jz .done
+       call ser_putchar
+       inc esi
+       jmp ser_putstr
+.done: ret
+
+
+end: