StupidOS/boot/bootsect/floppy.asm

185 lines
3 KiB
NASM

;; File: floppy.asm
format binary
use16
include '../common/const.inc'
include '../common/macro.inc'
org BOOTSECT_BASE
jmp short _start
nop
if FLOPPY_SIZE eq FLOPPY_2880
SECTORS_PER_CLUSTER = 2
ROOT_DIR_ENTRIES = 240
TOTAL_SECTORS = 5760
SECTORS_PER_TRACK = 36
else
SECTORS_PER_CLUSTER = 1
ROOT_DIR_ENTRIES = 224
TOTAL_SECTORS = 2880
SECTORS_PER_TRACK = 18
end if
; Boot Record
OEM_identifier db 'STUPID '
bytes_per_sector dw 512
sectors_per_cluster db SECTORS_PER_CLUSTER
reserved_sectors dw 1
FAT_count db 2
root_dir_entries dw ROOT_DIR_ENTRIES
total_sectors dw TOTAL_SECTORS
media_desc_type db 0xF0
sectors_per_FAT dw 9
sectors_per_track dw SECTORS_PER_TRACK
heads_per_cylinder dw 2
hidden_sectors dd 0
large_sector_count dd 0
; Extended Boot Record
drive_number db 0
reserved db 0
signature db 0x29 ; 0x28 or 0x29
volume_id dd 0xB00B135 ; hope mine will grow :'(
volume_label db 'Stupid Boot'
system_id db 'FAT12 '
_start:
cli
cld
jmp 0x0:.canonicalize_cs
.canonicalize_cs:
xor ax, ax
mov ds, ax
mov ss, ax
mov es, ax
mov sp, 0x7c00
mov [drive_number], dl
; reset floppy disk
@@:
mov dl, [drive_number]
xor ah, ah
int 0x13
jc @b
call fat_load_root
; search in root directory
mov si, stage1_file
call fat_search_root
jc .error_not_found
mov [stage1_start], ax
; load fat
xor ax, ax
mov al, [FAT_count]
mul word [sectors_per_FAT]
mov cx, ax
mov ax, [reserved_sectors]
xor bx, bx
call disk_read_sectors
; load stage 2
mov ax, LOADER_BASE/0x10
mov es, ax
mov ax, [stage1_start]
xor bx, bx
call fat_load_binary
mov dl, [drive_number]
jmp 0x0:LOADER_BASE
.error_not_found:
push si
mov si, msg_error
call bios_print
pop si
call bios_print
mov si, msg_not_found
call bios_print
hlt
jmp $
; CHS to LBA
; LBA = (C * HPC + H) * SPT + (S - 1)
;; Function: disk_read_sectors
;; Read sectors from disk to buffer
;;
;; Parameters:
;;
;; AX - LBA starting sector
;; CX - sector count
;; ES:BX - buffer
;;
disk_read_sectors:
; https://en.wikipedia.org/wiki/Logical_block_addressing
; convert LBA to CHS
; HPC = Head per Cluster
; SPT = Sector per Track
; S = (LBA % SPT) + 1
push ax
push bx
push cx
xor dx, dx
div word [sectors_per_track]
inc dx
mov [S], dx
; H = (LBA / SPT) % HPC
; C = LBA / (HPC * SPT)
xor dx, dx
div word [heads_per_cylinder]
mov [C], ax
mov [H], dx
; read sectors
mov ah, 0x2
mov al, 0x1
mov ch, byte [C]
mov cl, byte [S]
mov dh, byte [H]
mov dl, [drive_number]
int 0x13
jc @f
pop cx
pop bx
pop ax
add bx, word [bytes_per_sector]
inc ax
loop disk_read_sectors
ret
@@:
mov si, msg_error_sector
call bios_print
ret
C dw 0x00
H dw 0x00
S dw 0x00
include '../common/bios.inc'
include '../common/fat12.inc'
msg_error db "ERROR: ", 0
msg_not_found db " not found", CR, LF, 0
msg_error_sector db "reading sector", CR, LF, 0
stage1_file db "STPDLDR SYS", 0
stage1_start dw 0x0
rb 0x7C00+512-2-$
db 0x55, 0xAA