You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
10 KiB

; loader.asm
PartEntry STRUC
Bootable db ? ;80h = bootable, 00h = nonbootable
BeginHead db ? ;beginning head
BeginSector db ? ;beginning sector
BeginCylinder db ? ;beginning cylinder
FileSystem db ? ;name of file system
EndHead db ? ;ending head
EndSector db ? ;ending sector
EndCylinder db ? ;ending cylinder
StartSector dd ? ;starting sector (relative to beg. of disk)
PartSectors dd ? ;number of sectors in partition
PartEntry ENDS
BootSector STRUC
bsJump db 0EBh, (extra - bsJump), 090h
; E9 XX XX or EB xx 90
OemName db 8 dup (?) ; OEM name and version
; start of BIOS parameter block
BytesPerSec dw ? ; bytes per sector
SecPerClust db ? ; sectors per cluster
ResSectors dw ? ; number of reserved sectors
FATs db ? ; number of FATs
RootDirEnts dw ? ; number of root directory entries
Sectors dw ? ; total number of sectors (see HugeSectors)
Media db ? ; media descriptor byte (0f0h for floppies)
FATsecs dw ? ; number of sectors per FAT
SecPerTrack dw ? ; sectors per track
Heads dw ? ; number of heads
HiddenSecs dd ? ; number of hidden sectors
HugeSectors dd ? ; number of sectors if Sectors equals 0
; end of BIOS parameter block
DriveNumber db ? ;
Reserved1 db ? ;
BootSignature db ? ;
VolumeID dd ? ;
VolumeLabel db 11 dup (?)
FileSysType db 8 dup (?)
extra dw ?
BootSector ENDS
DirEntry STRUC
FileName db '????????' ;name
Extension db '???' ;extension
Attributes db ? ;attributes
Reserved db 10 dup (?) ;reserved
Time dw ? ;time stamp
Date dw ? ;date stamp
StartCluster dw ? ;starting cluster
FileSize dd ? ;file size
DirEntry ENDS
yonder segment para public use16 at 2000h
org 0h
destination proc far
destination endp
yonder ends
code segment para public use16 '_CODE'
assume cs:code, ds:code, es:code, ss:code
org 7c00h
main PROC
Boot bootsector < ,'BEROSET ',512,1,1,2,224,2880,0f0h,9,18,2,\
0,0,0,0,29h,02a04063ch,'BEROSET 001',\
'FAT12 ',07df1h>
mov ax,cs ;
mov ss,ax ; point ss:sp to CS:7c00h
mov sp,7c00h ; which sets up a stack in first 64K
mov ds,ax
mov es,ax
; CalcClustOff - calculates the starting logical sector number of
; cluster 0, which isn't really a cluster, but the
; number returned is useful for calculations converting
; cluster number to logical sector
; INPUT: ResSectors, FATsecs, FATs
; OUTPUT: dx:ax contains the starting logical sector number
CalcClustOff PROC
xor dh,dh
mov ax,[Boot.FatSecs]
mov dl,[Boot.FATs]
mul dx
add ax,[Boot.ResSectors]
adc dx,0
; now dx:ax = FATs * FATsecs + ResSectors
mov word ptr [ClustOffs],ax
mov word ptr [ClustOffs+2],dx
mov dx,20h ; bytes per dir entry
mov ax,[Boot.RootDirEnts]
mul dx ; multiply 'em out
div word ptr [Boot.BytesPerSec] ; and divide by bytes/sec
add word ptr [ClustOffs],ax
adc word ptr [ClustOffs+2],dx ; create the aggregate
mov al,[Boot.SecPerClust] ;
xor ah,ah ;
shl ax,1 ; AX = SecPerClust * 2
sub word ptr [ClustOffs],ax ;
sbb word ptr [ClustOffs+2],0 ; propagate carry flag
; mov ax,word ptr [ClustOffs] ;
; mov dx,word ptr [ClustOffs+2] ;
; ret
CalcClustOff ENDP
; mov WORD ptr [ClustOffs],ax
; mov WORD ptr [ClustOffs+2],dx
mov bx,offset Boot
call CalcClust2 C, \
WORD ptr [(BootSector PTR bx).ResSectors], \
WORD ptr [(BootSector PTR bx).FATsecs], \
WORD ptr [(BootSector PTR bx).FATs]
; now dx:ax contains the logical sector for cluster 2
call LsectToGeom C, \
WORD ptr [(BootSector PTR bx).HiddenSecs] , \
WORD ptr [((BootSector PTR bx).HiddenSecs)+2],\
[(BootSector PTR bx).Heads], \
[(BootSector PTR bx).SecPerTrack]
mov dl,[(BootSector PTR bx).DriveNumber]
mov bx,offset buff
mov al,[(BootSector PTR MBR).SecPerClust]
mov ah,2h ; get ready to read
int 13h
jc retry1
; now find our desired filename within buffer (which has the root dir)
call FindFile C, \
bx, 200h * 40h, offset BootFileName
xor dh,dh
mov dl,[(BootSector PTR MBR).SecPerClust]
mov si,ax
mov ax,[(DirEntry PTR si).StartCluster]
mul dx
add ax,WORD ptr [ClustOffs]
adc dx,WORD ptr [ClustOffs+2]
; now dx:ax contains logical sector number for start of file
call LsectToGeom C, \
WORD ptr [(BootSector PTR MBR).HiddenSecs] , \
WORD ptr [((BootSector PTR MBR).HiddenSecs)+2],\
[(BootSector PTR MBR).Heads], \
[(BootSector PTR MBR).SecPerTrack]
mov si,offset Boot
mov dl,[(BootSector PTR si).DriveNumber]
mov ah,2h
; read in a cluster's worth of data
mov al,[(BootSector PTR si).SecPerClust]
; point to our magic location
mov bx,seg destination
mov es,bx
mov bx,offset destination
int 13h
jc retry2
jmp destination
ENDP main
; LsectToGeom - converts from logical sector number to the physical
; geometry (head, cylinder, track) in the form required
; by the BIOS (Int 13h) disk read and write calls.
; INPUT: dx:ax=lsect, HiddenSecs, Heads, SecPerTrack
; OUTPUT: cx, dx are set with cylinder/track, and head respectively
LsectToGeom PROC C lHiddenSecs:DWORD, \
lHeads:WORD, lSecPerTrack:WORD, buffer:DWORD
USES ax ;save registers we'll use
stc ;add one additional
adc ax, WORD ptr [lHiddenSecs] ;add starting sector
adc dx, WORD ptr [lHiddenSecs+2] ;
div [lSecPerTrack] ;
mov cl,dl ;store sector in cl
xor dx,dx ;
div [lHeads] ;
mov dh,dl ;store head in dh
mov ch,al ;store low 8 bits of cylinder in ch
shr ax,1 ;
shr ax,1 ;
and al,0c0h ;pass through two hi bits only
or cl,ah ;mov bits into location
ret ;
LsectToGeom ENDP
; CalcClust2 - calculates the starting logical sector number of
; cluster 2, (the beginning of data space for
; partitions).
; INPUT: ResSectors, FATsecs, FATs
; OUTPUT: dx:ax contains the starting logical sector number
CalcClust2 PROC C cResSectors:WORD, cFATsecs:WORD, cFATs:BYTE
xor dx,dx ;
mov ax,[cFATsecs] ;
mul [cFATs] ;
add ax,[cResSectors] ;
adc dx,0 ;
CalcClust2 ENDP
; FindFile - given a memory buffer containing the directory data
; and a static file name for which to search, this routine
; finds the file and returns a pointer to its directory
; entry in ds:si
; INPUT: dirbuffer, filespec
; OUTPUT: ax contains pointer to directory entry (or NULL)
FindFile PROC C dirbuffer:WORD, limit:WORD, filespec:WORD
USES cx, dx, di, si, es
mov cx,ds ;
mov es,cx ; es and ds point to same segment
cld ; always count forward
mov ax,[dirbuffer] ; load 'em up
add [limit],ax
mov dx,[filespec] ;
mov cx,11 ; size of dos filename (8.3)
mov si,dx ;
mov di,ax ;
repe cmpsb ; compare 'em
jz foundit ;
add ax,20h ; size of directory entry
cmp ax,[limit]
jb keepsearching
xor ax,ax
FindFile ENDP
BootFileName db "BEROSET SYS" ;the boot loader for this OS
; MBR db 0200h DUP (?)
buff db 0200h * 40h DUP (?)
ClustOffs dd ?
org 7dfeh
dw 0AA55h ; signature byte
code ends