Initial commit
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
bits 16
|
||||
org 0x8000
|
||||
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
mov sp, 0x7000
|
||||
|
||||
FIRST_PARTITION_SECTOR equ 2048 ; TODO Read MBR.
|
||||
STAGE_BUFFER_SEGMENT equ 0x0900
|
||||
STAGE_BUFFER_OFFSET equ 0x0000
|
||||
KERNEL_BUFFER_SEGMENT equ 0x2000
|
||||
|
||||
jmp prepare_kernel
|
||||
|
||||
dap:
|
||||
.dap_size: db 16
|
||||
.reserved: db 0
|
||||
.src_sectors: dw 1
|
||||
.dst_offset: dw 0
|
||||
.dst_segment: dw 0
|
||||
.src_lba: dq 0
|
||||
dap_end:
|
||||
|
||||
bpb:
|
||||
.bytes_per_sector: dw 0
|
||||
.sectors_per_cluster: db 0
|
||||
.reserved_sectors: dw 0
|
||||
.fats_count: db 0
|
||||
.root_entry_count: dw 0
|
||||
.total_sectors_16: dw 0
|
||||
.media_type: db 0
|
||||
.sectors_per_fat: dw 0
|
||||
bpb_end:
|
||||
|
||||
fat_start: dw 0
|
||||
root_start: dw 0
|
||||
root_size: dw 0
|
||||
data_start: dw 0
|
||||
|
||||
kernel_filename: db 'KERNEL BIN'
|
||||
kernel_cluster: dw 0
|
||||
kernel_buffer_offset: dw 0
|
||||
|
||||
read_sectors:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
mov [dap.src_lba], eax
|
||||
mov [dap.src_sectors], cx
|
||||
mov [dap.dst_segment], es
|
||||
mov [dap.dst_offset], di
|
||||
mov ah, 0x42
|
||||
mov dl, 0x80
|
||||
mov si, dap
|
||||
int 0x13
|
||||
jc disk_error
|
||||
ret
|
||||
|
||||
disk_error:
|
||||
mov ah, 0x0E
|
||||
mov al, 'E'
|
||||
int 0x10
|
||||
jmp $
|
||||
|
||||
prepare_kernel:
|
||||
load_bpb:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
mov eax, FIRST_PARTITION_SECTOR
|
||||
mov cx, 1
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov es, bx
|
||||
mov di, STAGE_BUFFER_OFFSET
|
||||
call read_sectors
|
||||
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov ds, bx
|
||||
|
||||
mov si, STAGE_BUFFER_OFFSET + 11
|
||||
xor bx, bx
|
||||
mov es, bx
|
||||
mov di, bpb
|
||||
mov cx, bpb_end - bpb
|
||||
rep movsb
|
||||
|
||||
find_data_start:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
mov ax, FIRST_PARTITION_SECTOR
|
||||
add ax, [bpb.reserved_sectors]
|
||||
mov [fat_start], ax
|
||||
|
||||
xor ax, ax
|
||||
mov al, [bpb.fats_count]
|
||||
mul word [bpb.sectors_per_fat]
|
||||
add ax, [fat_start]
|
||||
mov [root_start], ax ; dx should be zero for sane FAT16 values
|
||||
|
||||
mov ax, [bpb.root_entry_count]
|
||||
shl ax, 5 ; * 32
|
||||
shr ax, 9 ; / 512 ; there should be at least 512 entries, so safe
|
||||
mov [root_size], ax
|
||||
|
||||
mov ax, [root_start]
|
||||
add ax, [root_size]
|
||||
mov [data_start], ax
|
||||
|
||||
find_kernel:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
xor eax, eax
|
||||
mov ax, [root_start]
|
||||
mov cx, [root_size]
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov es, bx
|
||||
mov di, STAGE_BUFFER_OFFSET
|
||||
call read_sectors
|
||||
|
||||
mov cx, [bpb.root_entry_count]
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov ds, bx
|
||||
mov si, STAGE_BUFFER_OFFSET
|
||||
|
||||
.check_entry:
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov ds, bx
|
||||
|
||||
cmp byte [si], 0x00
|
||||
je .no_more_entries
|
||||
cmp byte [si], 0xE5
|
||||
je .continue
|
||||
|
||||
push si
|
||||
push cx
|
||||
xor bx, bx
|
||||
mov es, bx
|
||||
mov di, kernel_filename
|
||||
mov cx, 11
|
||||
rep cmpsb
|
||||
pop cx
|
||||
pop si
|
||||
je .found
|
||||
|
||||
.continue:
|
||||
add si, 32
|
||||
loop .check_entry
|
||||
|
||||
.no_more_entries:
|
||||
mov ah, 0x0E
|
||||
mov al, 'K'
|
||||
int 0x10
|
||||
jmp $
|
||||
|
||||
.found:
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov ds, bx
|
||||
|
||||
mov ax, [si + 26]
|
||||
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
mov [kernel_cluster], ax
|
||||
|
||||
load_fat:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
xor eax, eax
|
||||
mov ax, [fat_start]
|
||||
mov cx, [bpb.sectors_per_fat]
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov es, bx
|
||||
mov di, STAGE_BUFFER_OFFSET
|
||||
call read_sectors
|
||||
|
||||
load_kernel_cluster:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
xor eax, eax
|
||||
mov ax, [kernel_cluster]
|
||||
sub ax, 2
|
||||
xor bx, bx
|
||||
mov bl, [bpb.sectors_per_cluster]
|
||||
mul bx
|
||||
add ax, [data_start]
|
||||
xor cx, cx
|
||||
mov cl, [bpb.sectors_per_cluster]
|
||||
mov bx, KERNEL_BUFFER_SEGMENT
|
||||
mov es, bx
|
||||
mov di, [kernel_buffer_offset]
|
||||
call read_sectors
|
||||
|
||||
mov ax, [bpb.sectors_per_cluster]
|
||||
shl ax, 9 ; * 512
|
||||
add ax, [kernel_buffer_offset]
|
||||
mov [kernel_buffer_offset], ax
|
||||
|
||||
find_next_kernel_cluster:
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
|
||||
mov si, [kernel_cluster]
|
||||
shl si, 1 ; * 2
|
||||
add si, STAGE_BUFFER_OFFSET
|
||||
mov bx, STAGE_BUFFER_SEGMENT
|
||||
mov ds, bx
|
||||
mov ax, [si]
|
||||
xor bx, bx
|
||||
mov ds, bx
|
||||
mov [kernel_cluster], ax
|
||||
cmp ax, 0xFFF8
|
||||
jb load_kernel_cluster
|
||||
|
||||
; ------------------------------------------------------------------------------
|
||||
|
||||
jmp load_gdt
|
||||
|
||||
gdt_start:
|
||||
gdt_0: dq 0x0000000000000000
|
||||
gdt_1:
|
||||
.limit_low: dw 0xFFFF
|
||||
.base_low: dw 0x0000
|
||||
.base_middle: db 0x00
|
||||
.access: db 10011010b ; present, ring 0, code, executable, readable
|
||||
.flags: db 11001111b ; 32-bit, 4KB granularity
|
||||
.base_high: db 0x00
|
||||
gdt_1_end:
|
||||
gdt_2:
|
||||
.limit_low: dw 0xFFFF
|
||||
.base_low: dw 0x0000
|
||||
.base_middle: db 0x00
|
||||
.access: db 10011010b ; present, ring 0, code, executable, readable
|
||||
.flags: db 10101111b ; long mode (L bit)
|
||||
.base_high: db 0x00
|
||||
gdt_2_end:
|
||||
gdt_3:
|
||||
.limit_low: dw 0xFFFF
|
||||
.base_low: dw 0x0000
|
||||
.base_middle: db 0x00
|
||||
.access: db 10010010b ; present, ring 0, data, writable
|
||||
.flags: db 00000000b
|
||||
.base_high: db 0x00
|
||||
gdt_3_end:
|
||||
gdt_end:
|
||||
|
||||
gdt_descriptor:
|
||||
.size: dw gdt_end - gdt_start - 1
|
||||
.offset: dd gdt_start
|
||||
gdt_descriptor_end:
|
||||
|
||||
load_gdt:
|
||||
cli
|
||||
|
||||
lgdt [gdt_descriptor]
|
||||
|
||||
mov eax, cr0
|
||||
or eax, 0x00000001
|
||||
mov cr0, eax
|
||||
|
||||
jmp 0x0008:protected_mode
|
||||
|
||||
; ------------------------------------------------------------------------------
|
||||
|
||||
bits 32
|
||||
protected_mode:
|
||||
mov ax, 0x0018 ; data segment is now third entry = 0x18
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
mov esp, 0x00090000
|
||||
|
||||
; zero page table memory at 0x00010000 (3 pages = 768 dwords)
|
||||
mov edi, 0x00010000
|
||||
mov ecx, 768
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
|
||||
; PML4[0] -> PDPT at 0x00011000
|
||||
mov dword [0x00010000], 0x00011003
|
||||
; PDPT[0] -> PD at 0x00012000
|
||||
mov dword [0x00011000], 0x00012003
|
||||
; PD: fill 64 entries, each mapping 2MB
|
||||
mov edi, 0x00012000
|
||||
mov eax, 0x00000083 ; present, writable, huge page, base 0
|
||||
mov ecx, 64
|
||||
|
||||
.fill_pd:
|
||||
mov dword [edi], eax
|
||||
add edi, 8
|
||||
add eax, 0x00200000 ; next 2MB
|
||||
loop .fill_pd
|
||||
|
||||
; load PML4 into CR3
|
||||
mov eax, 0x00010000
|
||||
mov cr3, eax
|
||||
|
||||
; enable PAE
|
||||
mov eax, cr4
|
||||
or eax, 0x00000020
|
||||
mov cr4, eax
|
||||
|
||||
; enable long mode in EFER MSR
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 0x00000100
|
||||
wrmsr
|
||||
|
||||
; enable paging (and keep protection enabled)
|
||||
mov eax, cr0
|
||||
or eax, 0x80000000
|
||||
mov cr0, eax
|
||||
|
||||
jmp 0x0010:long_mode ; 0x10 = second entry = 64-bit code segment
|
||||
|
||||
; ------------------------------------------------------------------------------
|
||||
|
||||
bits 64
|
||||
long_mode:
|
||||
mov ax, 0x0018 ; data segment
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
mov rsp, 0x0000000000090000
|
||||
|
||||
xor rax, rax
|
||||
xor rbx, rbx
|
||||
xor rcx, rcx
|
||||
xor rdx, rdx
|
||||
|
||||
jmp 0x00020000
|
||||
Reference in New Issue
Block a user