wrote a basic bootloader

This commit is contained in:
2025-02-25 01:14:52 +00:00
commit 012b0454ed
36 changed files with 1667 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
[BITS 16]
[ORG 0x7c00]
start:
mov ah,0x00 ; set mode
mov al,0x03 ; set vga text buffer mode (80x25)
int 0x10 ; call bios
cli
in al, 0x92
or al, 2
out 0x92, al
xor ax, ax
mov ds, ax
lgdt [GDT_PTR]
mov eax, 0x11
mov cr0, eax
jmp GDT_BOOT_CS-GDT:protmode
[BITS 32]
protmode:
mov ax, GDT_BOOT_DS-GDT
mov ds, ax
mov ss, ax
mov es, ax
mov esp, 0x90000 ; temporary stack
mov edi, 0xb8000
mov eax, "P R "
stosd
hang:
pause
jmp hang
GDT_PTR:
dw GDT_END-GDT-1
dd GDT
align 16
GDT:
GDT_NULL: dq 0 ; segment zero cannot be used
GDT_BOOT_DS: dq 0X00CF92000000FFFF
GDT_BOOT_CS: dq 0X00CF9A000000FFFF
GDT_END:
times 510-$+start db 0;
db 0x55;
db 0xaa;
+118
View File
@@ -0,0 +1,118 @@
[BITS 16]
[ORG 0x7C00]
; Initialize segment registers
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
; Reset disk system
mov ah, 0
int 0x13
; Load FAT32 BPB
mov si, bpb_oem_name
mov di, 0x7E00
mov cx, bpb_size
rep movsb
; Read FAT32 root directory
mov ax, [bpb_reserved_sectors]
mov [dapack.lba_start], ax
mov ah, 0x42
mov si, dapack
int 0x13
jc error
; Find kernel file
mov si, kernel_name
mov di, 0x8000
mov cx, 11 ; FAT32 8.3 filename length
find_kernel:
push cx
push si
push di
rep cmpsb
pop di
pop si
pop cx
je found_kernel
add di, 32 ; Move to next directory entry
cmp di, 0x8200 ; Check if we've reached the end of the sector
jl find_kernel
; Kernel not found
mov si, err_no_kernel
call print
jmp $
found_kernel:
; Get cluster number
mov ax, [di + 20] ; High word
shl eax, 16
mov ax, [di + 26] ; Low word
; Load kernel
mov [cluster], eax
call load_cluster
; Jump to kernel
jmp 0x8000
error:
mov si, err_disk
call print
jmp $
print:
lodsb
or al, al
jz .done
mov ah, 0x0E
int 0x10
jmp print
.done:
ret
load_cluster:
; Convert cluster to LBA
sub eax, 2
mul dword [sectors_per_cluster]
add eax, [first_data_sector]
mov [dapack.lba_start], eax
mov ah, 0x42
mov si, dapack
int 0x13
ret
align 4
dapack:
db 0x10 ; Size of packet
db 0 ; Reserved
dw 1 ; Number of sectors
dw 0x8000 ; Offset
dw 0 ; Segment
dq 0 ; LBA
cluster: dd 0
sectors_per_cluster: dd 8
first_data_sector: dd 0
kernel_name: db "KERNEL BIN"
err_disk: db "Disk error", 0
err_no_kernel: db "No kernel", 0
bpb_oem_name: times 8 db 0
bpb_bytes_per_sector: dw 512
bpb_sectors_per_cluster: db 8
bpb_reserved_sectors: dw 32
bpb_size: equ $ - bpb_oem_name
times 510-($-$$) db 0
dw 0xAA55
@@ -0,0 +1,83 @@
.section .efi.text, "ax"
.global _start
.code64 // UEFI is already in 64-bit protected mode
_start:
// Save UEFI parameters
mov %rcx, uefi_image_handle
mov %rdx, uefi_system_table
// Get memory map
call get_memory_map
// Exit boot services
mov uefi_image_handle, %rcx
mov memory_map_key, %rdx
call exit_boot_services
// Disable interrupts
cli
// Load GDT for long mode
lgdt gdt64_pointer(%rip)
// Setup page tables (identity map first 2MB + map kernel to higher half)
call setup_page_tables
// Enable PAE
mov %cr4, %rax
or $(1 << 5), %rax
mov %rax, %cr4
// Set long mode bit
mov $0xC0000080, %ecx
rdmsr
or $(1 << 8), %eax
wrmsr
// Enable paging
mov %cr0, %rax
or $0x80000000, %rax
mov %rax, %cr0
// Long jump to higher half kernel
lea higher_half(%rip), %rax
jmp *%rax
.align 8
higher_half:
// Now in long mode at higher half
// Setup stack and jump to Rust code
mov $kernel_stack_top, %rsp
call kmain
// GDT for long mode
.align 16
gdt64:
.quad 0 // Null descriptor
.quad 0x00AF9A000000FFFF // Code segment
.quad 0x00CF92000000FFFF // Data segment
gdt64_pointer:
.word gdt64_pointer - gdt64 - 1
.quad gdt64
.section .efi.data, "aw"
uefi_image_handle: .quad 0
uefi_system_table: .quad 0
memory_map_key: .quad 0
.section .bss
.align 4096
kernel_stack_bottom:
.skip 16384 // 16 KB stack
kernel_stack_top:
// Page tables
.align 4096
pml4_table:
.skip 4096
pdpt_table:
.skip 4096
pd_table:
.skip 4096
@@ -0,0 +1,94 @@
.section .efi.text
// Function to get UEFI memory map
get_memory_map:
push %rbp
mov %rsp, %rbp
// Local variables for memory map
sub $48, %rsp
mov $0, -8(%rbp) // memory_map_size
mov $0, -16(%rbp) // memory_map_buffer
mov $0, -24(%rbp) // map_key
mov $0, -32(%rbp) // descriptor_size
mov $0, -40(%rbp) // descriptor_version
// First call to get size
lea -8(%rbp), %rcx // memory_map_size
mov $0, %rdx // memory_map
lea -24(%rbp), %r8 // map_key
lea -32(%rbp), %r9 // descriptor_size
push $0 // descriptor_version
call boot_services_get_memory_map
// Allocate buffer
mov -8(%rbp), %rcx // size
add $1000, %rcx // Add some extra space
mov $8, %rdx // alignment
lea -16(%rbp), %r8 // buffer pointer
call boot_services_allocate_pool
// Get actual map
mov -8(%rbp), %rcx
mov -16(%rbp), %rdx
lea -24(%rbp), %r8
lea -32(%rbp), %r9
push -40(%rbp)
call boot_services_get_memory_map
// Save map key
mov -24(%rbp), %rax
mov %rax, memory_map_key
leave
ret
// Function to exit boot services
exit_boot_services:
push %rbp
mov %rsp, %rbp
// Parameters already in rcx (image_handle) and rdx (map_key)
call boot_services_exit
leave
ret
// Function to set up page tables
setup_page_tables:
push %rbp
mov %rsp, %rbp
// Clear tables
mov $pml4_table, %rdi
mov $12288, %ecx // 3 pages (PML4, PDPT, PD)
xor %eax, %eax
rep stosb
// Set up identity mapping for first 2MB
// PML4[0] -> PDPT
mov $pdpt_table, %eax
or $3, %eax // Present + Write
mov %eax, pml4_table
// PDPT[0] -> PD
mov $pd_table, %eax
or $3, %eax
mov %eax, pdpt_table
// PD[0] -> 2MB page
mov $0x83, %eax // Present + Write + Huge
mov %eax, pd_table
// Map kernel to higher half
// PML4[511] -> PDPT
mov $pdpt_table, %eax
or $3, %eax
mov %eax, pml4_table + 4088
// Load CR3
mov $pml4_table, %rax
mov %rax, %cr3
leave
ret