summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile5
-rw-r--r--src/boot.asm40
-rw-r--r--src/stage1_functions.asm105
-rw-r--r--src/stage2_check_magic.asm2
-rw-r--r--src/stage2_pm_functions.asm (renamed from src/stage2_functions.asm)0
-rw-r--r--src/stage2_real_functions.asm120
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