From 13e26c52945650293ccc5c6c31e1470f043d7d10 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 9 Jun 2017 17:43:01 +0200 Subject: fixed stage 1 boot loader problems (worked in some BIOSes across the 2 times sector/track limit). loading sectors one by one now fixed also spin down problem after loading stage 2 and the kernel for now tested with 1.44 MB floppies (both real and in bochs/qemu) --- BUGS | 7 +--- doc/LINKS.TODO | 3 ++ doc/README.DISK_GEOMETRY | 70 ++++++++++++++++++++++++++++++++++++++ src/Makefile | 8 +++-- src/boot.asm | 6 +++- src/stage1_functions.asm | 88 +++++++++++++++++++++++++++++++++++------------- 6 files changed, 150 insertions(+), 32 deletions(-) create mode 100644 doc/README.DISK_GEOMETRY diff --git a/BUGS b/BUGS index 69b9a8d..6afbc5b 100644 --- a/BUGS +++ b/BUGS @@ -1,9 +1,4 @@ -- on AMD-K5 machine, bootloader results in DISK ERROR 0x0004 - (too many sectors read in one row?) - PS/2 answers with ERROR if PS/2 mouse is not connected, read_ack should handle error cases correctly. We should - also probe correctly for the mouse. -- floppy drive doesn't spin down after reading stage2 and - kernel from floppy. Do we have to call 0x13, 0x00 reset - drive? + also probe correctly for the mouse. (0xFE on all commands) diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO index d58cc0d..81e0466 100644 --- a/doc/LINKS.TODO +++ b/doc/LINKS.TODO @@ -67,6 +67,9 @@ http://www.sci.muni.cz/docs/pc/serport.txt Boot: https://www.cs.cmu.edu/~410-s07/p4/p4-boot.pdf +http://www.osdever.net/tutorials/view/loading-sectors +http://www.osdever.net/tutorials/view/lba-to-chs +LILO boot loader C: http://www.drdobbs.com/extending-c-for-object-oriented-programm/184402731 diff --git a/doc/README.DISK_GEOMETRY b/doc/README.DISK_GEOMETRY new file mode 100644 index 0000000..54f6092 --- /dev/null +++ b/doc/README.DISK_GEOMETRY @@ -0,0 +1,70 @@ +This affects the boot loader in stage 1 using +BIOS functions to read stage 2 and the kernel + +Geometry Specification + + +360 KB 5.25" + + +1.2 MB 5.25" + + +720 KB 3.5" + + +1.44 MB 3.5" + + +2.88 MB 3.5" + +Tracks (Cylinders) + + +40 + + +80 + + +80 + + +80 + + +80 + +Sectors Per Track/Cylinder + + +9 + + +15 + + +9 + + +18 + + +36 + +Total Sectors Per Disk + + +720 + + +2,400 + + +1,440 + + +2,880 + + +5,760 diff --git a/src/Makefile b/src/Makefile index 615c3b6..24d0088 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,10 +14,14 @@ all: image.bin kernel.sym # + 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 38) +# 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) image.bin: boot.bin kernel.bin magic.bin cat boot.bin kernel.bin > image.tmp truncate -s 19456 image.tmp 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 $(NASM) boot.asm -DMAGIC='"$(MAGIC)"' -f bin -o boot.bin @@ -94,11 +98,11 @@ clean: -rm -f boot.bin kernel.bin kernel.sym kernel.elf image.bin magic.bin *.o boot.map image.tmp run-qemu: image.bin - qemu-system-i386 -net nic,model=ne2k_pci -d guest_errors -m 32 -drive "file=image.bin,if=ide,format=raw" \ + qemu-system-i386 -net nic,model=ne2k_pci -d guest_errors -m 32 -drive "file=image.bin,if=floppy,format=raw" \ -serial file:serial.log run-qemu-debug: image.bin - qemu-system-i386 -net nic,model=ne2k_pci -S -s -d guest_errors -m 32 -drive "file=image.bin,if=ide,format=raw" \ + qemu-system-i386 -net nic,model=ne2k_pci -S -s -d guest_errors -m 32 -drive "file=image.bin,if=floppy,format=raw" \ -serial file:serial.log run-bochs: diff --git a/src/boot.asm b/src/boot.asm index 9620fcc..3f9c127 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -44,6 +44,10 @@ ; after the boot sector) mov dl, [BOOT_DRIVE] call read_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 @@ -63,7 +67,7 @@ MESSAGE_BOOT_DRIVE: db "Booting from drive ", 0 MESSAGE_LOADING_STAGE_2: - db "Loading stage 2 boot loader", 13, 10, 0 + db "Loading stage 2 boot loader and kernel", 0 BOOT_DRIVE: db 0 diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm index c9ed1a5..8a73a9b 100644 --- a/src/stage1_functions.asm +++ b/src/stage1_functions.asm @@ -4,20 +4,6 @@ ; subtract 1 here!) NOF_LOAD_SECTORS equ 38 -; IN bx: begin of memory area to dump -; IN ax: number of words to dump -dump_range: - mov dx, bx - call print_hex - mov dx, [bx] - call print_hex - call print_newline - add bx, 2 - dec ax - cmp ax, 0 - jnz dump_range - ret - ; IN dx: hex value to print print_hex: push bx @@ -104,25 +90,76 @@ current_row: pop ax ret +; data sections used for reading from disk +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 + +; read the whole stage2 and kernel from the disk ; IN dl: drive to read from read_from_disk: - mov ah, 0x02 ; read sectors from drive - - mov al, NOF_LOAD_SECTORS ; read 1 sector - 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 + cmp [CURRENT_SECTOR], BYTE 0x13 ; 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 + cmp [CURRENT_HEAD], BYTE 0x02 ; 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, NOF_LOAD_SECTORS ; 1 sector read? + cmp al, 1 ; 1 sector read? jne .short_read ; if not, short read + + mov al, '.' + call print_char ret @@ -139,3 +176,8 @@ read_from_disk: call print_string jmp $ +kill_motor: + mov dx, 0x3F2 + mov al, 0x00 + out dx, al + ret -- cgit v1.2.3-54-g00ecf