summaryrefslogtreecommitdiff
path: root/asm
diff options
context:
space:
mode:
authorandromeda <andromeda@lenovo>2026-03-04 22:45:35 +0100
committerandromeda <andromeda@lenovo>2026-03-04 22:45:35 +0100
commit094e8c288a88db8a349492085381347ccdafc391 (patch)
tree9ee347819e3f7c3b0747c9b725e7f4c69b22d6ac /asm
parent1b6f76488dcc01c8e6c0efbe07751ebeea18c33b (diff)
use long mode, x86_64-unknown-none works now
Diffstat (limited to 'asm')
-rw-r--r--asm/boot.asm290
-rw-r--r--asm/kernel.asm8
2 files changed, 176 insertions, 122 deletions
diff --git a/asm/boot.asm b/asm/boot.asm
index bb852ef..29e807c 100644
--- a/asm/boot.asm
+++ b/asm/boot.asm
@@ -3,156 +3,210 @@
; 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
+
+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 0x7C00] ; address where bootloader is loaded
+[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 ss, ax
-mov sp, 0x7C00
-
-mov ah, 0x0E
-mov al, 'R'
-int 0x10
-mov al, 'e'
-int 0x10
-mov al, 'a'
-int 0x10
-mov al, 'l'
-int 0x10
-mov al, 0x0D
-int 0x10
-mov al, 0x0A
-int 0x10
-mov al, 0x00 ; stops serial and bios output from overlapping in qemu -nographic
-int 0x10 ; output
+mov fs, ax
+mov gs, ax
+cld
; activate a20
-mov ax, 0x2401
-int 0x15
-jc error
+mov ax, A20_LINE_ENABLE
+int BIOS_INT_MEMORY_OP
+jc error_a20_line
+mov si, msg_a20_line
+call print
-; load kernel
-; 'docs' from https://www.ctyme.com/intr/rb-0607.htm
-mov ah, 0x02
-mov al, 1 ; number of sectors to read (must be nonzero)
-mov ch, 0 ; low eight bits of cylinder number
-mov cl, 2 ; sector number 1-63 (bits 0-5); high two bits of cylinder (bits 6-7,
- ; hard disk only)
-mov dh, 0 ; head number
-; dl is already set by bios
-mov bx, 0x1000 ; data buffer
+; 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
-int 0x13 ; read disk
-jc error
-; load gdt
-lgdt [gdt_descriptor]
+; read disk
+mov ah, 0x02
+int BIOS_INT_DISK_OP
+jc error_disk_read
+mov si, msg_disk_read
+call print
-; jump to pm
-cli
-mov eax, cr0
-or eax, 1
-mov cr0, eax
-jmp 0x08:pm_start
+; zero es
+push ax
+xor ax, ax
+mov es, ax
+pop ax
-error:
- mov al, 'e'
- int 0x10
- mov al, 'r'
- int 0x10
- mov al, 'r'
- int 0x10
- mov al, 'o'
- int 0x10
- mov al, 'r'
- int 0x10
- jmp $
+mov edi, PAGE_TABLE_LOAD_ADDR
+jmp lm_load
-gdt_data:
- ; null segment
- dq 0x0000000000000000
- ; code segment
- dw 0xFFFF
- dw 0x0000
+; 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
- db 0x00
- db 10011010b ; 32-bit code segment, present, ring 0
- db 11001111b ; limit bits 16-19
- db 0x00
+ ; PDPT0E0
+ lea eax, [es:di + 2 * PAGE_TABLE_SIZE]
+ or eax, 11b
+ mov [es:di + PAGE_TABLE_SIZE], eax
- ; data segment
- dw 0xFFFF
- dw 0x0000
+ ; PDT0E0
+ lea eax, [es:di + 3 * PAGE_TABLE_SIZE]
+ or eax, 11b
+ mov [es:di + 2 * PAGE_TABLE_SIZE], eax
- db 0x00
- db 10010010b ; 32-bit data segment, present, ring 0
- db 11001111b ; limit bits 16-19
- db 0x00
+ ; 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_a20_line:
+ mov si, .msg
+ call print
+ jmp done
+ .msg db "err a20 line", 0x00
+
+error_disk_read:
+ mov si, .msg
+ call print
+ jmp done
+ .msg db "err disk read", 0x00
+
+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 real idt
+empty_idt:
+ dw 0 ; length
+ dd 0 ; base
+
+; 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 32]
+[bits 64]
-; entry point
-pm_start:
- ; data segment registers
+; long mode entry
+lm_start:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
- mov esp, 0x80000
- ; TODO actually configure COM1
- mov dx, 0x3F8 ; COM1
- mov al, 'P'
- out dx, al
- mov al, 'r'
- out dx, al
- mov al, 'o'
- out dx, al
- mov al, 't'
- out dx, al
- mov al, 'e'
- out dx, al
- mov al, 'c'
- out dx, al
- mov al, 't'
- out dx, al
- mov al, 'e'
- out dx, al
- mov al, 'd'
- out dx, al
- mov al, 0x0D
- out dx, al
- mov al, 0x0A
- out dx, al
+ ; set up serial device
+ ; TODO poll and whatnot (in rust??)
+ mov dx, 0x3F8
+
+ jmp KERNEL_LOAD_ADDR_ES * 0x10
- jmp 0x08:0x10000
+msg_a20_line db "a20 line", 0x0D, 0x0A, 0x00
+msg_disk_read db "disk read", 0x0D, 0x0A, 0x00
-pm_error:
- mov al, 'p'
- out dx, al
- mov al, 'm'
- out dx, al
- mov al, 'e'
- out dx, al
- mov al, 'r'
- out dx, al
- mov al, 'r'
- out dx, al
- mov al, 'o'
- out dx, al
- mov al, 'r'
- out dx, al
- jmp $
-
times 510-($-$$) db 0 ; 2 bytes less now
db 0x55
db 0xAA
diff --git a/asm/kernel.asm b/asm/kernel.asm
index 23c0d5d..b4cbb30 100644
--- a/asm/kernel.asm
+++ b/asm/kernel.asm
@@ -1,4 +1,4 @@
-[bits 32]
+[bits 64]
mov al, 'K'
out dx, al
@@ -18,6 +18,6 @@ mov al, 0x0A
out dx, al
mov al, 0x00
out dx, al
-jmp $
-
-times 512-($-$$) db 0
+.done
+ hlt
+ jmp .done