toaruos/boot/boot.S
2021-09-07 11:47:08 +09:00

298 lines
5.0 KiB
ArmAsm

.code16
main:
ljmp $0x0,$entry
entry:
/* Set up initial segments */
xor %ax, %ax
mov %ax, %ds
mov %ax, %ss
/* Don't lose dl */
mov %dl, boot_disk
/* Initialize stack to just below us */
mov $0x7c00, %ax
mov %ax, %sp
/* Prepare to switch to unreal mode */
cli
push %ds
push %es
/* Enable A20 */
in $0x92, %al
or $2, %al
out %al, $0x92
/* Switch to unreal mode */
lgdtw gdtr
mov %cr0, %eax
or $1, %al
mov %eax, %cr0
jmp pmode
pmode:
mov $0x10, %bx
mov %bx, %ds
mov %bx, %es
and $0xfe, %al
mov %eax, %cr0
jmp unrealmode
unrealmode:
pop %es
pop %ds
/* Clear the screen */
mov $0, %al
movl $3840, %ecx
movl $0xb8000, %edi
addr32 rep stosb
/* Check if we can actually go to long mode on this */
mov $0x80000001, %eax
cpuid
and $0x20000000, %edx
jnz can_long
movl $str_Need_long, %esi
movl $str_Need_long_end - str_Need_long, %ecx
movl $0xb8000, %edi
addr32 rep movsb
jmp _oh_no
can_long:
/* Print "Loading..." */
movl $str_Loading, %esi
movl $str_Loading_end - str_Loading, %ecx
movl $0xb8000, %edi
addr32 rep movsb
/* Use BIOS disk reads to locate the kernel and ramdisk
* and load them around the 2MB mark (by loading them
* in smaller chunks and copying those up thanks to
* our unreal mode %ds) */
/* Ask for drive params */
mov $0x48, %ah
mov boot_disk, %dl
mov $drive_params, %si
int $0x13
/* Are we a CD? Do we need to load more of ourselves? */
mov drive_params_bps, %ax
cmp $0x800, %ax
je boot_from_cd
movl $str_Bad, %esi
movl $str_Bad_end - str_Bad, %ecx
movl $0xb8000, %edi
addr32 rep movsb
_oh_no:
jmp _oh_no
.extern _bss_start
/* To load from the CD, we have 2048 byte sectors */
boot_from_cd:
movl $0x4000000, %ebx
movl $0x0, dap_lba_low /* Sector 10h generally has our primary boot descriptor */
movw $_bss_start, dap_buffer /* Load into root_data */
/* Load one sector */
load_one:
mov $0x42, %ah /* Extended read */
mov boot_disk, %dl /* Using our boot disk */
mov $dap, %si /* From the DAP below */
int $0x13
cmp $0, %ah
jnz done
/* Move the sector up */
movl $_bss_start, %esi
movl %ebx, %edi
xor %ecx, %ecx
movw drive_params_bps, %cx
addr32 rep movsb
/* Increment */
movl dap_lba_low, %ecx
add $1, %ecx
movl %ecx, dap_lba_low
xor %ecx, %ecx
movw drive_params_bps, %cx
add %ecx, %ebx
/* Update spinner */
movl ind_Spinny, %ecx
inc %ecx
and $0x3FF, %ecx
movl %ecx, ind_Spinny
shr $8, %ecx
movb str_Spinny(%ecx), %ah
mov $str_Loading_end - str_Loading - 2 + 0xb8000, %ecx
movb %ah, (%ecx)
jmp load_one
done:
/* The entire CD is now in memory at 64MiB, hopefully. */
/* Collect information on lower memory. */
mov $0x500, %ax
mov %ax, %es
clc
int $0x12
mov %ax, lower_mem
/* Collect information on upper memory. */
mov $0x0, %di
call do_e820
jc hang
/* Actually switch to protected mode. */
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
cli
.global bios_main
ljmp $0x08,$bios_main
hang:
jmp hang
do_e820:
xor %ebx, %ebx
xor %bp, %bp
mov $0x534D4150, %edx
mov $0xe820, %eax
movl $0x1,%es:20(%di)
mov $24, %ecx
int $0x15
jb do_e820.failed
mov $0x534D4150, %edx
cmp %edx, %eax
jne do_e820.failed
test %ebx, %ebx
je do_e820.failed
jmp do_e820.jmpin
do_e820.e820lp:
mov $0xe820, %eax
movl $0x1,%es:20(%di)
mov $24, %ecx
int $0x15
jb do_e820.e820f
mov $0x534D4150, %edx
do_e820.jmpin:
jcxz do_e820.skipent
cmp $20, %cl
jbe do_e820.notext
testb $0x1, %es:20(%di)
je do_e820.skipent
do_e820.notext:
mov %es:8(%di), %ecx
or %es:12(%di), %ecx
jz do_e820.skipent
inc %bp
add $24, %di
do_e820.skipent:
test %ebx, %ebx
jne do_e820.e820lp
do_e820.e820f:
mov %bp, mmap_ent
clc
ret
do_e820.failed:
stc
ret
.align 8
gdtr:
.word gdt_end - gdt_base - 1
.long gdt_base
gdt_base:
.quad 0
.word 0xFFFF
.word 0
.byte 0
.byte 0x9a
.byte 0xcf
.byte 0
.word 0xffff
.word 0
.byte 0
.byte 0x92
.byte 0xcf
.byte 0
gdt_end:
.global boot_disk
boot_disk:
.byte 0
.global mmap_ent
mmap_ent:
.byte 0
.byte 0
.global lower_mem
lower_mem:
.byte 0
.byte 0
.align 4
.global dap
dap:
.byte 16
.byte 0 /* always 0 */
.global dap_sectors
dap_sectors:
.word 1
.global dap_buffer
dap_buffer:
.long 0x0
dap_lba_low:
.long 0
dap_lba_high:
.long 0
.align 4
drive_params:
.word 0x1A
.word 0 /* flags */
.long 0 /* cylinders */
.long 0 /* heads */
.long 0 /* sectors */
.quad 0 /* total sectors */
.global drive_params_bps
drive_params_bps:
.word 0 /* bytes per sector */
str_Bad:
.byte 'B',7,'a',7,'d',7,' ',7,'d',7,'i',7,'s',7,'k',7
str_Bad_end:
str_Loading:
.byte 'L',7,'o',7,'a',7,'d',7,'i',7,'n',7,'g',7,'.',7,'.',7,'.',7,' ',7,' ',7
str_Loading_end:
str_Need_long:
.byte 'T',7,'o',7,'a',7,'r',7,'u',7,'O',7,'S',7,' ',7,'2',7,' ',7,'r',7,'e',7,'q',7,'u',7,'i',7,'r',7,'e',7,'s',7,' ',7,'a',7,' ',7,'6',7,'4',7,'-',7,'b',7,'i',7,'t',7,' ',7,'p',7,'r',7,'o',7,'c',7,'e',7,'s',7,'s',7,'o',7,'r',7
str_Need_long_end:
str_Spinny:
.byte '|','/','-','\\'
ind_Spinny:
.long 0