summaryrefslogtreecommitdiff
path: root/src/boot/stage2_real_functions.asm
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-06-10 20:55:56 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-06-10 20:55:56 +0200
commiteea5bf4b859eb56c5772c58ca54937a90a10e7ee (patch)
tree391b31a28a3740d3fd52a9a9d1c651bc9f12cc2b /src/boot/stage2_real_functions.asm
parent1625a4752545e54c439a38f3393ab9d72bfee721 (diff)
downloadabaos-eea5bf4b859eb56c5772c58ca54937a90a10e7ee.tar.gz
abaos-eea5bf4b859eb56c5772c58ca54937a90a10e7ee.tar.bz2
moved bootloader to subdirectory
Diffstat (limited to 'src/boot/stage2_real_functions.asm')
-rw-r--r--src/boot/stage2_real_functions.asm169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/boot/stage2_real_functions.asm b/src/boot/stage2_real_functions.asm
new file mode 100644
index 0000000..d49bfce
--- /dev/null
+++ b/src/boot/stage2_real_functions.asm
@@ -0,0 +1,169 @@
+; 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 37
+
+; data sections used for reading the kernel from disk
+SECTORS_PER_CYLINDER:
+ db 0x3F ; detect parameters enters the correct value here (sectors + 1)
+ ; if detection fails, force int13 to read ahead
+NOF_HEADS:
+ db 0x01 ; 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
+ jc .error
+ jmp .ok
+
+.error:
+ mov si, DISK_ERROR
+ call print_string
+ mov dh, 0
+ mov dl, ah
+ call print_hex
+ ret
+
+.ok:
+ 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
+
+probe_and_fix_disk_geometry:
+ mov cl, 0x1 ; from 1 to 63
+ mov BYTE [SECTORS_PER_CYLINDER], cl
+
+.loop:
+ mov dl, [BOOT_DRIVE]
+ mov ah, 0x02 ; read sectors from drive
+ mov al, 1 ; read 1 sector
+ mov cl, BYTE [SECTORS_PER_CYLINDER]
+ mov ch, BYTE 0
+ mov dh, BYTE 0
+
+ int 0x13
+
+ jnc .next_sector ; on error, remeber cl being the highest sector
+
+.fix_heads:
+ cmp [NOF_HEADS], BYTE 0 ; 0 heads, the BIOS is playing tricks to us!
+ je .illegal_heads
+ jmp .end
+
+.illegal_heads:
+ mov [NOF_HEADS], BYTE 1
+ jmp .end
+
+.next_sector:
+ mov cl, BYTE [SECTORS_PER_CYLINDER]
+ inc cl ; next sector
+ mov BYTE [SECTORS_PER_CYLINDER], cl
+ cmp cl, 0x40 ; to a max of 63, if so, this is the default
+ jbe .loop
+ jmp .fix_heads
+
+.end:
+ 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 ; after the end of the current track?
+ 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 ; after the number of heads?
+ 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