diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2017-06-10 09:30:59 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2017-06-10 09:30:59 +0200 |
commit | 1595632297f12b3aa2f1adfdcd06ea47bf31486c (patch) | |
tree | 83b0b2065884fc58c0ff4ecdf115dc00db3b7cb3 | |
parent | 0be74eeee017b7116126e258b97df5a857dac4ab (diff) | |
download | abaos-1595632297f12b3aa2f1adfdcd06ea47bf31486c.tar.gz abaos-1595632297f12b3aa2f1adfdcd06ea47bf31486c.tar.bz2 |
rearranged boot loader: first load 3 sectors of stage 2 in simple
int 13h read. then in stage 2 do a much better detection of disk
geometries in the future (for now, it's the same) and load the
kernel sectors with a more complex loading routine
-rw-r--r-- | src/Makefile | 5 | ||||
-rw-r--r-- | src/boot.asm | 40 | ||||
-rw-r--r-- | src/stage1_functions.asm | 105 | ||||
-rw-r--r-- | src/stage2_check_magic.asm | 2 | ||||
-rw-r--r-- | src/stage2_pm_functions.asm (renamed from src/stage2_functions.asm) | 0 | ||||
-rw-r--r-- | src/stage2_real_functions.asm | 120 |
6 files changed, 161 insertions, 111 deletions
diff --git a/src/Makefile b/src/Makefile index 55f8975..3ec465d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,8 @@ all: image.bin kernel.sym # + M * 512 (M is currently 7) = 3144 for kernel.bin # + 1 * 512 = 512 for magic.bin # (M + N + 1 is the number of sectors to be read in stage 2, as stage 1 -# loads only the first sector, so adapt NOF_LOAD_SECTORS to 39) +# loads only the first sector, and stage 1 loads 3 sectors of stage 2, +# adapt NOF_LOAD_SECTORS to 36) # then we make sure the image has the size of a 1.44 MB floppy # (emulators like qemu do some guess work for CHS resolution based # on the size of the image) @@ -23,7 +24,7 @@ image.bin: boot.bin kernel.bin magic.bin cat image.tmp magic.bin > image.bin truncate -s 1474560 image.bin -boot.bin: boot.asm boot_gdt.asm stage1_functions.asm stage2_functions.asm stage2_switch_mode.asm stage2_a20.asm +boot.bin: boot.asm boot_gdt.asm stage1_functions.asm stage2_real_functions.asm stage2_pm_functions.asm stage2_switch_mode.asm stage2_a20.asm $(NASM) boot.asm -DMAGIC='"$(MAGIC)"' -f bin -o boot.bin kernel.bin: kernel.elf diff --git a/src/boot.asm b/src/boot.asm index 88f7404..b047d58 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -40,18 +40,11 @@ mov si, MESSAGE_LOADING_STAGE_2 call print_string -; detect disk geometry - mov dl, [BOOT_DRIVE] - call detect_disk_geometry - -; load stage 2 and the kernel together to 0x7e00 (directly +; load stage 2 with simple load method to 0x7e00 (directly ; after the boot sector) mov dl, [BOOT_DRIVE] - call read_from_disk + call read_stage2_from_disk call print_newline - -; turn off disk motor - call kill_motor ; jump over variables and subroutines of stage 1 and execute stage 2 jmp stage2 @@ -71,7 +64,10 @@ MESSAGE_BOOT_DRIVE: db "Booting from drive ", 0 MESSAGE_LOADING_STAGE_2: - db "Loading stage 2 boot loader and kernel", 0 + db "Loading stage 2 boot loader", 0 + +MESSAGE_LOADING_KERNEL: + db "Loading kernel", 0 BOOT_DRIVE: db 0 @@ -88,6 +84,23 @@ stage2: mov si, MESSAGE_STAGE_2_LOADED call print_string +; print a message we are now loading the kernel + mov si, MESSAGE_LOADING_KERNEL + call print_string + +; detect disk geometry + mov dl, [BOOT_DRIVE] + call detect_disk_geometry + +; load kernel to 0x8400 (directly after stage 2 +; of the boot loader) + mov dl, [BOOT_DRIVE] + call read_from_disk + call print_newline + +; turn off disk motor + call kill_motor + ; check A20 gate mov si, MESSAGE_STAGE_2_CHECKING_A20 call print_string @@ -135,7 +148,8 @@ MESSAGE_STAGE_2_A20_DISABLED: MESSAGE_HALTED_REAL: db "Operating system halted in real mode", 13, 10, 0 - + +%include "stage2_real_functions.asm" %include "stage2_switch_mode.asm" %include "stage2_a20.asm" @@ -188,10 +202,10 @@ MESSAGE_CALL_C_ENTRY: MESSAGE_HALTED: db "Operating system halted", 0 -%include "stage2_functions.asm" +%include "stage2_pm_functions.asm" %include "stage2_check_magic.asm" -; make sure we have full sectors, stage one is 512 bytes, so we +; make sure we have full sectors, stage 1 is 512 bytes, so we ; have to will up 3 sectors times 2048-($-$$) db 0 diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm index e9281c4..bdb2aac 100644 --- a/src/stage1_functions.asm +++ b/src/stage1_functions.asm @@ -1,9 +1,3 @@ -; number of sectors to be read -; 3 * 512 for bootloader stage2 and the kernel code -; (note: the first sector gets loaded by the BIOS, so -; subtract 1 here!) -NOF_LOAD_SECTORS equ 39 - ; IN dx: hex value to print print_hex: push bx @@ -90,99 +84,25 @@ current_row: pop ax ret -; data sections used for reading from disk -SECTORS_PER_CYLINDER: - db 0x13 ; detect parameters enters the correct value here (sectors + 1) -NOF_HEADS: - db 0x02 ; number of heads + 1 -SECTORS_TO_LOAD: - db NOF_LOAD_SECTORS ; load NOF_LOAD_SECTORS sectors in total -CURRENT_SECTOR: - db 2 ; second sector after boot sector -CURRENT_CYLINDER: - db 0 -CURRENT_HEAD: - db 0 - -; detect disk geometry -; IN dl: drive -detect_disk_geometry: - mov dx, 0 - mov es, dx - mov ah, 0x08 - int 0x13 - add dh, 1 - mov [NOF_HEADS], BYTE dh -; call print_hex -; mov dx, cx -; call print_hex - and cl, 0x3F - add cl, 1 - mov [SECTORS_PER_CYLINDER], BYTE cl - ret - -; read the whole stage2 and kernel from the disk ; IN dl: drive to read from -read_from_disk: - +read_stage2_from_disk: + mov ah, 0x02 ; read sectors from drive + + mov al, 3 ; read 3 sectors of stage 2 + mov ch, 0 ; select first cylinder + mov dh, 0 ; first head + mov cl, 2 ; second sector after boot sector + mov bx, 0 ; where to store the data mov es, bx mov bx, 0x7e00 ; 512 bytes after first sector - -.read_next_sector: - - call read_one_sector_from_disk - - sub [SECTORS_TO_LOAD], BYTE 1 ; one less to load - cmp [SECTORS_TO_LOAD], BYTE 0 ; finished? - je .finished - - add bx, 0x200 ; advance write buffer position - add [CURRENT_SECTOR], BYTE 1 ; next sector - mov ch, [SECTORS_PER_CYLINDER] - cmp [CURRENT_SECTOR], ch ; assuming 18 sectors per track for now - je .next_head - jmp .read_next_sector - -.next_head: - mov [CURRENT_SECTOR], BYTE 1 ; start from first sector again - add [CURRENT_HEAD], BYTE 1 ; advance head - mov ch, [NOF_HEADS] - cmp [CURRENT_HEAD], ch ; 2 heads on floppies - je .next_track - jmp .read_next_sector - -.next_track: - mov [CURRENT_HEAD], BYTE 0 ; start from head 0 again - add [CURRENT_CYLINDER], BYTE 1 ; advance track - jmp .read_next_sector - -.finished: - ret - -; Read one sector after the other, if we get illegal parameter -; errors we assume we have gone over the limit of number of -; sectors per cylinder. This avoids to probe for this number with -; shacky BIOS functions or with probing (as LILO does). It's not -; very efficient though.. -; IN dl: drive to read from -read_one_sector_from_disk: - mov ah, 0x02 ; read sectors from drive - - mov al, 1 ; read 1 sector - mov ch, BYTE [CURRENT_CYLINDER] - mov dh, BYTE [CURRENT_HEAD] - mov cl, BYTE [CURRENT_SECTOR] - + int 0x13 jc .read_error - cmp al, 1 ; 1 sector read? + cmp al, 3 ; 3 sectors read? jne .short_read ; if not, short read - - mov al, '.' - call print_char ret @@ -199,8 +119,3 @@ read_one_sector_from_disk: call print_string jmp $ -kill_motor: - mov dx, 0x3F2 - mov al, 0x00 - out dx, al - ret diff --git a/src/stage2_check_magic.asm b/src/stage2_check_magic.asm index 43bbb95..1deaf05 100644 --- a/src/stage2_check_magic.asm +++ b/src/stage2_check_magic.asm @@ -8,7 +8,7 @@ check_magic: push edi mov eax, NOF_LOAD_SECTORS ; number of 512-byte sectors shl eax, 9 ; 512 bytes per sector - mov edx, 0x7e00 ; offset of stage 2 + mov edx, 0x8400 ; offset of kernel add edx, eax sub edx, MAGICLEN ; subtract the length of the magic string mov esi, edx ; now use edx as first string address to compare to diff --git a/src/stage2_functions.asm b/src/stage2_pm_functions.asm index f3c348b..f3c348b 100644 --- a/src/stage2_functions.asm +++ b/src/stage2_pm_functions.asm diff --git a/src/stage2_real_functions.asm b/src/stage2_real_functions.asm new file mode 100644 index 0000000..bb05b6e --- /dev/null +++ b/src/stage2_real_functions.asm @@ -0,0 +1,120 @@ +; number of sectors to be read for the kernel itself +; (note: the first sector gets loaded by the BIOS, the +; next 3 sectors are read by the simple stage 1 loader, +; so subtract 3 here!) +NOF_LOAD_SECTORS equ 36 + +; data sections used for reading the kernel from disk +SECTORS_PER_CYLINDER: + db 0x13 ; detect parameters enters the correct value here (sectors + 1) +NOF_HEADS: + db 0x02 ; number of heads + 1 +SECTORS_TO_LOAD: + db NOF_LOAD_SECTORS ; load NOF_LOAD_SECTORS sectors in total +CURRENT_SECTOR: + db 5 ; first sector after stage 2 +CURRENT_CYLINDER: + db 0 +CURRENT_HEAD: + db 0 + +; detect disk geometry +; IN dl: drive +detect_disk_geometry: + mov dx, 0 + mov es, dx + mov ah, 0x08 + int 0x13 + add dh, 1 + mov [NOF_HEADS], BYTE dh + call print_hex + mov dx, cx + call print_hex + and cl, 0x3F + add cl, 1 + mov [SECTORS_PER_CYLINDER], BYTE cl + ret + +; read the whole stage2 and kernel from the disk +; IN dl: drive to read from +read_from_disk: + + mov bx, 0 ; where to store the data + mov es, bx + mov bx, 0x8400 ; 2'048 bytes after first sector + +.read_next_sector: + + call read_one_sector_from_disk + + sub [SECTORS_TO_LOAD], BYTE 1 ; one less to load + cmp [SECTORS_TO_LOAD], BYTE 0 ; finished? + je .finished + + add bx, 0x200 ; advance write buffer position + add [CURRENT_SECTOR], BYTE 1 ; next sector + mov ch, [SECTORS_PER_CYLINDER] + cmp [CURRENT_SECTOR], ch ; assuming 18 sectors per track for now + je .next_head + jmp .read_next_sector + +.next_head: + mov [CURRENT_SECTOR], BYTE 1 ; start from first sector again + add [CURRENT_HEAD], BYTE 1 ; advance head + mov ch, [NOF_HEADS] + cmp [CURRENT_HEAD], ch ; 2 heads on floppies + je .next_track + jmp .read_next_sector + +.next_track: + mov [CURRENT_HEAD], BYTE 0 ; start from head 0 again + add [CURRENT_CYLINDER], BYTE 1 ; advance track + jmp .read_next_sector + +.finished: + ret + +; Read one sector after the other, if we get illegal parameter +; errors we assume we have gone over the limit of number of +; sectors per cylinder. This avoids to probe for this number with +; shacky BIOS functions or with probing (as LILO does). It's not +; very efficient though.. +; IN dl: drive to read from +read_one_sector_from_disk: + mov ah, 0x02 ; read sectors from drive + + mov al, 1 ; read 1 sector + mov ch, BYTE [CURRENT_CYLINDER] + mov dh, BYTE [CURRENT_HEAD] + mov cl, BYTE [CURRENT_SECTOR] + + int 0x13 + + jc .read_error + + cmp al, 1 ; 1 sector read? + jne .short_read ; if not, short read + + mov al, '.' + call print_char + + ret + +.read_error: + mov si, DISK_ERROR + call print_string + mov dh, 0 + mov dl, ah + call print_hex + jmp $ + +.short_read: + mov si, SHORT_READ + call print_string + jmp $ + +kill_motor: + mov dx, 0x3F2 + mov al, 0x00 + out dx, al + ret |