From: John Tsiombikas Date: Mon, 4 Jul 2022 05:43:18 +0000 (+0300) Subject: test: dropping to 32bit protected mode X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=efitest3;a=commitdiff_plain;h=ec88f1d0899fa575bb443d547779a4fa22c9fcb5 test: dropping to 32bit protected mode --- diff --git a/Makefile b/Makefile index a2b0638..1f4e102 100644 --- 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 diff --git a/efitest.asm b/efitest.asm index 2cc79a2..26d29d1 100644 --- a/efitest.asm +++ b/efitest.asm @@ -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: