diff options
Diffstat (limited to 'asm/boot.asm')
| -rw-r--r-- | asm/boot.asm | 286 |
1 files changed, 0 insertions, 286 deletions
diff --git a/asm/boot.asm b/asm/boot.asm deleted file mode 100644 index 5291d58..0000000 --- a/asm/boot.asm +++ /dev/null @@ -1,286 +0,0 @@ -; bootler -; legacy bootloader in nasm-flavoured asm -; 2026 Andromeda -; GPL licensed - -LOAD_ADDR equ 0x7C00 - -KERNEL_START equ 2 ; first sector on disk to load kernel from; 1 indexed -KERNEL_SIZE equ 1 ; length of kernel in sectors -KERNEL_LOAD_ADDR_ES equ 0x1000 ; kernel to be loaded at es * 0x10 + 0x0000 - -PAGE_TABLE_LOAD_ADDR equ 0x1000 ; start of page table; 4 * pt size -PAGE_TABLE_SIZE equ 0x1000 ; size of page table in bytes - -; 64 bit IDT stuff -IDT_ADDR equ 0x8000 ; bottom of IDT -IDT_SIZE equ 0x1000 ; size of IDT - -IDT_SEGMENT equ 0x0008 ; gdt code segment to jump to for idt calls - -; magic numbers and things -A20_LINE_ENABLE equ 0x2401 ; magic number in ax to enable a20 line with 0x15 -BIOS_INT_DISK_OP equ 0x13 -BIOS_INT_MEMORY_OP equ 0x15 - -CR0_PE equ 1 << 0 ; Protected Mode Enabled -CR0_PG equ 1 << 31 ; Paging - -CR4_PAE equ 1 << 5 ; Physical Address Extension -CR4_PGE equ 1 << 7 ; Page Global Enabled - -MSR_IA32_EFER equ 0xC0000080 ; Extended Feature Enable model-specific Register - -[bits 16] -[org LOAD_ADDR] - -jmp 0x0000:.cs_reset ; in case it loads us at 0x7C00:0x0000 -.cs_reset: - -xor ax, ax -mov ss, ax -mov sp, LOAD_ADDR ; stack builds down, loader faces up -mov ds, ax -mov es, ax -mov fs, ax -mov gs, ax -cld - -; activate a20 -mov ax, A20_LINE_ENABLE -int BIOS_INT_MEMORY_OP -jc error -mov si, msg_a20_line -call print - -; prep to read disk -mov al, KERNEL_SIZE ; size in sectors, min. 1 -mov ch, 0 ; cylinder -mov cl, KERNEL_START ; start sector, 1-indexed -mov dh, 0 ; head -; dl set by bios -mov bx, KERNEL_LOAD_ADDR_ES ; load addr es:bx -mov es, bx -xor bx, bx - -; read disk -mov ah, 0x02 -int BIOS_INT_DISK_OP -jc error -mov si, msg_disk_read -call print - -; zero es -push ax -xor ax, ax -mov es, ax -pop ax - -mov edi, PAGE_TABLE_LOAD_ADDR -jmp lm_load - -; expects: -; es:edi -> 16kb for page table -; ss:esp -> stack -; heavily based on https://wiki.osdev.org/Entering_Long_Mode_Directly -lm_load: - ; clear page table - push di - mov ecx, PAGE_TABLE_SIZE - xor eax, eax - cld - rep stosd ; clear space for all 4 tables - pop di - - ; PML4TE0 - lea eax, [es:di + PAGE_TABLE_SIZE] - or eax, 11b - mov [es:di], eax - - ; PDPT0E0 - lea eax, [es:di + 2 * PAGE_TABLE_SIZE] - or eax, 11b - mov [es:di + PAGE_TABLE_SIZE], eax - - ; PDT0E0 - lea eax, [es:di + 3 * PAGE_TABLE_SIZE] - or eax, 11b - mov [es:di + 2 * PAGE_TABLE_SIZE], eax - - ; PT0 - push di - lea di, [di + 3 * PAGE_TABLE_SIZE] - mov eax, 0x11 - - .set_pt_entry - mov [es:di], eax - add eax, 0x1000 - add di, 8 - cmp eax, 0x200000 ; size of page - jb .set_pt_entry - - pop di - - ; disable interrupts from PIC by masking all interrupts - mov al, 0xFF ; mask - out 0xA1, al - out 0x21, al - - ; PAE, PGE - mov eax, CR4_PAE | CR4_PGE - mov cr4, eax - - ; cr3 -> PML4TE0 - mov edx, edi - mov cr3, edx - - ; highs LME bit in EFER - mov ecx, MSR_IA32_EFER - rdmsr - or eax, 0x00000100 - wrmsr - - ; activate long mode - mov ebx, cr0 - or ebx, CR0_PG | CR0_PE - mov cr0, ebx - - cli - lgdt [gdt_descriptor] - - jmp 0x08:lm_start - -error: - mov si, .msg - call print - .msg db "err ", 0x00 - ret - -done: - hlt - jmp done - -print: - pushad - .loop - lodsb - test al, al - je .done - mov ah, 0x0E - int 0x10 - jmp .loop - .done - popad - ret - -; TODO make readable (yoinked from https://wiki.osdev.org/Entering_Long_Mode_Directly) -gdt_data: - dq 0x0000000000000000 - dq 0x00209A0000000000 - dq 0x0000920000000000 - -gdt_descriptor: - dw $ - gdt_data - 1 ; size - dd gdt_data ; start - -[bits 64] - -; long mode entry -lm_start: - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - - ; set up serial device - ; TODO poll and whatnot (in rust??) - mov dx, 0x3F8 - - ; qemu -no-graphic overlaps serial and bios output without this - mov al, 0x0D - out dx, al - mov al, 0x0A - out dx, al - - ; initialize IDT at IDT_ADDR - call idt_init - - int3 ; silly test - - jmp KERNEL_LOAD_ADDR_ES * 0x10 - -idt_init: - ; clear space for idt - mov rdi, IDT_ADDR - push di - mov rcx, IDT_SIZE / 4 - xor rax, rax - cld - rep stosd ; clear double word for each rcx - pop di - - push rdx ; dx contains the output device - ; nothing between here and the `pop rdx` will be able to print - - ; breakpoint - mov rdi, 0x8E ; present, no dpl, interrupt - mov rsi, 0x03 ; breakpoint interrupt - lea rdx, [int_hdl_dummy] - call mk_idt_entry - - pop rdx ; get back dx output device - - lidt [idt_descriptor] - - ret - -int_hdl_dummy: - mov rsi, .msg - call lm_print - iretq - .msg db "INTdummy", 0x0D, 0x0A, 0x00 - -; rdi = flags -; rsi = entry number -; rdx -> handler -mk_idt_entry: - mov rax, rdx - mov rcx, rsi - - shl rcx, 4 ; offset = entry number * 16 - add rcx, IDT_ADDR - - mov word [rcx + 0], ax ; offset - mov word [rcx + 2], IDT_SEGMENT ; code segment - mov word [rcx + 5], di - mov byte [rcx + 4], 0 ; IST (0 = none) - shr rax, 16 - mov word [rcx + 6], ax ; offset - shr rax, 16 - mov dword [rcx + 8], eax ; offset - mov dword [rcx + 12], 0 ; reserved - ret - -lm_print: - .loop - mov al, [rsi] - test al, al - jz .done - out dx, al - inc si - jmp .loop - .done: - ret - -idt_descriptor: - dw IDT_SIZE - 1 ; size - dq IDT_ADDR ; start - -msg_a20_line db "a20 line", 0x0D, 0x0A, 0x00 -msg_disk_read db "disk", 0x0D, 0x0A, 0x00 - -times 510-($-$$) db 0 ; 2 bytes less now -db 0x55 -db 0xAA |
