Bootloader: Find root partition from GPT header

This commit is contained in:
Bananymous 2023-11-13 18:55:48 +02:00
parent b4775fbe75
commit aa4f3046ff
1 changed files with 283 additions and 59 deletions

View File

@ -186,11 +186,13 @@ stage1_main:
# setup stack # setup stack
movw %ax, %ss movw %ax, %ss
movw $0x7C00, %sp movl $0x7C00, %esp
# save boot disk number # save boot disk number
movb %dl, (boot_disk_number) movb %dl, (boot_disk_number)
# FIXME: validate boot disk (needs size optizations)
# confirm that int 13h extensions are available # confirm that int 13h extensions are available
clc clc
movb $0x41, %ah movb $0x41, %ah
@ -427,11 +429,35 @@ isprint:
ret ret
# fills memory map data structure # check if drive exists
# doesn't return on error # dl: drive number
get_memory_map: # return:
# al: 1 if disk is usable, 0 otherwise
drive_exists:
pusha pusha
movb $0x48, %ah
movw $disk_drive_parameters, %si
movw $0x1A, (disk_drive_parameters) # set buffer size
clc
int $0x13
jc .drive_exists_nope
popa
movb $1, %al
ret
.drive_exists_nope:
popa
movb $0, %al
ret
# fills memory map data structure
# doesn't return on error
# NO REGISTERS SAVED
get_memory_map:
movl $0, (memory_map_entry_count) movl $0, (memory_map_entry_count)
movl $0x0000E820, %eax movl $0x0000E820, %eax
@ -472,7 +498,6 @@ get_memory_map:
jnc .get_memory_map_rest jnc .get_memory_map_rest
.get_memory_map_done: .get_memory_map_done:
popa
ret ret
.get_memory_map_error: .get_memory_map_error:
@ -481,9 +506,8 @@ get_memory_map:
# fills command line buffer # fills command line buffer
# NO REGISTERS SAVED
get_command_line: get_command_line:
pusha
movw $command_line_enter_msg, %si movw $command_line_enter_msg, %si
call puts call puts
@ -532,36 +556,12 @@ get_command_line:
call print_newline call print_newline
popa
ret ret
stage2_main: # print memory map from memory_map_entries
# clear screen and enter 80x25 text mode # NO REGISTERS SAVED
movb $0x03, %al print_memory_map:
movb $0x00, %ah
int $0x10
# print hello message
movw $hello_msg, %si
call puts
call print_newline
call get_memory_map
call get_command_line
call print_newline
movw $start_kernel_load_msg, %si
call puts
call print_newline
movw $command_line_msg, %si
call puts
movw $command_line_buffer, %si
call puts
call print_newline
movw $memory_map_msg, %si movw $memory_map_msg, %si
call puts call puts
call print_newline call print_newline
@ -619,10 +619,212 @@ stage2_main:
decl %edx decl %edx
jnz .loop_memory_map jnz .loop_memory_map
ret
# find root disk and populate root_disk_drive_number field
# NO REGISTERS SAVED
find_root_disk:
movb $0x80, %dl
.find_root_disk_loop:
call drive_exists
testb %al, %al
jz .find_root_disk_not_found
# read GPT header
xorw %bx, %bx
movl $1, %eax
movw $1, %cx
movw $gpt_header, %di
call read_from_disk
# confirm header (starts with 'EFI PART')
cmpl $0x20494645, (gpt_header + 0)
jne .find_root_disk_next_disk
cmpl $0x54524150, (gpt_header + 4)
jne .find_root_disk_next_disk
# compare disk GUID
movw $root_disk_guid, %si
movw $(gpt_header + 56), %di
movw $16, %cx
call memcmp
testb %al, %al
jz .find_root_disk_next_disk
movb %dl, (root_disk_drive_number)
ret
.find_root_disk_next_disk:
incb %dl
jmp .find_root_disk_loop
.find_root_disk_not_found:
movw $no_root_disk_msg, %si
jmp print_and_halt
# finds root partition from root disk
# fills root_partition_entry data structure
# NOTE: assumes GPT header is in `gpt_header`
# NO REGISTERS SAVED
find_root_partition:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
# esp + 0: 8 byte entry array lba
movl (gpt_header + 72), %eax
movl %eax, 0(%esp)
movl (gpt_header + 76), %eax
movl %eax, 4(%esp)
# FIXME: check that bits 48-63 are zero
# esp + 8: 4 byte entries per sector
xorl %edx, %edx
movl $SECTOR_SIZE, %eax
divl (gpt_header + 84)
movl %eax, 8(%esp)
# esp + 12: 4 byte entries remaining
movl (gpt_header + 80), %eax
testl %eax, %eax
jz .find_root_partition_not_found
movl %eax, 12(%esp)
.find_root_partition_read_entry_section:
movl 0(%esp), %eax
movl 4(%esp), %ebx
movw $1, %cx
movb (root_disk_drive_number), %dl
movw $sector_buffer, %di
call read_from_disk
# ecx: min(entries per section, entries remaining)
movl 8(%esp), %ecx
cmpl 12(%esp), %ecx
jae .find_root_partition_got_entry_count
movl 12(%esp), %ecx
.find_root_partition_got_entry_count:
# update entries remaining
subl %ecx, 12(%esp)
# si: entry pointer
movw $sector_buffer, %si
.find_root_partition_loop_entries:
# temporarily save cx in dx
movw %cx, %dx
# check that entry is used
movw $16, %cx
movw $zero_guid, %di
call memcmp
test %al, %al
jnz .find_root_partition_next_entry
# compare entry guid to root guid
movw $16, %cx
addw $16, %si
movw $root_partition_guid, %di
call memcmp
subw $16, %si
testb %al, %al
jnz .find_root_partition_found
.find_root_partition_next_entry:
# restore cx
movw %dx, %cx
# entry pointer += entry size
addw (gpt_header + 84), %si
loop .find_root_partition_loop_entries
# entry not found in this sector
# increment 8 byte entry array lba
incl 0(%esp)
jno .find_root_partition_no_overflow
incl 4(%esp)
.find_root_partition_no_overflow:
# loop to read next section if entries remaining
cmpl $0, 12(%esp)
jnz .find_root_partition_read_entry_section
.find_root_partition_not_found:
movw $no_root_partition_msg, %si
jmp print_and_halt
.find_root_partition_found:
# copy entry to buffer
movw $root_partition_entry, %di
movw $128, %cx
rep movsb
leavel
ret
stage2_main:
# clear screen and enter 80x25 text mode
movb $0x03, %al
movb $0x00, %ah
int $0x10
# print hello message
movw $hello_msg, %si
call puts; call print_newline
call get_memory_map
call get_command_line
call print_newline
movw $start_kernel_load_msg, %si
call puts; call print_newline
call print_memory_map
call find_root_disk
movw $root_disk_found_msg, %si
call puts; call print_newline
call find_root_partition
movw $root_partition_found_msg, %si
call puts; call print_newline
movw $16, %bx
movw $2, %cx
movw (root_partition_entry + 38), %ax; call printnum
movw (root_partition_entry + 36), %ax; call printnum
movw (root_partition_entry + 34), %ax; call printnum
movw (root_partition_entry + 32), %ax; call printnum
movb $'-', %al; call putc
movb $'>', %al; call putc
movw (root_partition_entry + 46), %ax; call printnum
movw (root_partition_entry + 44), %ax; call printnum
movw (root_partition_entry + 42), %ax; call printnum
movw (root_partition_entry + 40), %ax; call printnum
jmp halt jmp halt
# These will be patched during bootloader installation
root_disk_guid:
.ascii "root disk guid "
root_partition_guid:
.ascii "root part guid "
zero_guid:
.quad 0
.quad 0
hello_msg: hello_msg:
.asciz "This is banan-os bootloader" .asciz "This is banan-os bootloader"
@ -639,6 +841,16 @@ memory_map_error_msg:
start_kernel_load_msg: start_kernel_load_msg:
.asciz "Starting to load kernel" .asciz "Starting to load kernel"
root_disk_found_msg:
.asciz "Root disk found!"
no_root_disk_msg:
.asciz "Root disk not found"
root_partition_found_msg:
.asciz "Root partition found!"
no_root_partition_msg:
.asciz "Root partition not found"
stage2_end: stage2_end:
@ -650,12 +862,24 @@ gpt_header:
gpt_entry_data: gpt_entry_data:
.skip SECTOR_SIZE .skip SECTOR_SIZE
sector_buffer:
.skip SECTOR_SIZE
disk_drive_parameters:
.skip 0x1A
disk_address_packet: disk_address_packet:
.skip 16 .skip 16
printnum_buffer: printnum_buffer:
.skip 10 .skip 10
root_disk_drive_number:
.skip 1
root_partition_entry:
.skip 128
memory_map_entry_count: memory_map_entry_count:
.skip 4 .skip 4
# 100 entries should be enough... # 100 entries should be enough...