1
0
tetros/bios/stage1.asm
2025-03-02 22:05:01 -08:00

175 lines
3.4 KiB
NASM

USE16
stage1:
; Initialize segment registers
xor ax, ax ; Set ax to 0
mov ds, ax
mov es, ax
mov ss, ax
; Initialize stack pointer
; (stack grows up)
mov sp, 0x7C00
; Initialize CS
;
; `retf` sets both CS and IP to a known-good state.
; This is necessary because we don't know where the BIOS put us at startup.
; (could be 0x00:0x7C00, could be 0x7C00:0x00. Not everybody follows spec.)
push ax ; `ax` is still 0
push word .set_cs
retf
.set_cs:
; Save disk number.
; BIOS sets `dl` to the number of
; the disk we're booting from.
mov [disk], dl
; Print "Stage 1"
mov si, stage_msg
call print
mov al, '1'
call print_char
call print_line
; read CHS gemotry, save into [chs]
; CL (bits 0-5) = maximum sector number
; CL (bits 6-7) = high bits of max cylinder number
; CH = low bits of maximum cylinder number
; DH = maximum head number
mov ah, 0x08
mov dl, [disk]
xor di, di
int 0x13
jc error ; carry flag set on error
mov bl, ch
mov bh, cl
shr bh, 6
mov [chs.c], bx
shr dx, 8
inc dx ; returns heads - 1
mov [chs.h], dx
and cl, 0x3f
mov [chs.s], cl
; First sector of stage 2
mov eax, STAGE2_SECTOR
; Where to load stage 2
mov bx, stage2
; length of stage2 + stage3
; (on disk, in sectors)
mov cx, (stage3.end - stage2) / 512
mov dx, 0
; Consume eax, bx, cx, dx
; and load code from disk.
call load
jmp stage2.entry
; Load sectors from disk to memory.
; Cannot load more than 1MiB.
;
; Input:
; ax: start sector
; bx: offset of buffer
; cx: number of sectors (512 Bytes each)
; dx: segment of buffer
;
; Clobbers ax, bx, cx, dx, si
load:
; replaced 127 with 1.
; see https://stackoverflow.com/questions/58564895/problem-with-bios-int-13h-read-sectors-from-drive
; TODO: fix later
cmp cx, 1 ;127
jbe .good_size
pusha
mov cx, 1; 127
call load
popa
add eax, 1; 127
add dx, 1 * 512 / 16 ; 127
sub cx, 1;127
jmp load
.good_size:
mov [DAPACK.addr], eax
mov [DAPACK.buf], bx
mov [DAPACK.count], cx
mov [DAPACK.seg], dx
; Print the data we're reading
; TODO: decode
mov bx, [DAPACK.addr + 2]
call print_hex
mov bx, [DAPACK.addr]
call print_hex
mov al, '#'
call print_char
mov bx, [DAPACK.count]
call print_hex
mov al, ' '
call print_char
mov bx, [DAPACK.seg]
call print_hex
mov al, ':'
call print_char
mov bx, [DAPACK.buf]
call print_hex
call print_line
; Read from disk.
;
; Note:
; int 0x13 extended read does not work on CDROM,
; but we don't care. We're booting from a floppy.
mov dl, [disk]
mov si, DAPACK
mov ah, 0x42
int 0x13
jc error ; carry flag set on error
ret
error:
call print_line
mov bh, 0
mov bl, ah
call print_hex
mov si, stage1_error_msg
call print
call print_line
.halt:
cli
hlt
jmp .halt
%include "print.asm"
stage_msg: db "Stage ",0
stage1_error_msg: db " ERROR",0
disk: db 0
chs:
.c: dd 0
.h: dd 0
.s: dd 0
DAPACK:
db 0x10
db 0
.count: dw 0 ; int 13 resets this to # of blocks actually read/written
.buf: dw 0 ; memory buffer destination address (0:7c00)
.seg: dw 0 ; in memory page zero
.addr: dq 0 ; put the lba to read in this spot
db 0xff