EttinOS/src/BOOT.ASM

289 lines
5.1 KiB
NASM

cpu 8086
org 0x7c00
;Jump to the code
jmp start
;Padding
nop
;OEM label
db "ETTINOS "
%ifdef F1440
;1.44 MB 3.5" floppy disk BPB (enable with the argument -d F1440)
sectorsize dw 0x200 ;bytes
clustersize db 0x1 ;sectors
reservedsectors dw 0x1
fats db 0x2
rootentries dw 0xe0
logicalsectors dw 0xb40
mediadescriptor db 0xf0
sectorsperfat dw 0x9
sectorspertrack dw 0x12
heads dw 0x2
%else
;360 KiB 5.25" floppy disk BPB (default)
sectorsize dw 0x200 ;bytes
clustersize db 0x2 ;sectors
reservedsectors dw 0x1
fats db 0x2
rootentries dw 0x70
logicalsectors dw 0x2d0
mediadescriptor db 0xfd
sectorsperfat dw 0x2
sectorspertrack dw 0x9
heads dw 0x2
%endif
;Setup
;Set the segments
start:
mov ax, 0x0
mov ds, ax
mov ss, ax
mov es, ax
;Set the stack
cli
mov sp, 0x0
sti
;Store the boot drive number
mov [drive], dl
;Calculate and store variables not found in the BPB
;Start of the root
mov ah, 0x0
mov al, [fats]
mul word [sectorsperfat]
add ax, [reservedsectors]
mov [rootstart], ax
;Size of the root in sectors
mov ax, [rootentries]
mov dx, 0x20
mul dx
mov dx, 0x0
div word [sectorsize]
mov [rootsectors], ax
;Start of data
add ax, [rootstart]
mov [datastart], ax
;Load the root
;Set the source
mov ax, [rootstart]
;Set the destination
mov si, buffer
mov bx, si
;Set the size
mov cx, [rootsectors]
;Store the source and the loop counter in the stack
loadrootsector:
push ax
push cx
;Set the source
call calcsource
;Set the size
mov al, 0x1
;Load a sector
mov ah, 0x2
int 0x13
;Load the loop counter and the source from the stack
pop cx
pop ax
;Set the next sector
add ax, 0x1
add bx, word [sectorsize]
;Load the next sector
loop loadrootsector
;Search the root for the system entry
;Set DI to the root
mov di, buffer
;Set the number of root entries
mov cx, word [rootentries]
;Set the entry pointer
mov ax, 0x0
;Store the loop counter in the stack
search:
push cx
;Check for the system entry
mov si, file
mov cx, 0xb
rep cmpsb
je loadfat
;Set DI at the next entry
add ax, 0x20
mov di, buffer
add di, ax
;Load the loop counter from the stack
pop cx
;Search the next entry
loop search
;Print an error message and hang if the system is not found
;Set SI at the file error message
mov si, filerrormsg
;Load a character
printstr:
lodsb
;Check for the string end
cmp al, 0x0
je $
;Print the character
mov ah, 0xe
int 0x10
;Print the next character
jmp printstr
;Load the FAT
;Load CX from the stack
loadfat:
pop cx
;Store the address of the first cluster
mov ax, [di + 0xf]
mov [cluster], ax
;Set the source
mov ax, [reservedsectors]
call calcsource
;Set the destination
mov bx, buffer
;Set the size
mov ax, [sectorsperfat]
;Load the FAT
mov ah, 0x2
int 0x13
;Load a cluster
loadcluster:
;Set the source
mov ax, word [cluster]
sub ax, 0x2
mul byte [clustersize]
add ax, [datastart]
;Set the destination
mov bx, word [pointer]
;Set the size
mov ch, 0x0
mov cl, byte [clustersize]
;Store the loop counter in the stack
loadclustersector:
push cx
;Set the source
call calcsource
;Set the size
push ax
mov al, 0x1
;Load a sector
mov ah, 0x2
int 0x13
pop ax
;Set the next sector
add ax, 0x1
add bx, [sectorsize]
;Load the loop counter from the stack
pop cx
;Load the next sector
loop loadclustersector
;Calculate the next cluster
;Check if the cluster is even or odd
mov ax, [cluster]
mov dx, 0x0
mov bx, 0x3
mul bx
mov bx, 0x2
div bx
mov si, buffer
add si, ax
mov ax, word [si]
or dx, dx
jz even
;If the cluster is odd shift out the first four bits
times 0x4 shr ax, 0x1
jmp contcalc
;If the cluster is even mask out the final four bits
even:
and ax, 0xfff
contcalc:
;Check for the file end
cmp ax, 0xff8
jge boot
;Store the address of the next cluster
mov word [cluster], ax
;Set the destination of the next cluster
mov ax, [sectorsize]
mul word [clustersize]
add word [pointer], ax
;Load the next cluster
jmp loadcluster
;Boot the system
;Pass the boot drive number to the system
boot:
mov dl, byte [drive]
;Boot the system
jmp 0x0:0x500
;Data
drive db 0x0
rootstart dw 0x0
rootsectors dw 0x0
datastart dw 0x0
file db "SYSTEM BIN"
filerrormsg db "System not found", 0xd, 0xa, 0x0
cluster dw 0x0
pointer dw 0x500
;***
;Calculate the source arguments for loading data from the disk
calcsource:
;Store AX and BX in the stack
push ax
push bx
;Calculate the cylinder, head, and sector
;Store the logical sector in BX
mov bx, ax
;Calculate the sector
mov dx, 0x0
div word [sectorspertrack]
add dl, 0x1
mov cl, dl
;Load the logical sector from BX
mov ax, bx
;Calculate the head and cylinder
mov dx, 0x0
div word [sectorspertrack]
mov dx, 0x0
div word [heads]
mov dh, dl ;Head
mov ch, al ;Cylinder
;Load the boot drive number
mov dl, byte [drive]
;Load BX and AX from the stack
pop bx
pop ax
;Return
ret
;***
;Padding
times 0x1fe-($-$$) db 0x0
;Boot signature
dw 0xaa55
;File system buffer
buffer: