summaryrefslogtreecommitdiff
path: root/asm/boot.asm
diff options
context:
space:
mode:
Diffstat (limited to 'asm/boot.asm')
-rw-r--r--asm/boot.asm286
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