;----------------------------------;
; Floppy Boot Record ;
; Written by Christian Henrichsen ;
; 30.09.2024 ;
; Copyright (C) ;
; Christian Henrichsen ;
; 2024 ;
; ;
; Copyright Notice Must be ;
; Included with All Copies of This ;
; Program ;
;----------------------------------;
org 7c00h ; Program origin of 7c00h
bits 16 ; 16-bit programing
cpu 8086 ; And assembling for the iAPX 8086 processor
jmp short start
nop
;------------------------------
; BIOS PARAMETER BLOCK
BPB:
OEMLabel db "MSWIN4.1" ; Disk label
bps dw 512 ; Bytes per sector
spc db 1 ; Sectors per cluster
rs dw 1 ; Reserved sectors for boot record
nFAT db 2 ; Number of copies of the FAT
MRDIR dw 224 ; Number of entries in root dir
; (224 * 32 = 7168 = 14 sectors to read)
tSect dw 2880 ; Number of logical sectors
mdesc db 0F0h ; Medium descriptor byte
spfat dw 9 ; Sectors per FAT
sptrk dw 18 ; Sectors per track (36/cylinder)
nhead dw 2 ; Number of sides/heads
hsect dd 0 ; Number of hidden sectors
tsectl dd 0 ; Number of LBA sectors
drvno dw 0 ; Drive No: 0
ebsig db 41 ; Drive signature: 41 for floppy
vsnum dd 00000000h ; Volume ID: any number
vlabl db "MIKEOS "; Volume Label: any 11 chars
fstyp db "FAT12 " ; File system type: don't change!
;bps dw 512 ; Bytes Per Sector
;spc db 2 ; Sectors Per Cluster
;rs dw 0 ; Reserved Sectors
;nFAT db 2 ; Number of FAT's
;MRDIR dw 224 ; Max Root Directory Entries
;tSect dw 2880 ; Total Sectors
;mdesc db 0f0h ; Media Descriptor Byte
;spfat dw 9 ; Sectors Per FAT
;sptrk dw 18 ; Sectors Per Track
;nhead dw 2 ; Number of heads
;hsect dd 0 ; Hidden Sectors
;tsect dd 0 ; Total Sectors
;drvno db 0 ; Drive Number
;flags db 0 ; Flags
;ebsig db 29h ; Extended Boot Signature
;vsnum dd 12341234h ; Volume Serial Number
;vlabl db 'NO NAME ' ; Volume Label
;fstyp db 'FAT12 ' ; Filesystem Type
FILES_AREA equ 33
ROOT_DIR equ 19
ROOT_SIZE equ 14
LOAD_OFFSET equ 0000h
LOAD_SEGMENT equ 2000h
;-----------------
; Boot Loader
start:
cli ; Clear the interrupt flag, only non-maskable interrupts will be enabled
xor ax, ax ; Zero out accumulator
mov ss, ax ; Set the stack segment register
mov sp, 7c00h ; and the Stack Pointer
push ax ; Pushing AX
push ax ; Pushing AX again
pop es ; And popping it into ES
pop ds ; and DS and setting them both to zero
sti ; Set the interrupts flag back on, now every single interrupt can interrupt my work
jmp 0000:enforce_csip ; Preforming a far jump to enforce CS:IP
enforce_csip: ; Now that CS:IP is enforced
read_rootdir:
;mov byte [drvno], dl ; Sve drive number
mov ax, ROOT_DIR ; AX = the lba of the root directory
call convert_LBA ; Convert it to its appropriate CHS parameters for int 13h
mov al, ROOT_SIZE ; How many sectors? 14, read 14 sectors
mov bx, buffer
call read_sect ; Let's read those sector's
mov cx, 224
check_root_dir:
mov di, buffer
mov si, filename
push cx
mov cx, 11
rep cmpsb
je found_file
pop cx
add di, 32
loop check_root_dir
no_kernel:
mov si, non_sys_disk
jmp print_string
found_file:
pop cx
mov ax, 1
call convert_LBA
mov al, 9
mov bx, buffer
call read_sect
mov si, di
mov al, [si+0bh]
test al, 0d8h ; Bit-mask for bits 11011000
;jnz no_kernel ; The kernel is either invalid or not here
xor ax, ax
mov dx, ax
mov word ax, [si+1ah] ; AX = First cluster of kernel
push ax
mov bx, LOAD_SEGMENT
mov es, bx
mov bx, LOAD_OFFSET
read_cluster:
sub ax, 2 ; Cluster number - 2
mul byte [spc] ; Times Sectors Per Cluster
add ax, FILES_AREA ; AX now equals the actual LBA sector to read
call convert_LBA ; Convert to CHS
mov al, [spc] ; Sectors to read
call read_sect ; Read setctor's
pop ax ; AX = Cluster number for next entry in FAT
push bx ; Save BX since it has the load pointer
mov bx, buffer ; BX = FAT buffer
call get_fat ; Get FAT12 field
cmp ax, 0ff8h ; Is it ff8 or greater?
jae short jump_to_kernel ; Yes, it's the end of our kernel. Let's jump to it
pop bx ; Nope keep reading
add bx, 512 ; Add 512 since we are to not overwrite what we have read
jmp short read_cluster
jump_to_kernel:
pop bx
jmp LOAD_SEGMENT:LOAD_OFFSET
;-----------------
; Loader Subroutines
get_fat:
push bx
push cx
mov cx, ax
shl ax, 1
add ax, cx
test ax, 1
pushf
shr ax, 1
add bx, ax
mov ax, [bx]
popf
jnz .getfat1
and ax, 0fffh
jmp .getfat2
.getfat1:
mov cl, 4
shr ax, cl
.getfat2:
pop cx
pop bx
ret
print_string:
mov ah, 0eh
.print_loop:
lodsb
cmp al, 0
je .done
int 10h
jmp short .print_loop
.done:
reboot:
xor ax, ax
int 16h
mov word [ds:472h], 1234h ; To simulate a ctrl+alt+del
jmp 0ffffh:0000h ; Reset the system
read_sect: ; IN: call to convert_LBA, DL = Drive to read, BX = Buffer address, ES = Segment
mov ah, 02h
int 13h
ret
convert_LBA: ; Converts LBA to CHS tuple ready for int 13h call
push bx
push ax
mov bx, ax ; Save logical sector
mov dx, 0 ; First the sector
div word [sptrk]
add dl, 01h ; Physical sectors start at 1
mov cl, dl ; Sectors belong in CL for int 13h
mov ax, bx
mov dx, 0 ; Now calculate the head
div word [sptrk]
mov dx, 0
div word [nhead]
mov dh, dl ; Head/side
mov ch, al ; Track
pop ax
pop bx
ret
non_sys_disk db 'Non system disk or disk error!', 0
filename db 'AC-DOS SYS'
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
buffer: