mirror of https://github.com/AR1972/DOS3.3
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
767 lines
25 KiB
767 lines
25 KiB
title Non-Contiguous BIOS Loader (MSLOAD)
|
|
|
|
IF1
|
|
%OUT ASSEMBLING: Non-Contiguous BIOS Loader (MSLOAD)
|
|
%OUT
|
|
ENDIF
|
|
|
|
bootseg segment at 0h
|
|
org 7C00h
|
|
Boot_Sector label byte
|
|
org 7D00h
|
|
Relocate_Start label byte
|
|
bootseg ends
|
|
|
|
|
|
dosseg segment at 70h
|
|
org 00h
|
|
BIOS_Address label byte
|
|
|
|
dosseg ends
|
|
|
|
|
|
cseg segment public para 'code'
|
|
assume cs:cseg,ds:cseg,es:cseg,ss:cseg
|
|
|
|
|
|
|
|
include msload.inc
|
|
|
|
org 0h
|
|
|
|
start:
|
|
|
|
subttl Setup Stack
|
|
page
|
|
;***********************************************************************
|
|
; Setup_Stack
|
|
;***********************************************************************
|
|
;
|
|
; Input: none
|
|
;
|
|
; Output:
|
|
;
|
|
; SS:SP = 0:7C00h
|
|
; AX destroyed
|
|
;-----------------------------------------------------------------------
|
|
; First thing is to reset the stack to a better and more known place.
|
|
;
|
|
; Move the stack to just under the boot record and relocation area (0:7C00h)
|
|
;
|
|
; Preserve all other registers
|
|
;----------------------------------------------------------------------
|
|
|
|
CLI ;Stop interrupts till stack ok
|
|
XOR AX,AX
|
|
MOV SS,AX ;Work in stack just below this routine
|
|
MOV SP,7C00h - 30 ;Leave room for stack frame
|
|
MOV BP,7C00h - 30 ;Point BP as stack index pointer
|
|
STI
|
|
|
|
|
|
subttl Save Input Values
|
|
page
|
|
;***********************************************************************
|
|
; Save_Input_Values
|
|
;***********************************************************************
|
|
;
|
|
; Input: none
|
|
;
|
|
; DL = INT 13 drive number we booted from
|
|
; CH = media byte
|
|
; BX = First data sector on disk (0-based)
|
|
;
|
|
; Output:
|
|
;
|
|
; BX = first data sector on disk
|
|
; CL = number of floppies including fake one
|
|
; CH = media byte
|
|
;
|
|
; [bp].Media_Byte = input CH
|
|
; [bp].Drive_Number = input DL
|
|
; [bp].First_Sector = input BX
|
|
; [bp].Drive_Boot = output AX
|
|
; [bp].Number_Floppy = output CL
|
|
; [bp].Number_Sectors = Sectors/track
|
|
; [bp].Number_Heads = heads/cylinder
|
|
;
|
|
; DS = 0
|
|
; AX,DX,SI destroyed
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
; Save input information
|
|
;
|
|
; Get Equipment Flag
|
|
;
|
|
; Find how many drives on system
|
|
;
|
|
; Figure out boot drive
|
|
;
|
|
;----------------------------------------------------------------------
|
|
Save_Input_Values:
|
|
mov [bp].First_Sector,bx
|
|
mov [bp].media_Byte,ch
|
|
mov [bp].Drive_Number,dl
|
|
; INT 11h ;GET EQUIPMENT STATUS
|
|
; ROL AL,1 ;Put bits 6 & 7 into bits 0 & 1
|
|
; ROL AL,1
|
|
; AND AX,3 ;Only look at bits 0 & 1
|
|
; JNZ NOTsingle ;Zero means single drive system
|
|
; INC AX ;Pretend it's a two drive system
|
|
NOTSingle:
|
|
; INC AX ;AX has number of drives, 2-4
|
|
;Is also 0 indexed boot drive if we
|
|
; booted off hard file
|
|
; MOV CL,AL ;CH is FAT ID, CL # floppies
|
|
; TEST DL,80H ;BOOT FROM FLOPPY ?
|
|
; JNZ GOTHRD ;NO.
|
|
; XOR AX,AX ;INDICATE BOOT FROM DRIVE A
|
|
GotHrd:
|
|
xor ax,ax ;Segment 0
|
|
mov ds,ax
|
|
|
|
assume ds:Bootseg
|
|
|
|
mov ax,Boot_Sector.SECLIM ;Get Sectors per track
|
|
mov [bp].Sectors_Per_Track,ax
|
|
mov ax,Boot_Sector.HDLIM ;Get BPB heads per cylinder
|
|
mov [bp].Number_Of_Heads,ax
|
|
mov ax,Boot_Sector.cSecFat ;Get sectors per FAT
|
|
mov [bp].Number_Of_FAT_Sectors,ax
|
|
mov ax,Boot_Sector.cSecHid ;Get hidden sectors
|
|
mov [bp].Hidden_Sectors,ax
|
|
mov ax,Boot_Sector.cSecRes ;Get Reserved Sectors
|
|
mov [bp].Reserved_Sectors,ax
|
|
|
|
|
|
subttl Find_Cluster_Size
|
|
page
|
|
;***********************************************************************
|
|
; Find_Cluster_Size
|
|
;***********************************************************************
|
|
;
|
|
; Input: BPB information in loaded boot record at 0:7C00h
|
|
;
|
|
; Output:
|
|
;
|
|
; DS = 0
|
|
; AX = Bytes/Cluster
|
|
; BX = Sectors/Cluster
|
|
; SI destroyed
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Get Bytes/sector from BPB
|
|
;
|
|
; Get sectors/cluster from BPB
|
|
;
|
|
; Bytes/cluster = Bytes/sector * sector/cluster
|
|
;----------------------------------------------------------------------
|
|
Find_Cluster_Size:
|
|
|
|
;For the time being just assume the boot record is valid and the BPB
|
|
;is there.
|
|
|
|
xor ax,ax ;Segment 0
|
|
mov ds,ax
|
|
|
|
assume ds:bootseg
|
|
|
|
mov ax,Boot_Sector.ByteSec ;Get BPB bytes/sector
|
|
xor bx,bx
|
|
mov bl,Boot_Sector.cAlloc ;Get sectors/cluster
|
|
mul bx ;Bytes/cluster
|
|
mov [bp].Size_Cluster,ax ;Save it
|
|
|
|
|
|
|
|
subttl Determine FAT size
|
|
page
|
|
;***********************************************************************
|
|
; Determine_FAT_Size
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Determine if FAT is 12 or 16 bit FAT. 12 bit FAT if floppy, read MBR
|
|
; to find out what system id byte is.
|
|
;
|
|
; Input: [bp].Media_Byte = FAT ID Byte
|
|
;
|
|
; Output:
|
|
;
|
|
; [BP].Fat_Size = FAT12_bit or FAT16_bit
|
|
; ES = 0
|
|
; All other registers destroyed
|
|
;
|
|
; Calls: READ_DISK
|
|
;-----------------------------------------------------------------------
|
|
;IF (not FAT ID of F8)
|
|
; {12 bit FAT}
|
|
;ELSE
|
|
; {
|
|
; Read in master boot record at 0:7C00h
|
|
;
|
|
; Scan system id bytes for 1 or 4
|
|
;
|
|
; IF (Sys id = 4)
|
|
; {16 bit FAT}
|
|
; ELSE
|
|
; {IF (Sys id = 1)
|
|
; {12 bit FAT}
|
|
; ELSE
|
|
; {Error}
|
|
; ENDIF
|
|
; ENDIF
|
|
; ENDIF
|
|
;
|
|
;----------------------------------------------------------------------
|
|
Determine_FAT_Size:
|
|
mov [bp].FAT_Size,FAT12_bit ;Assume 12 bit fat
|
|
cmp [bp].Media_Byte,0F8h ;Is it floppy
|
|
jne FAT_Size_Found ;Yep, all set
|
|
mov [bp].Logical_Sector,0 ;Got hardfile, go get MBR
|
|
xor ax,ax
|
|
mov es,ax
|
|
mov di,offset Relocate_Start
|
|
mov [bp].Sector_Count,1
|
|
call Disk_Read
|
|
mov si,offset Relocate_Start+1C2h
|
|
mov cx,4
|
|
xor ax,ax
|
|
mov ds,ax
|
|
Find_Sys_Id:
|
|
mov [bp].FAT_Size,FAT12_bit ;Assume 12 bit fat
|
|
cmp byte ptr [si],1
|
|
je FAT_Size_Found
|
|
mov [bp].FAT_Size,FAT16_bit ;Assume 12 bit fat
|
|
cmp byte ptr [si],4
|
|
je Fat_Size_Found
|
|
add si,16
|
|
loop Find_Sys_Id
|
|
;xxxxxxxxxxxxxxxxxxxxxxxxxx error
|
|
FAT_Size_Found:
|
|
|
|
|
|
subttl Determine First Cluster
|
|
page
|
|
;***********************************************************************
|
|
; Determine_First_Cluster
|
|
;***********************************************************************
|
|
;
|
|
; Notes: Find the last cluster that was loaded
|
|
;
|
|
;
|
|
; Input:
|
|
;
|
|
; [BP].Size_Cluster
|
|
; Total_Length is offset of end of MSLOAD
|
|
;
|
|
; Output:
|
|
;
|
|
; [BP].Last_Found_Cluster = the last cluster loaded containing MSLOAD
|
|
; code. This is also the number of clusters
|
|
; with MSLOAD code +2
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
;Get length of loader portion of bios
|
|
;
|
|
;Divide by bytes/cluster
|
|
;
|
|
;If (Remainder = 0)
|
|
; {Last_Used_Cluster = quotient+2}
|
|
;Else
|
|
; {Last_Used_Cluster = quotient+3}
|
|
;----------------------------------------------------------------------
|
|
Determine_First_Cluster:
|
|
mov [bp].Last_Found_Cluster,1 ;2 is the first cluster-1
|
|
mov ax,offset Total_Length ;Get whole length
|
|
xor dx,dx
|
|
div [bp].Size_Cluster ;Div by bytes/sector
|
|
add [bp].Last_Found_Cluster,ax ;Save the result
|
|
cmp dx,0 ;Was there remainder?
|
|
je First_Cluster_Found ;No
|
|
inc [bp].Last_Found_Cluster ;Yes, round up
|
|
|
|
First_Cluster_Found:
|
|
|
|
|
|
subttl Relocate
|
|
page
|
|
;
|
|
;***********************************************************************
|
|
; RELOCATE
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Relocate the loader code to 0:7C00 - this will allow bios to be loaded
|
|
; underneath at 70:0
|
|
;
|
|
; Input: none
|
|
;
|
|
; Output: es is set to 0
|
|
; ds is set to cs (70h)
|
|
; ax,cx,si,di destroyed
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
; Copy code from Relocate_Code to Relocate_Start (7C00h)
|
|
;
|
|
; The length to copy is Relocate_Length
|
|
;
|
|
; Jump to relocated code
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
Relocate:
|
|
push cs ;Set up ds segreg
|
|
pop ds
|
|
xor ax,ax ;Set up ES segreg
|
|
mov es,ax
|
|
|
|
assume es:bootseg,ds:cseg
|
|
|
|
mov si,offset Relocate_Code ;Source
|
|
mov di,offset Relocate_Start ;Target
|
|
mov cx,Relocate_Length ;Length
|
|
rep movsb ;Go do it
|
|
|
|
jmp far ptr Relocate_Start
|
|
|
|
;
|
|
;*************************************************************************
|
|
;* RELOCATED CODE ********************************************************
|
|
;*************************************************************************
|
|
;
|
|
|
|
Relocate_Code label byte
|
|
|
|
subttl Read In FAT
|
|
page
|
|
;***********************************************************************
|
|
; Read_In_FAT
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Reads in the entire FAT at 0:8000. This gives the relocated portion
|
|
; of this loader a maximum size of 1024 bytes (8000 - 7C00). The max
|
|
; size of the FAT is 64 sectors (32k) so everything will fit under the
|
|
; 64k DMA boundary, so no problems with loading.
|
|
;
|
|
; Input: none
|
|
;
|
|
; Output:
|
|
;
|
|
; ES = 0
|
|
; All sectors destroyed
|
|
;
|
|
; Calls: READ DISK
|
|
;-----------------------------------------------------------------------
|
|
; Get number of sectors in FAT
|
|
;
|
|
; Set ES:DI to 0:8000h
|
|
;
|
|
; Read in the sectors
|
|
;
|
|
;----------------------------------------------------------------------
|
|
Read_In_FAT:
|
|
xor ax,ax
|
|
mov ds,ax
|
|
|
|
assume ds:bootseg
|
|
|
|
mov ax,[bp].Number_Of_FAT_Sectors ;Get sectors/FAT
|
|
mov [bp].Sector_Count,ax ;Number of sectors to read
|
|
mov ax,[bp].Hidden_Sectors ;Hidden+Reserved = Fat
|
|
add ax,[bp].Reserved_Sectors
|
|
mov [bp].Logical_Sector,ax ;Save it, setup for read
|
|
xor ax,ax
|
|
mov es,ax
|
|
mov di,8000h ;Point to buffer
|
|
call Disk_Read
|
|
|
|
subttl Keep Loaded BIO
|
|
page
|
|
;***********************************************************************
|
|
; KEEP LOADED BIO
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Determine how much of bios was loaded in when the loader was loaded
|
|
; by the boot record (only the portion that is guaranteed to be
|
|
; contiguous
|
|
;
|
|
; Input:
|
|
;
|
|
; [BP].Last_Found_Cluster = number of clusters used for loader+2
|
|
;
|
|
; Output:
|
|
; ES = DS = 70h
|
|
; DI = Next offset to load bios code
|
|
; AX,BX,CX,DX,SI destroyed
|
|
;
|
|
; [bp].Next_BIO_Location = DI on output
|
|
; [bp].Last_Cluster = last cluster loaded
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
;Number of clusters loaded+2 is in [BP].Last_Found_Cluster
|
|
;
|
|
;Multiply cluster * cluster size in bytes to get total loaded for MSLOAD
|
|
;
|
|
;Subtract TOTAL_LOADED - LOADBIO_SIZE to get loaded bios in last cluster
|
|
;
|
|
;Relocate this piece of bios down to 70:0
|
|
;
|
|
;----------------------------------------------------------------------
|
|
Keep_Loaded_BIO:
|
|
push ds
|
|
mov ax,[bp].Last_Found_Cluster ;Point to last cluster loaded
|
|
sub ax,1 ;Get number of clusters loaded
|
|
mul [bp].Size_Cluster ;Get total bytes loaded by
|
|
;This is always < 64k, so
|
|
;lower 16 bits ok
|
|
sub ax,LoadBio_Size ;Get portion of bios loaded
|
|
mov cx,ax ;Save length to move
|
|
mov ax,70h ;Segment at 70h
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov si,offset cs:Total_Length ;Point at bios
|
|
mov di,0 ;Point at 70:0
|
|
rep movsb ;Relocate this code
|
|
mov [bp].Next_Bio_Location,di ;Save where to load next
|
|
pop ds
|
|
|
|
subttl Get Contiguous Clusters
|
|
page
|
|
;***********************************************************************
|
|
; Get_Contiguous_Clusters
|
|
;***********************************************************************
|
|
;
|
|
; Notes: Go find clusters as long as they are contiguous
|
|
;
|
|
;
|
|
; Input:
|
|
;
|
|
; [BP].Next_BIO_Location
|
|
; [BP].
|
|
;
|
|
;
|
|
; Output:
|
|
;
|
|
;
|
|
; Calls: Get_Next_FAT_Entry
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
;Set [BP].Sector_Count to Sectors per cluster
|
|
;
|
|
;Call Get_Next_FAT_Entry to get next cluster in file
|
|
;
|
|
;Call Check_for_EOF
|
|
;
|
|
;IF (NC returned)
|
|
;
|
|
; {Call Get_Next_FAT_Entry
|
|
;
|
|
; IF (New cluster is contig to old cluster)
|
|
; {Add sectors per cluster to [BP].Sector_Count
|
|
;
|
|
; Call Check_For_EOF
|
|
;
|
|
; IF (NC returned)
|
|
;
|
|
;
|
|
;----------------------------------------------------------------------
|
|
Get_Contiguous_Cluster:
|
|
xor ah,ah
|
|
mov al,Boot_Sector.cAlloc ;Assume we will get one cluster
|
|
mov [bp].Sector_Count,ax
|
|
call Get_Next_Fat_Entry ;Go get it
|
|
mov [bp].Last_Found_Cluster,ax ;Update the last one found
|
|
cmp [bp].EOF,End_Of_File
|
|
je GOTO_bios
|
|
|
|
Got_Contig_Clusters:
|
|
sub ax,2 ;Zero base the cluster
|
|
xor ch,ch
|
|
mov cl,Boot_Sector.cAlloc ;Get sectors per cluster
|
|
mul cx ;Get how many
|
|
add ax,[bp].First_Sector ;See where the data sector starts
|
|
mov [bp].Logical_Sector,ax ;Save it
|
|
mov di,[bp].Next_Bio_Location ;Get where to put code
|
|
push [bp].Sector_Count ;Save how many sectors
|
|
mov ax,dosseg ;Get area to load code
|
|
mov es,ax
|
|
call Disk_Read
|
|
pop ax ;Get back total sectors read in
|
|
; jc ##########
|
|
mul Boot_Sector.ByteSec ;Get number of bytes we loaded
|
|
add [bp].Next_Bio_Location,ax ;Point to where to load next
|
|
jmp short Get_Contiguous_Cluster
|
|
|
|
subttl GOTO bios
|
|
page
|
|
;***********************************************************************
|
|
; GOTO_bios
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Set up required registers for bios, then jump to it (70:0)
|
|
;
|
|
; Input: none
|
|
;
|
|
; [bp].Media_Byte = media byte
|
|
; [bp].Drive_Number = INT 13 drive number we booted from
|
|
; [bp].First_Sector = First data sector on disk (0-based)
|
|
;
|
|
; Output:
|
|
;
|
|
; Required by MSINIT
|
|
; DL = INT 13 drive number we booted from
|
|
; CH = media byte
|
|
; BX = First data sector on disk (0-based)
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
;
|
|
; Set up registers for MSINIT then do Far Jmp
|
|
;
|
|
;----------------------------------------------------------------------
|
|
GOTO_bios:
|
|
mov ch,[bp].Media_Byte ;Restore regs required for MSINT
|
|
mov dl,[bp].Drive_Number
|
|
mov bx,[bp].First_Sector
|
|
jmp far ptr bios_Address
|
|
|
|
|
|
|
|
|
|
subttl Disk Read
|
|
page
|
|
;***********************************************************************
|
|
; Disk_Read
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Read in the [BP].Sector_Count number of sectors at ES:DI
|
|
;
|
|
;
|
|
; Input: none
|
|
;
|
|
; DI = Offset of start of read
|
|
; ES = Segment of read
|
|
; [bp].Sector_Count = number of sectors to read
|
|
; [bp].Logical_sector = starting sector
|
|
; Following is BPB info that must be setup prior to call
|
|
; [bp].Number_Of_Heads
|
|
; [bp].Number_Of_Sectors
|
|
; [bp].Drive_Number
|
|
; [bp].Sectors_Per_Track
|
|
;
|
|
; Output:
|
|
;
|
|
; ES = 0
|
|
; AX,BX,CX,DX,SI,DI destroyed
|
|
;
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
; Divide start sector by sectors per track
|
|
; The remainder is the actual sector number, 0 based
|
|
;
|
|
; Increment actual sector number to get 1 based
|
|
;
|
|
; The quotient is the number of tracks - divide by heads to get the cyl
|
|
;
|
|
; The remainder is actual head, the quotient is cylinder
|
|
;
|
|
; Figure the number of sectors in that track, set AL to this
|
|
;
|
|
; Do the read
|
|
;
|
|
; If Error, Do RESET, then redo the INT 13h
|
|
;
|
|
; If successful read, Subtract # sectors read from Sector_Count, Add to
|
|
; Logical Sector, add #sectors read * Sector_Size to BX;
|
|
;
|
|
; If Sector_Count <> 0 Do next read
|
|
;----------------------------------------------------------------------
|
|
Disk_Read:
|
|
|
|
;
|
|
; convert a logical sector into Track/sector/head. AX has the logical
|
|
; sector number
|
|
;
|
|
DODIV:
|
|
MOV cx,5 ;5 retries
|
|
|
|
Try_Read:
|
|
PUSH cx ;Save it
|
|
|
|
MOV AX,[bp].Logical_Sector ;Get starting sector
|
|
XOR DX,DX
|
|
DIV word ptr [bp].Sectors_Per_Track
|
|
MOV bx,[bp].Sectors_Per_Track ;Get number of sectors we can
|
|
sub bx,dx ;read in this track
|
|
mov si,bx
|
|
cmp [bp].Sector_Count,si ;Is possible sectors in track more
|
|
jae Got_Length ;than what we need to read?
|
|
mov si,[bp].Sector_Count ;Yes, only read what we need to
|
|
|
|
Got_Length:
|
|
INC DL ; sector numbers are 1-based
|
|
MOV bl,dl ;Start sector in DL
|
|
XOR DX,DX
|
|
DIV word ptr [bp].Number_Of_Heads ;Start cyl in ax,head in DL
|
|
MOV DH,DL
|
|
;
|
|
; Issue one read request. ES:BX have the transfer address, AL is the number
|
|
; of sectors.
|
|
;
|
|
;
|
|
; Now convert to standard ROM call
|
|
;
|
|
mov cl,bl ;Get starting sector
|
|
ror ah,1 ;Set up high 2 bits
|
|
ror ah,1 ;Set up high 2 bits
|
|
or cl,ah ;Combine cyl/start sector
|
|
mov ch,al ;Set low order of cyl
|
|
mov bx,di ;Set offset
|
|
mov dl,[bp].Drive_Number ;Set drive
|
|
mov ax,si ;Set count
|
|
mov ah,02 ;Read Command
|
|
push ax ;Save regs
|
|
push di ; *
|
|
int 13h ;Call ROM-Bios
|
|
pop di ;Restore Regs
|
|
pop ax ; *
|
|
pop cx ;Get retry count back
|
|
jnc Read_OK
|
|
push cx
|
|
mov bx,di ;
|
|
push di ;Save Reg
|
|
mov dl,[bp].Drive_Number ;Set drive
|
|
mov ah,0 ;RESET Disk Command
|
|
int 13h ;Call ROM-Bios
|
|
pop di ;Restore Reg
|
|
pop cx
|
|
loop Try_Read
|
|
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx error
|
|
Read_OK:
|
|
xor ah,ah ;Mask out command, just get # read
|
|
sub [bp].Sector_Count,ax ;Bump number down
|
|
jz Read_Finished
|
|
add [bp].Logical_Sector,ax ;Where to start next time
|
|
xor bx,bx ;Get number sectors read
|
|
mov bl,al
|
|
mov ax,Boot_Sector.ByteSec ;Bytes per sector
|
|
mul bx ;Get total bytes read
|
|
add di,ax ;Add it to offset
|
|
jmp short DODIV
|
|
Read_Finished:
|
|
RET
|
|
|
|
subttl GET NEXT FAT ENTRY
|
|
page
|
|
;***********************************************************************
|
|
; GET_NEXT_FAT_ENTRY
|
|
;***********************************************************************
|
|
;
|
|
; Notes:
|
|
;
|
|
; Given the last cluster found, this will return the next cluster of
|
|
; bios. If the last cluster is (F)FF8 - (F)FFF, then the final cluster
|
|
; of bios has been loaded, and control is passed to GOTO_bios
|
|
;
|
|
; Input:
|
|
;
|
|
; [bp].Last_Found_Cluster
|
|
; [bp].Fat_Size
|
|
;
|
|
; Output:
|
|
;
|
|
; [bp].Last_Found_Cluster (updated)
|
|
;
|
|
; Calls: none
|
|
;-----------------------------------------------------------------------
|
|
; Get Last_Found_Cluster
|
|
;
|
|
; IF (16 bit FAT)
|
|
; {IF (Last_Found_Cluster = FFF8 - FFFF)
|
|
; {JMP GOTO_bios}
|
|
; ELSE
|
|
; {Get offset by multiply cluster by 2}
|
|
;
|
|
; ELSE
|
|
; {IF (Last_Found_Cluster = FF8 - FFF)
|
|
; {JMP GOTO_bios}
|
|
; ELSE
|
|
; {Get offset by - multiply cluster by 3
|
|
;
|
|
; Rotate right to divide by 2
|
|
;
|
|
; IF (CY set - means odd number)
|
|
; {SHR 4 times to keep high twelve bits}
|
|
;
|
|
; ELSE
|
|
; {AND with 0FFFh to keep low 12 bits}
|
|
; }
|
|
; }
|
|
;
|
|
; Add in 8000h to get offset of next cluster in FAT buffer
|
|
;
|
|
;----------------------------------------------------------------------
|
|
Get_Next_FAT_Entry:
|
|
|
|
mov [bp].EOF,End_Of_File ;Assume last cluster
|
|
mov ax,[bp].Last_Found_Cluster ;Get last cluster
|
|
cmp [bp].Fat_Size,FAT12_bit
|
|
jne Got_16_Bit
|
|
xor bx,bx
|
|
mov bl,3 ;Mult by 3
|
|
mul bx
|
|
shr ax,1 ;Div by 2 to get 1.5
|
|
mov si,ax ;Get the final buffer offset
|
|
mov ax,[si]+8000h ;Get new cluster
|
|
test [bp].Last_Found_Cluster,1 ;Was last cluster odd?
|
|
jnz Odd_Result ;If Carry set it was odd
|
|
and ax,0FFFh ;Keep low 12 bits
|
|
jmp short Test_EOF
|
|
|
|
Odd_Result:
|
|
mov cl,4 ;Keep high 12 bits for odd
|
|
shr ax,cl
|
|
Test_EOF:
|
|
cmp ax,0FF8h ;Is it last cluster?
|
|
jae Got_Cluster_Done ;Yep, all done here
|
|
jmp short Not_Last_CLuster
|
|
|
|
Got_16_Bit:
|
|
shl ax,1 ;Multiply cluster by 2
|
|
mov si,ax ;Get the final buffer offset
|
|
mov ax,[si]+8000h ;Get new cluster
|
|
cmp ax,0FFF8h
|
|
jae Got_Cluster_Done
|
|
|
|
Not_Last_Cluster:
|
|
mov [bp].EOF,not End_Of_File ;Assume last cluster
|
|
|
|
Got_Cluster_Done:
|
|
ret
|
|
|
|
|
|
|
|
|
|
Relocate_Length equ $ - Read_In_FAT
|
|
Total_Length label byte
|
|
LoadBIO_Size equ $ - Start
|
|
|
|
cseg ends
|
|
end start
|