171 lines
3.8 KiB
ArmAsm
Raw Normal View History

2022-11-22 21:43:13 +03:00
#include "cpu/gdt.h"
2022-09-21 16:53:45 +03:00
.code16
.global _start
2022-09-21 17:37:27 +03:00
_start:
2022-09-21 18:25:06 +03:00
mov %dl, boot_drive
2022-09-21 16:53:45 +03:00
mov $banner, %si
call print_string
2022-11-20 22:17:13 +03:00
call get_drive_geometry
2022-09-21 18:25:06 +03:00
call load_kernel
call switch_to_32bit
2022-11-20 22:17:13 +03:00
hlt
2022-09-21 16:53:45 +03:00
jmp . // loop forever
2022-11-20 22:17:13 +03:00
get_drive_geometry:
mov $8, %ah
mov boot_drive, %dl
int $0x13
2022-11-20 23:40:45 +03:00
inc %dh // number of heads
mov %dh, disk_heads
and 0x3f, %cl
mov %cl, sectors_per_track
ret
2022-11-20 22:17:13 +03:00
2022-09-21 16:53:45 +03:00
2022-11-17 23:16:57 +03:00
.equ ELF32_ENTRY_OFFSET, 0x18
.equ ELF32_PHDR_OFFSET, 0x1c
2022-11-20 19:48:55 +03:00
.equ ELF32_PHENTSIZE_OFFSET, ELF32_PHDR_OFFSET + 14
.equ ELF32_PHNUM_OFFSET, ELF32_PHENTSIZE_OFFSET + 2
.equ ELF32_PHDR_P_OFFSET, 4
2022-11-17 23:16:57 +03:00
.equ ELF32_PHDR_FILESZ_OFFSET, 4*4
2022-09-21 18:25:06 +03:00
.equ KERNEL_OFFSET, 0x1000
2022-11-17 23:16:57 +03:00
2022-11-18 22:58:49 +03:00
.equ MBR_SECTORS, 2
2022-11-17 23:16:57 +03:00
.equ SECTOR_BASE, 1
.equ ELFHDR_SECTORS, 8
.equ SECTOR_SIZE, 512
.equ SECTOR_SHIFT, 9
2022-09-21 18:25:06 +03:00
load_kernel:
2022-11-17 23:16:57 +03:00
mov $1, %al // sectors to read
mov $SECTOR_BASE + MBR_SECTORS, %cl // start after MBR
call bios_disk_read
mov KERNEL_OFFSET + ELF32_ENTRY_OFFSET, %si
mov %si, entry // store entry point
2022-11-20 23:40:45 +03:00
#if 0
2022-11-20 19:48:55 +03:00
mov KERNEL_OFFSET + ELF32_PHNUM_OFFSET, %ax
dec %ax // no offset to the first entry
mulb KERNEL_OFFSET + ELF32_PHENTSIZE_OFFSET
mov %ax, %di
add KERNEL_OFFSET + ELF32_PHDR_OFFSET, %di
// now di holds offset to the last phentry
2022-11-20 23:40:45 +03:00
#else
mov KERNEL_OFFSET + ELF32_PHDR_OFFSET, %di
// now di holds offset to the first phentry
#endif
2022-11-17 23:16:57 +03:00
mov KERNEL_OFFSET + ELF32_PHDR_FILESZ_OFFSET(%di), %ax
2022-11-20 19:48:55 +03:00
add KERNEL_OFFSET + ELF32_PHDR_P_OFFSET(%di), %ax
2022-11-17 23:16:57 +03:00
sub $0x1000, %ax // we won't load the header
add $SECTOR_SIZE - 1, %ax
shr $SECTOR_SHIFT, %ax // round up to sector count
mov $SECTOR_BASE + MBR_SECTORS + ELFHDR_SECTORS, %cl //start after ELF header
call bios_disk_read
ret
bios_disk_read:
// expects %al to specify number of sectors, %cl the initial sector
2022-11-20 22:17:13 +03:00
xor %ah, %ah
mov %ax, %si
2022-09-21 18:25:06 +03:00
mov $0, %ch // cylinder 0
mov $0, %dh // head 0
mov $KERNEL_OFFSET, %bx // bx -> destination
mov boot_drive, %dl // dl -> disk
2022-11-20 22:17:13 +03:00
mov $1, %al
1:
mov $2, %ah // read mode
2022-09-21 18:25:06 +03:00
int $0x13
2022-11-22 21:24:49 +03:00
jc fail
2022-11-20 22:17:13 +03:00
add $SECTOR_SIZE, %bx
inc %cl
dec %si
jnz 1b
2022-09-21 18:25:06 +03:00
ret
2022-11-20 22:17:13 +03:00
fail:
mov $read_error, %si
call print_string
hlt
jmp .
2022-09-21 18:25:06 +03:00
switch_to_32bit:
2022-11-19 22:02:37 +03:00
mov $2, %al
out %al, $0x92 // enable A20
2022-09-21 18:25:06 +03:00
cli // 1. disable interrupts
2022-11-19 22:02:37 +03:00
lgdt gdt_descriptor // 2. load GDT descriptor
2022-09-21 18:25:06 +03:00
mov %cr0, %eax
or $1, %eax // 3. enable protected mode
mov %eax, %cr0
2022-11-22 21:43:13 +03:00
ljmp $SEG_KCODE << 3, $init_32bit // 4. far jump
2022-09-21 18:25:06 +03:00
.code32
init_32bit:
2022-11-22 21:43:13 +03:00
mov $SEG_KDATA << 3, %ax // 5. update segment registers
2022-09-21 18:25:06 +03:00
mov %ax, %ds
mov %ax, %ss
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov $0x90000, %ebp // 6. setup stack
mov %ebp, %esp
2022-11-17 23:16:57 +03:00
movzwl entry, %esi
call *%esi // 7. jump to the kernel
2022-09-21 18:25:06 +03:00
jmp . // 8. loop forever
.code16
2022-09-21 16:53:45 +03:00
print_string:
mov $0x0e, %ah // "teletype output"
repeat:
lodsb // equivalent to mov (%si), %al; inc %si
test %al, %al
je done
int $0x10 // bios interrupt
jmp repeat
done:
ret
. = _start + 256 # pad to 256 bytes
2022-09-21 18:25:06 +03:00
boot_drive:
.byte 0
2022-09-21 16:53:45 +03:00
banner:
.asciz "YABLOKO bootloader started\r\n"
2022-11-20 22:17:13 +03:00
read_error:
.asciz "Read error\r\n"
2022-09-21 16:53:45 +03:00
2022-11-17 23:16:57 +03:00
.balign 2
entry:
.word 0
2022-11-20 23:40:45 +03:00
disk_heads:
.byte 0
sectors_per_track:
.byte 0
2022-11-17 23:16:57 +03:00
.balign 4
2022-09-21 18:25:06 +03:00
gdt_start:
.quad 0x0 // null descriptor
2022-11-22 21:43:13 +03:00
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
2022-09-21 18:25:06 +03:00
gdt_end:
// GDT descriptor
gdt_descriptor:
.word gdt_end - gdt_start - 1 // size (16 bit)
.int gdt_start // address (32 bit)
2022-09-21 16:53:45 +03:00
. = _start + 510 # pad to 510 bytes
.byte 0x55, 0xaa # boot sector magic value