boot: Jump back to real mode to load sectors?
This commit is contained in:
parent
6ed0e72278
commit
a9b853d24c
178
boot/boot.S
178
boot/boot.S
@ -73,16 +73,6 @@ can_long:
|
||||
jmp _oh_no
|
||||
|
||||
good_memory:
|
||||
|
||||
/* Print "Loading..." */
|
||||
movl $str_Loading, %esi
|
||||
call print_string
|
||||
|
||||
/* 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
|
||||
@ -102,52 +92,7 @@ _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 $0xb8016, %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
|
||||
@ -240,6 +185,100 @@ print_string.loop:
|
||||
print_string.exit:
|
||||
ret
|
||||
|
||||
pm_stack:
|
||||
.quad 0
|
||||
|
||||
.global do_bios_call
|
||||
do_bios_call:
|
||||
.code32
|
||||
/* Standard function entry point stuff */
|
||||
push %ebp
|
||||
mov %esp, %ebp
|
||||
push %ebx
|
||||
push %edi
|
||||
push %esi
|
||||
/* Save stack because bios might mess it up? */
|
||||
movl %esp, %eax
|
||||
movl %eax, (pm_stack)
|
||||
|
||||
/* Prepare intermediary mode */
|
||||
mov $0x20, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
/* Enable intermediary mode */
|
||||
ljmp $0x18,$do_bios_call.0
|
||||
|
||||
do_bios_call.0:
|
||||
.code16
|
||||
/* Disable protected mode */
|
||||
mov %cr0, %eax
|
||||
and $~1, %eax
|
||||
mov %eax, %cr0
|
||||
|
||||
/* Jump to deactivate protected mode */
|
||||
ljmp $0x0,$do_bios_call.1
|
||||
|
||||
do_bios_call.1:
|
||||
/* Set up real mode segments */
|
||||
xor %ax, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
/* Enable interrupts while BIOS is active */
|
||||
sti
|
||||
|
||||
/* Perform disk read */
|
||||
mov $0x42, %ah /* Extended read */
|
||||
mov boot_disk, %dl /* Using our boot disk */
|
||||
mov $dap, %si /* From the DAP below */
|
||||
int $0x13
|
||||
|
||||
/* Disable interrupts again */
|
||||
cli
|
||||
|
||||
/* Restore data segment, gdt */
|
||||
xor %ax,%ax
|
||||
mov %ax, %ds
|
||||
lgdtw gdtr
|
||||
|
||||
/* Enable protected mode */
|
||||
mov %cr0, %eax
|
||||
or $1, %eax
|
||||
mov %eax, %cr0
|
||||
|
||||
/* Jump to activate protected mode */
|
||||
ljmp $0x08,$do_bios_call.2
|
||||
|
||||
do_bios_call.2:
|
||||
.code32
|
||||
/* Restore protected mode data segments */
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
/* Restore stack */
|
||||
movl (pm_stack), %eax
|
||||
movl %eax, %esp
|
||||
|
||||
/* Pop callee-saved registers we may messed with */
|
||||
pop %esi
|
||||
pop %edi
|
||||
pop %ebx
|
||||
pop %ebp
|
||||
|
||||
/* Return */
|
||||
ret
|
||||
|
||||
.align 8
|
||||
gdtr:
|
||||
.word gdt_end - gdt_base - 1
|
||||
@ -253,12 +292,27 @@ gdt_base:
|
||||
.byte 0x9a
|
||||
.byte 0xcf
|
||||
.byte 0
|
||||
|
||||
.word 0xffff
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x92
|
||||
.byte 0xcf
|
||||
.byte 0
|
||||
|
||||
.word 0xffff
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x9e
|
||||
.byte 0
|
||||
.byte 0
|
||||
|
||||
.word 0xffff
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x92
|
||||
.byte 0
|
||||
.byte 0
|
||||
gdt_end:
|
||||
|
||||
.global boot_disk
|
||||
@ -286,8 +340,10 @@ dap_sectors:
|
||||
.global dap_buffer
|
||||
dap_buffer:
|
||||
.long 0x0
|
||||
.global dap_lba_low
|
||||
dap_lba_low:
|
||||
.long 0
|
||||
.global dap_lba_high
|
||||
dap_lba_high:
|
||||
.long 0
|
||||
|
||||
@ -305,13 +361,13 @@ drive_params_bps:
|
||||
|
||||
str_Bad:
|
||||
.asciz "The boot disk does not seem to be a CD."
|
||||
str_Loading:
|
||||
.asciz "Loading... "
|
||||
str_Need_long:
|
||||
.asciz "ToaruOS 2.0 requires a 64-bit processor."
|
||||
str_More_mem:
|
||||
.asciz "ToaruOS 2.0 needs at least 128MiB of RAM, and 1GiB is recommended."
|
||||
str_Spinny:
|
||||
.byte '|','/','-','\\'
|
||||
ind_Spinny:
|
||||
.long 0
|
||||
str_Out_of_modes:
|
||||
.asciz "Out of display modes"
|
||||
|
||||
.global disk_space
|
||||
disk_space:
|
||||
.zero 2048
|
||||
|
@ -589,10 +589,26 @@ static void finish_boot(void) {
|
||||
);
|
||||
}
|
||||
|
||||
extern int bios_call(char * into, uint32_t sector);
|
||||
|
||||
static int spin_x = 0;
|
||||
static void spin(void) {
|
||||
static char spinchars[] = "/-\\|";
|
||||
static char tmp[] = "x";
|
||||
static int spincnt = 0;
|
||||
|
||||
x = spin_x;
|
||||
spincnt = (spincnt + 1) & 0x3;
|
||||
tmp[0] = spinchars[spincnt];
|
||||
|
||||
print_(tmp);
|
||||
}
|
||||
|
||||
void boot(void) {
|
||||
clear_();
|
||||
print("Looking for ISO9660 filesystem... ");
|
||||
for (int i = 0x10; i < 0x15; ++i) {
|
||||
bios_call((char*)(DATA_LOAD_BASE + ISO_SECTOR_SIZE * i), i);
|
||||
root = (void*)(DATA_LOAD_BASE + ISO_SECTOR_SIZE * i);
|
||||
switch (root->type) {
|
||||
case 1:
|
||||
@ -612,6 +628,14 @@ done:
|
||||
|
||||
kernel_load_start = (char*)(DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE);
|
||||
|
||||
print_("Loading kernel... "); spin_x = x;
|
||||
for (int i = 0, j = 0; i < dir_entry->extent_length_LSB; j++) {
|
||||
if (!(j & 0x3FF)) spin();
|
||||
bios_call(kernel_load_start + i, dir_entry->extent_start_LSB + j);
|
||||
i += ISO_SECTOR_SIZE;
|
||||
}
|
||||
print_("\n");
|
||||
|
||||
print("Looking for ramdisk... ");
|
||||
if (!navigate(ramdisk_path)) {
|
||||
print_("Failed to locate ramdisk.\n");
|
||||
@ -620,6 +644,15 @@ done:
|
||||
print("found.\n");
|
||||
|
||||
ramdisk_off = DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE;
|
||||
|
||||
print_("Loading ramdisk... "); spin_x = x;
|
||||
for (int i = 0, j = 0; i < dir_entry->extent_length_LSB; j++) {
|
||||
if (!(j & 0x3FF)) spin();
|
||||
bios_call((char*)(ramdisk_off + i), dir_entry->extent_start_LSB + j);
|
||||
i += ISO_SECTOR_SIZE;
|
||||
}
|
||||
print_("\n");
|
||||
|
||||
ramdisk_len = dir_entry->extent_length_LSB;
|
||||
|
||||
multiboot_header.cmdline = (uintptr_t)cmdline;
|
||||
|
@ -64,13 +64,31 @@ int bios_main(void) {
|
||||
return kmain();
|
||||
}
|
||||
|
||||
extern void do_bios_call(void);
|
||||
extern volatile uint16_t dap_sectors;
|
||||
extern volatile uint32_t dap_buffer;
|
||||
extern volatile uint32_t dap_lba_low;
|
||||
extern volatile uint32_t dap_lba_high;
|
||||
extern uint8_t disk_space[];
|
||||
|
||||
int bios_call(char * into, uint32_t sector) {
|
||||
dap_buffer = (uint32_t)disk_space;
|
||||
dap_lba_low = sector;
|
||||
dap_lba_high = 0;
|
||||
dap_sectors = 1;
|
||||
do_bios_call();
|
||||
memcpy(into, disk_space, 2048);
|
||||
}
|
||||
|
||||
iso_9660_volume_descriptor_t * root = NULL;
|
||||
iso_9660_directory_entry_t * dir_entry = NULL;
|
||||
static char * dir_entries = NULL;
|
||||
|
||||
int navigate(char * name) {
|
||||
dir_entry = (iso_9660_directory_entry_t*)&root->root;
|
||||
|
||||
dir_entries = (char*)(DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE);
|
||||
bios_call(dir_entries, dir_entry->extent_start_LSB);
|
||||
long offset = 0;
|
||||
while (1) {
|
||||
iso_9660_directory_entry_t * dir = (iso_9660_directory_entry_t *)(dir_entries + offset);
|
||||
|
Loading…
Reference in New Issue
Block a user