170 lines
2.6 KiB
NASM
170 lines
2.6 KiB
NASM
; SPDX-License-Identifier: MIT
|
|
; Copyright (c) 2021 Juhani 'nortti' Krekelä.
|
|
|
|
iosegment segment at 60h
|
|
ioinit proc far
|
|
ioinit endp
|
|
iosegment ends
|
|
|
|
bootloader segment
|
|
assume cs:bootloader, ds:bootloader, es:bootloader, ss:bootloader
|
|
org 7c00h
|
|
|
|
jmp code
|
|
|
|
; BPB
|
|
db "Ordos " ; OEM Identifier
|
|
dw 512 ; Bytes per sector
|
|
db 2 ; Sectors per cluster
|
|
dw 1 ; Reserved sectors
|
|
fats db 2 ; FATs
|
|
dw 112 ; Root directory entries
|
|
dw 2*720 ; Total sectors
|
|
db 0f9h ; Media descriptor
|
|
sectorsperfat dw 3 ; Sectors per fat
|
|
sectorspertrack dw 9
|
|
heads dw 2
|
|
dd 0 ; Hidden sectors
|
|
dd 0 ; Total sectors (large)
|
|
|
|
code:
|
|
cld
|
|
mov ax, cs
|
|
mov ds, ax
|
|
mov es, ax
|
|
cli
|
|
mov ss, ax
|
|
mov sp, 7c00h
|
|
sti
|
|
|
|
mov drivenumber, dl
|
|
|
|
; TODO: Check we actually have the OS
|
|
mov ax, 14
|
|
mov bx, 600h
|
|
mov cx, 17 ; This is what PC-DOS 1.10's full size ends up at
|
|
call loadsectors
|
|
|
|
mov si, offset success_msg
|
|
call printstr
|
|
|
|
jmp ioinit
|
|
|
|
; IN:
|
|
; ax = LBA of first sector
|
|
; es:bx = destination buffer
|
|
; cx = number of sectors to load
|
|
loadsectors proc
|
|
push ax
|
|
push cx
|
|
push dx
|
|
push di
|
|
|
|
loading_loop:
|
|
mov di, 3 + 1 ; Retry thrice, + 1 is since we dec first
|
|
|
|
retry:
|
|
|
|
push ax
|
|
push cx
|
|
|
|
chs:
|
|
xor dx, dx
|
|
; cylinder (track) - head - sector
|
|
; cylinder = LBA / sectorspertrack / heads
|
|
; head = LBA / sectorspertrack % heads
|
|
; sector = LBA % sectorspertrack + 1
|
|
div sectorspertrack
|
|
; ax = LBA / sectorspertrack
|
|
; dx = LBA % sectorspertrack
|
|
|
|
; sector
|
|
mov cl, dl
|
|
inc cl
|
|
|
|
xor dx, dx
|
|
div heads
|
|
; ax = LBA / sectorspertrack / heads
|
|
; dx = LBA / sectorspertrack % heads
|
|
|
|
; head
|
|
mov dh, dl
|
|
|
|
; cylinder (track)
|
|
mov ch, al
|
|
shr ax, 1
|
|
shr ax, 1
|
|
and al, 0c0h
|
|
or cl, al
|
|
|
|
mov ax, 0201h
|
|
mov dl, drivenumber
|
|
int 13h
|
|
|
|
jc disk_error
|
|
|
|
mov ax, 0e00h + '.'
|
|
int 10h
|
|
|
|
pop cx
|
|
pop ax
|
|
|
|
inc ax
|
|
add bx, 512
|
|
|
|
loop loading_loop
|
|
|
|
pop di
|
|
pop dx
|
|
pop cx
|
|
pop ax
|
|
ret
|
|
|
|
disk_error:
|
|
; Do we still have retries remaining?
|
|
dec di
|
|
jnz reset_disk
|
|
|
|
; No, die
|
|
mov si, offset error_msg
|
|
call printstr
|
|
|
|
hang:
|
|
hlt
|
|
jmp hang
|
|
|
|
reset_disk:
|
|
; Yes, reset disk and retry
|
|
xor ah, ah
|
|
int 13h
|
|
|
|
pop cx
|
|
pop ax
|
|
jmp retry
|
|
loadsectors endp
|
|
|
|
; IN:
|
|
; si = null-terminated string
|
|
printstr proc
|
|
lodsb
|
|
test al, al
|
|
jz ret_printstr
|
|
mov ah, 0eh
|
|
int 10h
|
|
jmp printstr
|
|
|
|
ret_printstr:
|
|
ret
|
|
printstr endp
|
|
|
|
drivenumber db (?)
|
|
|
|
success_msg db 13, 10, "DOS Loaded", 13, 10, 0
|
|
error_msg db 13, 10, "Disk error", 0
|
|
|
|
org 7c00h + 510
|
|
dw 0aa55h
|
|
|
|
bootloader ends
|
|
|
|
end
|