banan-os/bootloader/arch/x86_64/boot.S

288 lines
4.5 KiB
ArmAsm

# FIXME: don't assume 512 byte sectors
.set SECTOR_SIZE, 512
.set GPT_HEADER_ADDR, free_memory_start
.set GPT_ENTRY_ADDR, free_memory_start + SECTOR_SIZE
.code16
#########################################
#
# STAGE 1 BOOTLOADER
#
# its sole purpose is to load stage2 from
# bios boot partition
#
#########################################
.section .stage1
stage1_start:
jmp main
# al: character to print
putc:
mov $0x0E, %ah
int $0x10
ret
# ds:si: null terminated string to print
puts:
push %si
push %ax
1:
lodsb
test %al, %al
jz 2f
call putc
jmp 1b
2:
mov $'\r', %al
call putc
mov $'\n', %al
call putc
pop %ax
pop %si
ret
# si: ptr1
# di: ptr2
# cx: count
# return: 1 if equal, 0 otherwise
memcmp:
pushw %si
pushw %di
cld
repe cmpsb
setzb %al
popw %di
popw %si
ret
# read sectors from disk
#
# bx:eax: lba start
# cx: lba count (has to less than 0x80)
# dl: drive number
# ds:di: physical address
#
# returns only on success
read_from_disk:
push %ax
push %si
# prepare disk read packet
mov $disk_address_packet, %si
movb $0x10, 0x00(%si) # packet size
movb $0x00, 0x01(%si) # always 0
movw %cx, 0x02(%si) # lba count
movw %di, 0x04(%si) # offset
movw %ds, 0x06(%si) # segment
movl %eax, 0x08(%si) # 32 bit lower lba
movw %bx, 0x0C(%si) # 16 bit upper lba
movw $0, 0x0E(%si) # zero
# issue read command
clc
mov $0x42, %ah
int $0x13
jc .read_failed
pop %si
pop %ax
ret
main:
# setup segments
movw $0, %ax
movw %ax, %ds
movw %ax, %es
# setup stack
movw %ax, %ss
movw $0x7C00, %sp
# save boot disk number
movb %dl, (boot_disk_number)
# confirm that int 13h extensions are available
clc
movb $0x41, %ah
movw $0x55AA, %bx
movb (boot_disk_number), %dl
int $0x13
jc .no_int13h_ext
# read gpt header
movl $1, %eax
movw $0, %bx
movw $1, %cx
movb (boot_disk_number), %dl
movw $GPT_HEADER_ADDR, %di
call read_from_disk
# confirm header (starts with 'EFI PART')
cmpl $0x20494645, (GPT_HEADER_ADDR + 0)
jne .not_gpt_partition
cmpl $0x54524150, (GPT_HEADER_ADDR + 4)
jne .not_gpt_partition
# eax := entry_count
movl (GPT_HEADER_ADDR + 80), %eax
test %eax, %eax
jz .no_bios_boot_partition
# edx:eax := eax * entry_size
mull (GPT_HEADER_ADDR + 84)
test %edx, %edx
jnz .too_gpt_big_entries
# sector count := (arr_size + SECTOR_SIZE - 1) / SECTOR_SIZE
pushl %eax
addl $(SECTOR_SIZE - 1), %eax
movl $SECTOR_SIZE, %ecx
divl %ecx
movl %eax, %ecx
popl %eax
# start lba
movl (GPT_HEADER_ADDR + 72), %eax
movw (GPT_HEADER_ADDR + 76), %bx
movb (boot_disk_number), %dl
movw $GPT_ENTRY_ADDR, %di
call read_from_disk
# NOTE: 'only' 0xFFFF partitions supported
movw (GPT_HEADER_ADDR + 80), %cx
.loop_entries:
push %cx
movw $16, %cx
movw $bios_boot_guid, %si
call memcmp
pop %cx
testb %al, %al
jnz .bios_boot_found
# add entry size to entry pointer
addw (GPT_HEADER_ADDR + 84), %di
loop .loop_entries
jmp .no_bios_boot_partition
.bios_boot_found:
# first lba
movl 32(%di), %eax
movw $0, %bx
# count := last lba - first lba + 1
movl 40(%di), %ecx
subl %eax, %ecx
addl $1, %ecx
# calculate stage2 sector count
movw $((stage2_end - stage2_start + SECTOR_SIZE - 1) / SECTOR_SIZE), %cx
movb (boot_disk_number), %dl
movw $stage2_start, %di
call read_from_disk
jmp stage2_start
print_and_halt:
call puts
halt:
hlt
jmp halt
.no_int13h_ext:
mov $no_int13_ext_msg, %si
jmp print_and_halt
.read_failed:
mov $read_failed_msg, %si
jmp print_and_halt
.not_gpt_partition:
mov $not_gpt_partition_msg, %si
jmp print_and_halt
.no_bios_boot_partition:
mov $no_bios_boot_partition_msg, %si
jmp print_and_halt
.too_gpt_big_entries:
mov $too_gpt_big_entries_msg, %si
jmp print_and_halt
# 21686148-6449-6E6F-744E-656564454649
bios_boot_guid:
.long 0x21686148 # little endian
.word 0x6449 # little endian
.word 0x6E6F # little endian
.word 0x4E74 # big endian
.quad 0x494645646565 # big endian
no_int13_ext_msg:
.asciz "no INT 13h ext"
read_failed_msg:
.asciz "read error"
not_gpt_partition_msg:
.asciz "not gpt"
no_bios_boot_partition_msg:
.asciz "no bios boot partition"
too_gpt_big_entries_msg:
.asciz "too big GPT array"
boot_disk_number:
.skip 1
disk_address_packet:
.skip 16
#########################################
#
# STAGE 2 BOOTLOADER
#
#########################################
.section .stage2
stage2_start:
# clear screen and enter 80x25 text mode
movb $0x03, %al
movb $0x00, %ah
int $0x10
# print hello message
movw $hello_msg, %si
call puts
1:
jmp 1b
hello_msg:
.asciz "This is banan-os bootloader"
stage2_end: