bits 64 org 1000h %include "src/serial.inc" BOOT_SERVICES equ 96 BOOT_GET_MEMORY_MAP equ 56 BOOT_EXIT_BOOT_SERVICES equ 232 start: mov [efihandle], rcx mov [systab], rdx ; 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 sub rsp, 32 mov rax, [systab] mov rbx, [rax + BOOT_SERVICES] call [rbx + BOOT_GET_MEMORY_MAP] add rsp, 40 ; exit boot services mov rcx, [efihandle] mov rdx, [mmap_key] mov rax, [systab] mov rbx, [rax + BOOT_SERVICES] call [rbx + BOOT_EXIT_BOOT_SERVICES] ; move code to absolute 1000h call get_rip .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 get_rip: mov rax, [rsp] ret ; 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 ; ----------- 32bit code ---------- 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 ; halt for ever sti halt: hlt jmp halt 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, [si] test al, al jz .done call ser_putchar inc si jmp ser_putstr .done: ret ; ---------- data ------------ align 8 efihandle dq 0 systab dq 0 ; memory map data mmap_size dq 4096 mmap_key dq 0 mmap_descsz dq 0 mmap_descver dq 0 align 4096 mmapbuf: times 4096 db 0 str_hello db 'hello!',13,10,0 align 4 gdtlim dw 31 gdtbase dq gdt align 8 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 ; 3: code16 dd 0x0000ffff dd 0x00009a00 align 4 end: ; vi:ft=nasm: