DOS 3.30 source code leak
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.
 
 
 
 

1204 lines
34 KiB

; SCCSID = @(#)oemfor.asm 1.28 85/10/15
name OemFormatRoutines
debug equ 0
;-------------------------------------------------------------------------------
; Public for debugging only
public CheckSwitches
public LastChanceToSaveIt
public WriteBootSector
public OemDone
public WriteBogusDos
public ConvertToOldDirectoryFormat
public SetPartitionTable
public ReadSector
public WriteSector
public SectorIO
public GetVolumeId
public CheckVolumeId
public customBPBs
public BootSectorIsFine
public NotSlashB
public NotSingleSided
public EndSwitchCheck
public WeCanNotIgnoreThisError
public CanNotWriteBoot
public HardDisk?
public BogusDos
public sys_mess_loop
public end_sys_loop
public DirectoryRead
public wrtdir
public DirectoryWritten
public PartitionTableRead
public partitionscan
public dochange
public partitionset
public BadPartitionTable
public FCBforVolumeIdSearch
public CopyVolumeId
public CompareVolumeIds
public VolumeToUpper
public NextLetter
public BadVolumeId
public switchlist
public boot2
public boot
public scratchBuffer
public bootDrive
public biosFilename
public dosFilename
public oldDrive
public oldVolumeId
public bootSignature
public ptr_msgWhatIsVolumeId?
public trackReadWritePacket
public BPB81
public BPB82
public BPB91
public BPB92
;-------------------------------------------------------------------------------
data segment public 'DATA'
data ends
code segment public 'CODE'
assume cs:code,ds:data
Public AccessDisk
public CheckSwitches
public LastChanceToSaveIt
public WriteBootSector
public OemDone
public BiosFile
public DosFile
data segment
extrn AddToSystemSize:near
extrn currentCylinder:word
extrn currentHead:word
extrn deviceParameters:byte
extrn drive:byte
extrn driveLetter:byte
extrn fBigFAT:byte
extrn inbuff:byte
extrn switchmap:word
extrn Old_Dir:byte
extrn fLastChance:byte
extrn msgBadVolumeId:byte
extrn msgBadPartitionTable:byte
extrn msgBootWriteError:byte
extrn msgDirectoryReadError:byte
extrn msgDirectoryWriteError:byte
extrn msgInvalidParameter:byte
extrn msgIncompatibleParameters:byte
extrn msgIncompatibleParametersForHardDisk:byte
extrn msgParametersNotSupportedByDrive:byte
extrn msgPartitionTableReadError:byte
extrn msgPartitionTableWriteError:byte
extrn msgWhatIsVolumeId?:byte
extrn NumSectors:word, TrackCnt:word
IF DEBUG
extrn msgFormatBroken:byte
ENDIF
data ends
extrn PrintString:near
extrn std_printf:near
extrn crlf:near
extrn user_string:near
;-------------------------------------------------------------------------------
; Support Routines
Switches macro s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16
;;
switchCount = 0
switchmask = 1
irp x,<&s1,&s2,&s3,&s4,&s5,&s6,&s7,&s8,&s9,&s10,&s11,&s12,&s13,&s14,&s15,&s16>
ifnb <x>
switchCount = switchCount + 1
SWITCH_&&x = switchmask
switchmask = 2 * switchmask
endif
endm
public switchlist
switchlist db switchCount
db "&s16&&s15&&s14&&s13&&s12&&s11&&s10&&s9&&s8&&s7&&s6&&s5&&s4&&s3&&s2&&s1&"
endm
;-------------------------------------------------------------------------------
; Constants
; Standard dos macros
INCLUDE DOSMAC.INC
; This defines all the int 21H system calls
INCLUDE SYSCALL.INC
; Limits
; following were removed into FILESIZE.INC by kwc on 10/04/86
;BIOS_SIZE equ 5400h ; Used to set size of
;DOS_SIZE equ 7600h ; Bogus DOS for /B switch
include filesize.inc
; end of FILESIZE.INC change by kwc on 10/04/86
LOGBOOTSECT equ 1
;MAX_SECTORS_IN_TRACK equ 20 Already defined in ioctl.INC
Set_Drv_Owner equ 0Fh ; IOCTL subfunction
;-------------------------------------------------------------------------------
; These are the data structures which we will need
INCLUDE DIRENT.INC
include ioctl.INC
;-------------------------------------------------------------------------------
; And this is the actual data
data segment
BiosFile db "x:\IO.SYS", 0
DosFile db "x:\MSDOS.SYS", 0
trackReadWritePacket a_TrackReadWritePacket <>
Switches S,V,H,C,T,N,1,4,8,B
; BIOS parameter blocks for various media
customBPBs label byte
BPB92 a_BPB <512, 2, 1, 2, 112, 2*9*40, 0fdH, 2, 9, 2, 0, 0, 0, 0>
BPB91 a_BPB <512, 1, 1, 2, 64, 1*9*40, 0fcH, 2, 9, 1, 0, 0, 0, 0>
BPB82 a_BPB <512, 2, 1, 2, 112, 2*8*40, 0ffH, 1, 8, 2, 0, 0, 0, 0>
BPB81 a_BPB <512, 1, 1, 2, 64, 1*8*40, 0feH, 1, 8, 1, 0, 0, 0, 0>
BPB720 a_BPB <512, 2, 1, 2, 112, 2*9*80, 0F9h, 3, 9, 2, 0, 0, 0, 0>
Custom_Media equ 0F0H ; Media byte for custom format
Dual_8_Media equ 0FFh ; Dual sided 8 sectored
Single_8_Media equ 0FEh ; Single sided 8 sectored
Dual_9_Media equ 0FDh ; Dual sided 9 sectored
Single_9_Media equ 0FCh ; Single sided 9 sectored
Dual_15_Media equ 0F9h ; Dual sided 15 sectored
Fixed_Disk equ 0F8h ; Fixed Disk
boot2 db 0,0,0, "Boot 1.x"
db 512 - 11 dup(?)
REORG2 LABEL BYTE
ORG BOOT2
INCLUDE ..\BOOT\BOOT11.INC
ORG REORG2
boot db 0,0,0,"Boot 2.x"
bootBPB a_BPB <>
db 512 - (size a_BPB + 11 + 3) dup(0)
bootDrive db 0
bootSignature dw 0
REORG LABEL BYTE
ORG BOOT
INCLUDE ..\BOOT\BOOT.INC
ORG REORG
scratchBuffer db 512 dup(?)
ptr_msgWhatIsVolumeId? dw offset msgWhatIsVolumeId?
dw offset driveLetter
data ends
;-------------------------------------------------------------------------------
; AccessDisk:
; Called whenever a different disk is about to be accessed
;
; Input:
; al - drive letter (0=A, 1=B, ...)
;
; Output:
; none
AccessDisk proc near
push ax ; save drive letter
mov bl,al ; Set up GENERIC IOCTL REQUEST preamble
inc bl
mov ax,(IOCTL SHL 8) + Set_Drv_Owner ; IOCTL function
int 21h
pop ax
return
AccessDisk endp
;-------------------------------------------------------------------------------
; CheckSwitches:
; Check switches against device parameters
; Use switches to modify device parameters
;
; Input:
; deviceParameters
;
; Output:
; deviceParameters may be modified
; Carry set if error
;
; Algorithm:
; if hard disk
; Check Boot Sector for valid Signature
; IF (valid)
; Check the volume id
; Make sure no switches other than /V, /S are specifed
; else if 96 tpi without /4 or not 5.25" disk
; Make sure no switches other than /V, /S are specifed
; else
; if 48 tpi drive and switch /4
; turn off switch /4
; if single sided drive and switch /1 but not switch /8
; turn off switch /1
; if any of interesting switches are on (/C, /O, /V, /S are not)
; set number of cylinders to 40
; choose new BPB depending on switches /1 and /8
;
CheckSwitches proc near
IF DEBUG
; See if the boot sector was initialised correctly
cmp bootSignature, 0aa55H
je BootSectorIsFine
lea dx, msgFormatBroken
jmp short SwitchError
ENDIF ; DEBUG
BootSectorIsFine:
; Disallow /C
lea dx, msgInvalidParameter
test switchmap, SWITCH_C
jz CheckExcl
SwitchError:
call PrintString
stc
ret
; Only certain permutations of the switches /N /T /V /B /S and /V are legal.
; For specific cases see the file Switchmap.legal.
CheckExcl:
lea dx, msgIncompatibleParameters ; Error message
test SwitchMap, SWITCH_B ; IF ( SWITCH_B)
jz SVpermitted
test SwitchMap, SWITCH_S or SWITCH_V ; THEN exclude SWITCH_S and
jnz SwitchError ; SWITCH_V
SVpermitted:
test SwitchMap, SWITCH_8 ; IF ( SWITCH_8 )
jz Check_N
; THEN
test SwitchMap, SWITCH_N or SWITCH_T ; exclude SWITCH_N and
jnz SwitchError
test SwitchMap, SWITCH_V ; SWITCH_V if unaccompanied
jz Check_N ; by SWITCH_S
test SwitchMap, SWITCH_S
jz SwitchError ; ENDIF ( SWITCH_8 )
Check_N: ; IF ( SWITCH_N or SWITCH_T )
test SwitchMap, SWITCH_N or SWITCH_T
jz ExclChkDone
test SwitchMap, SWITCH_1 or SWITCH_4 ; THEN exclude SWITCH_1 and
jnz SwitchError ; SWITCH_4
ExclChkDone:
; Patch the boot sector so that the boot strap loader knows what disk to
; boot from
mov bootDrive, 00H
cmp deviceParameters.DP_DeviceType, DEV_HARDDISK
jne CheckFor5InchDrives
; Formatting a hard disk so we must repatch the boot sector
mov bootDrive, 80H
test switchmap, not (SWITCH_S or SWITCH_V)
jz SwitchesOkForHardDisk
lea dx, msgIncompatibleParametersForHardDisk
call PrintString
stc
ret
; Before checking the Volume Id we need to verify that a valid one exists
; We assume that unless a valid boot sector exists on the target disk, no
; valid Volume Id can exist.
SwitchesOkForHardDisk:
SaveReg <ax,bx,cx,dx,ds>
mov al,drive
mov cx,LogBootSect
xor dx,dx
lea bx,scratchBuffer ; ScratchBuffer := Absolute_Disk_Read(
INT 25h ; Logical_sec_1 )
pop ax ; Stupid Int 25! leaves flags
; on the stack. We throw them away
jnc CheckSignature
stc
RestoreReg <ds,dx,cx,bx,ax>
ret
CheckSignature: ; IF (BootSector.BootSignature != aa55)
mov ax, Word Ptr (ScratchBuffer + (BootSignature - boot))
cmp ax, 0aa55h
RestoreReg <ds,dx,cx,bx,ax>
clc ; not an error, just not vol.
retnz ; THEN RETURN
call CheckVolumeId ; ELSE CheckVolumeID
return
OnlyVSpermitted:
test switchmap, not (SWITCH_S or SWITCH_V)
retz
lea dx, msgIncompatibleParameters
Print_And_Return:
call PrintString
stc
return
CheckFor5InchDrives:
;If drive type is anything other than 48 or 96, then only /V/S/H/N/T allowed
cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI
je Got96
cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH
je Got48
test switchmap, not (SWITCH_V or SWITCH_S or SWITCH_N or SWITCH_T or SWITCH_H)
jz Goto_Got_BPB
lea dx,msgParametersNotSupportedByDrive
jmp short Print_And_Return
; We have a 96tpi floppy drive
; /4 allows just about all switches however, /1 requires /4
Got96:
test switchmap, SWITCH_4
jnz CheckForInterestingSwitches ;If /4 check /N/T/V/S
test switchmap, SWITCH_1 ;If /1 and /4 check others
jz Got48
;If only /1 with no /4, see if /N/T
test SwitchMap,(Switch_N or Switch_T)
jnz CheckForInterestingSwitches
lea dx, msgIncompatibleParameters ;If no /4 but /1 die
jmp short Print_And_Return
Got48:
;Ignore /4 for non-96tpi 5 1/4" drives
and switchmap, not SWITCH_4
;Ignore /1 if drive has only one head and not /8
cmp word ptr deviceParameters.DP_BPB.BPB_Heads, 1
ja CheckForInterestingSwitches
test switchmap, SWITCH_8
jz CheckForInterestingSwitches
and switchmap, not SWITCH_1
;Are any interesting switches set?
CheckForInterestingSwitches:
test switchmap, not (SWITCH_V or SWITCH_S or SWITCH_H) ;Anything but /V/S/H?
jz Goto_EndSwitchCheck ;No, everything ok
;At this point there are switches other than /v/s/h
test SwitchMap,(SWITCH_N or SWITCH_T)
jz Use_48tpi ;Not /n/t, so must be /b/1/8/4
;We've got /N/T, see if there are others
test SwitchMap, not (SWITCH_N or SWITCH_T or SWITCH_V or SWITCH_S or SWITCH_H)
jz NT_Compatible ;Nope, all is well
;If 96tpi drive and /1 exists with /N/T, then okay, otherwise error
cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI
jne Bad_NT_Combo
test SwitchMap, not (SWITCH_1 or SWITCH_N or SWITCH_T or SWITCH_V or SWITCH_S or SWITCH_H)
jz Goto_Got_BPB
Bad_NT_Combo:
lea dx, msgIncompatibleParameters
jmp Print_And_Return
Goto_Got_BPB:
jmp Got_BPB_Ok ;Sleazy, but je won't reach it
Goto_EndSwitchCheck:
jmp EndSwitchCheck
;There is a problem with /N/T in that IO.SYS will default to a BPB with the
;media byte set to F0 (other) if the /N/T combo is used for the format. This
;will cause problems if we are creating a media that has an assigned media
;byte, i.e. 160,180,320,360, or 720k media using /N/T. To avoid this problem,
;if we detect a /N/T combo that would correspond to one of these medias, then
; we will set things up using the /4/1/8 switches instead of the /N/T
; MT - 7/17/86 PTR 33D0110
; Combo's that we look for - 96tpi drive @ /T:40, /N:9
; 96tpi drive @ /T:40, /N:8
;
; Look for this combo after we set everything up with the /T/N routine
; 1.44 drive @ /T:80, /N:9
NT_Compatible:
cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI
jne Goto_Got_BPB
cmp TrackCnt,40 ;Look for 40 tracks
jne Got_BPB_Ok
cmp NumSectors,9 ;9 sectors?
je Found_48tpi_Type
cmp NumSectors,8 ;8 sectors?
jne Goto_Got_BPB ;Nope, different type, let it go thru
or SwitchMap,SWITCH_8 ;Yes, turn on /8 switch
Found_48tpi_Type:
and SwitchMap,not (SWITCH_N or SWITCH_T) ;Turn off /T/N
;******End PTR fix
; if we have a 96 tpi drive then we will be using it in 48 tpi mode
Use_48tpi:
cmp byte ptr deviceParameters.DP_DeviceType, DEV_5INCH96TPI
jne Not96tpi
mov byte ptr deviceParameters.DP_MediaType, 1
mov word ptr deviceParameters.DP_Cylinders, 40
Not96tpi:
; Since we know we are formatting in 48 tpi mode turn on /4 switch
; (We use this info in LastChanceToSaveIt)
or switchmap, SWITCH_4
; At this point we know that we will require a special BPB
; It will be one of:
; 0) 9 track 2 sides - if no switches
; 1) 9 track 1 side - if only /1 specified
; 2) 8 track 2 sides - if only /8 specified
; 3) 8 track 1 side - if /8 and /1 specified
;
Get_BPBs:
; ax is used to keep track of which of the above BPB's we want
xor ax, ax
; /B implies /8
test switchmap, SWITCH_B
jz NotSlashB
or switchmap, SWITCH_8
NotSlashB:
test switchmap, SWITCH_1
jz NotSingleSided
add ax, 1
NotSingleSided:
test switchmap, SWITCH_8
jz Not8SectorsPerTrack
add ax, 2
; /8 implies Old_Dir = TRUE
mov Old_Dir,TRUE
Not8SectorsPerTrack:
; Ok now we know which BPB to use so lets move it to the device parameters
mov bx, size a_BPB
mul bx
lea si, CustomBPBs
add si, ax
lea di, deviceParameters.DP_BPB
mov cx, size a_BPB
push ds
pop es
repnz movsb
;*****************************************************************
;* /N/T DCR stuff. Possible flaw exists if we are dealing with a
;* HardDisk. If they support the "custom format" features for
;* Harddisks too, then CheckForInterestingSwitches should
;* consider /n/t UNinteresting, and instead of returning
;* after setting up the custom BPB we fall through and do our
;* Harddisk Check.
Got_BPB_OK:
test switchmap,SWITCH_N+SWITCH_T
jnz Setup_Stuff
jmp EndSwitchCheck
Setup_Stuff:
; Set up NumSectors and SectorsPerTrack entries correctly
test switchmap,SWITCH_N
jz No_Custom_Seclim
mov ax,word ptr NumSectors
mov DeviceParameters.DP_BPB.BPB_SectorsPerTrack,ax
jmp short Handle_Cyln
No_Custom_Seclim:
mov ax,deviceParameters.DP_BPB.BPB_SectorsPerTrack
mov NumSectors,ax
Handle_Cyln:
test switchmap,SWITCH_T
jz No_Custom_Cyln
; Set up TrackCnt and Cylinders entries correctly
mov ax,TrackCnt
mov DeviceParameters.DP_Cylinders,ax
jmp short Check_720
No_Custom_Cyln:
mov ax,DeviceParameters.DP_Cylinders
mov TrackCnt,ax
;****PTM P868 - Always making 3 1/2 media byte 0F0h. If 720, then set to
; 0F9h and use the DOS 3.20 BPB. Should check all drives
; at this point (Make sure not 5 inch just for future
; protection)
; We will use the known BPB info for 720 3 1/2 diskettes for
; this special case. All other new diskette media will use the
; calculations that follow Calc_Total for BPB info.
; Fix MT 11/12/86
Check_720:
cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH96TPI
je Calc_Total
cmp byte ptr deviceParameters.DP_DeviceType,DEV_5INCH
je Calc_Total
cmp TrackCnt,80
jne Calc_Total
cmp NumSectors,9
jne Calc_Total
; At this point we know we have a 3 1/2 720kb diskette to format. Use the
; built in BPB rather than the one handed to us by DOS, because the DOS one
; will be based on the default for that drive, and it can be different from
; what we used in DOS 3.20 for the 720's. Short sighted on our part to use
; 0F9h as the media byte, should have use 0F0h (OTHER) and then we wouldn't
; have this problem.
SaveReg <ds,es,si,di,cx>
mov cx,seg data ;Setup seg regs, just in case they ain't!
mov ds,cx
mov es,cx
mov si,offset BPB720 ;Copy the BPB!
mov di,offset deviceParameters.DP_BPB
mov cx,size a_BPB
rep movsb
RestoreReg <cx,di,si,es,ds>
jmp EndSwitchCheck
;End PTM P868 fix ****************************************
Calc_Total:
mov ax,NumSectors
mov bx,DeviceParameters.DP_BPB.BPB_Heads
mul bl ; AX = # of sectors * # of heads
mul TrackCnt ; DX:AX = Total Sectors
or dx,dx
jnz Got_BigTotalSectors
mov DeviceParameters.DP_BPB.BPB_TotalSectors,ax
jmp short Set_BPB
Got_BigTotalSectors:
mov DeviceParameters.DP_BPB.BPB_BigTotalSectors,ax
mov DeviceParameters.DP_BPB.BPB_BigTotalSectors+2,dx
push dx ; preserve dx for further use
xor dx,dx
mov DeviceParameters.DP_BPB.BPB_TotalSectors,dx
pop dx
Set_BPB:
; We calculate the number of sectors required in a FAT. This is done as:
; # of FAT Sectors = TotalSectors / SectorsPerCluster * # of bytes in FAT to
; represent one cluster (i.e. 3/2) / BytesPerSector (i.e. 512)
xor bx,bx
mov bl,DeviceParameters.DP_BPB.BPB_SectorsPerCluster
div bx ; DX:AX contains # of clusters
; now multiply by 3/2
mov bx,3
mul bx
mov bx,2
div bx
xor dx,dx ; throw away modulo
; now divide by 512
mov bx,512
div bx
; dx:ax contains number of FAT sectors necessary
inc ax ; Go one higher
mov DeviceParameters.DP_BPB.BPB_SectorsPerFAT,ax
mov DeviceParameters.DP_MediaType,0
mov DeviceParameters.DP_BPB.BPB_MediaDescriptor,Custom_Media
EndSwitchCheck:
clc
return
CheckSwitches endp
;-------------------------------------------------------------------------------
; LastChanceToSaveIt:
; This routine is called when an error is detected in DiskFormat.
; If it returns with carry not set then DiskFormat is restarted.
; It gives the oem one last chance to try formatting differently.
; fLastChance gets set Then to prevent multiple prompts from being
; issued for the same diskette.
;
; Algorithm:
; IF (error_loc == Track_0_Head_1) &
; ( Device_type < 96TPI )
; THEN
; fLastChance := TRUE
; try formatting 48TPI_Single_Sided
; ELSE return ERROR
;
LastChanceToSaveIt proc near
cmp currentCylinder, 0
jne WeCanNotIgnoreThisError
cmp currentHead, 1
jne WeCanNotIgnoreThisError
cmp deviceParameters.DP_DeviceType, DEV_5INCH
ja WeCanNotIgnoreThisError
mov fLastChance, TRUE
or switchmap, SWITCH_1
call CheckSwitches
clc
ret
WeCanNotIgnoreThisError:
stc
ret
LastChanceToSaveIt endp
;-------------------------------------------------------------------------------
WriteBootSector proc near
; Copy BPB to boot sector
lea si, deviceParameters.DP_BPB
lea di, bootBPB
mov cx, size a_BPB
push ds
pop es
repnz movsb
; Write out the boot sector
mov al, drive
mov cx, 1
xor dx, dx
lea bx, boot
int 26H
pop ax
jc CanNotWriteBoot
return
CanNotWriteBoot:
lea dx, msgBootWriteError
call PrintString
stc
ret
WriteBootSector endp
;-------------------------------------------------------------------------------
; OemDone:
;
OemDone proc near
; if /b write out a fake dos & bios
test switchmap, SWITCH_B
jz Switch8?
call WriteBogusDos
retc
Switch8?:
test switchmap, SWITCH_8
jz HardDisk?
call ConvertToOldDirectoryFormat
retc
HardDisk?:
cmp deviceParameters.DP_DeviceType, DEV_HARDDISK
clc
retnz
call SetPartitionTable
return
OemDone endp
;------------------------------------------------------------------------------
data segment
biosFilename db "x:\io.sys",0
dosFilename db "x:\msdos.sys",0
data ends
; simple code to stuff bogus dos in old-style diskette.
BogusDos:
push cs
pop ds
mov al,20h
out 20h,al ; turn on the timer so the disk motor
mov si,mesofs ; shuts off
sys_mess_loop:
lodsb
end_sys_loop:
or al,al
jz end_sys_loop
mov ah,14
mov bx,7
int 16
jmp sys_mess_loop
include bootmes.inc
mesofs equ no_sys_mess - BogusDos
WriteBogusDos proc near
mov al,driveLetter
mov biosFilename,al
mov dosFilename,al
mov cx, ATTR_HIDDEN or ATTR_SYSTEM
lea dx, biosFilename
mov ah,CREAT
int 21h
mov bx,ax
mov cx, BIOS_SIZE
push ds
push cs
pop ds
assume ds:code
lea dx, BogusDos
mov ah,WRITE
int 21h
pop ds
assume ds:data
mov ah,CLOSE
int 21h
mov cx, ATTR_HIDDEN or ATTR_SYSTEM
lea dx, dosFilename
mov ah,CREAT
int 21h
mov bx,ax
mov cx, DOS_SIZE
lea dx, BogusDos
mov ah,WRITE
int 21h
mov ah,CLOSE
int 21h
; Comunicate system size to the main format program
xor dx,dx
mov ax,DOS_SIZE
call AddToSystemSize
xor dx,dx
mov ax,BIOS_SIZE
call AddToSystemSize
clc
return
WriteBogusDos endp
;-------------------------------------------------------------------------------
ConvertToOldDirectoryFormat proc near
;
; convert to 1.1 directory
;
mov al,drive ; Get 1st sector of directory
mov cx,1 ; 1.1 directory always starts on
mov dx,3 ; sector 3
lea bx,scratchBuffer
int 25h
pop ax ; clean up stack
jnc DirectoryRead
lea dx, msgDirectoryReadError
call PrintString
stc
ret
DirectoryRead:
; fix attribute of io.sys and msdos.sys
lea bx,scratchBuffer
mov byte ptr [bx].dir_attr, ATTR_HIDDEN or ATTR_SYSTEM
add bx, size dir_entry
mov byte ptr [bx].dir_attr, ATTR_HIDDEN or ATTR_SYSTEM
wrtdir:
mov al,[drive] ; write out the directory
cbw
mov cx,1
mov dx,3
lea bx,scratchBuffer
int 26h
pop ax ; clean up stack
jnc DirectoryWritten
lea dx, msgDirectoryWriteError
call PrintString
stc
ret
DirectoryWritten:
test switchmap, SWITCH_S ; Was system requested?
retnz ; yes, don't write old boot sector
mov al,drive
cbw
mov bx,offset boot2 ; no, write old boot sector
cmp deviceParameters.DP_BPB.BPB_Heads, 1
je bootset8
mov word ptr [bx+3],0103h ; start address for double sided drives
bootset8:
mov cx,1
xor dx,dx
int 26h ; write out that boot sector
pop ax
retnc
lea dx, msgBootWriteError
call PrintString
stc
ret
ConvertToOldDirectoryFormat endp
;-------------------------------------------------------------------------------
a_PartitionTableEntry struc
BootInd db ?
BegHead db ?
BegSector db ?
BegCylinder db ?
SysInd db ?
EndHead db ?
EndSector db ?
EndCylinder db ?
RelSec dd ?
CSec dd ?
a_PartitionTableEntry ends
; structure of the IBM hard disk boot sector:
IBMBoot STRUC
db 512 - (4*size a_PartitionTableEntry + 2) dup(?)
PartitionTable db 4*size a_PartitionTableEntry dup(?)
Signature dw ?
IBMBoot ENDS
SetPartitionTable proc near
mov ax, 0 ; Head
mov bx, 0 ; Cylinder
mov cx, 0 ; Sector
lea dx, boot2
call ReadSector
jnc PartitionTableRead
lea dx, msgPartitionTableReadError
call PrintString
stc
ret
PartitionTableRead:
; Check to see if there is a partition table (by looking for its signature)
cmp boot2.signature, 0aa55H
jne BadPartitionTable
; Scan all the partitions search for the FIRST DOS partition. We then set the
; appropriate FAT size in the FIRST DOS partition and return.
lea bx, boot2.PartitionTable
partitionscan:
; have we scanned all partitions?
cmp bx,(offset Boot2.PartitionTable)+4*size a_PartitionTableEntry
jae BadPartitionTable
cmp [bx].sysind,1
jz dochange
cmp [bx].sysind,4
jz dochange
add bx,size a_PartitionTableEntry
jmp partitionscan
dochange:
mov [bx].sysind,4 ; assume 16 bit fat
cmp fbigfat,0 ; test assumption
jnz partitionset ; is 16 bit fat, assumption correct
mov [bx].sysind,1 ; 12 bit fat, pre 3.0 dos can read it
partitionset:
mov ax, 0 ; Head
mov bx, 0 ; Cylinder
mov cx, 0 ; Sector
lea dx, boot2
call WriteSector
retnc
lea dx, msgPartitionTableWriteError
call PrintString
stc
ret
BadPartitionTable:
lea dx, msgBadPartitionTable
call PrintString
stc
ret
SetPartitionTable endp
;-------------------------------------------------------------------------------
; ReadSector:
; Read one sector
;
; Input:
; ax - head
; bx - cylinder
; cx - sector
; dx - transfer address
ReadSector proc near
mov TrackReadWritePacket.TRWP_FirstSector, cx
mov cx,(RAWIO shl 8) or READ_TRACK
call SectorIO
return
ReadSector endp
;-------------------------------------------------------------------------------
; WriteSector:
; Write one sector
;
; Input:
; ax - head
; bx - cylinder
; cx - sector
; dx - transfer address
WriteSector proc near
mov TrackReadWritePacket.TRWP_FirstSector, cx
mov cx,(RAWIO shl 8) or WRITE_TRACK
call SectorIO
return
WriteSector endp
;-------------------------------------------------------------------------------
; SectorIO:
; Read/Write one sector
;
; Input:
; ax - head
; bx - cylinder
; cx - (RAWIO shl 8) or READ_TRACK
; - (RAWIO shl 8) or WRITE_TRACK
; dx - transfer address
SectorIO proc near
mov TrackReadWritePacket.TRWP_Head, ax
mov TrackReadWritePacket.TRWP_Cylinder, bx
mov WORD PTR TrackReadWritePacket.TRWP_TransferAddress, dx
mov WORD PTR TrackReadWritePacket.TRWP_TransferAddress + 2, ds
mov TrackReadWritePacket.TRWP_SectorsToReadWrite, 1
mov bl, drive
inc bl
mov ax, (IOCTL shl 8) or GENERIC_IOCTL
lea dx, trackReadWritePacket
int 21H
return
SectorIO endp
;-------------------------------------------------------------------------------
data segment
oldDrive db ?
FCBforVolumeIdSearch db 0ffH
db 5 dup(0)
db 08H
db 0
db "???????????"
db 40 DUP(0)
data ends
GetVolumeId proc near
; Input:
; dl = drive
; di = name buffer
; Save current drive
mov ah,19H
int 21H
mov oldDrive, al
; Change current drive to the drive that has the volume id we want
mov ah, 0eH
int 21H
; Search for the volume id
mov ah, 11H
lea dx, FCBforVolumeIdSearch
int 21H
push ax
; Restore current drive
mov ah, 0eH
mov dl,oldDrive
int 21H
; Did the search succeed?
pop ax
or al,al
jz CopyVolumeId
stc
ret
CopyVolumeId:
; Find out where the FCB for the located volume id was put
mov ah,2fH
int 21H
; Copy the Volume Id
mov si, bx
add si, 8
push es
push ds
pop es
pop ds
mov cx, 11
rep movsb
push es
pop ds
clc
ret
GetVolumeId endp
data segment
oldVolumeId db 11 dup(0)
data ends
CheckVolumeId proc near
; Get the volume id that's on the disk
lea di, oldVolumeId
mov dl, drive
call GetVolumeId
jnc Ask_User ;Did we find one?
clc ;No, return with no error
ret
; Ask the user to enter the volume id that he/she thinks is on the disk
; (first blank out the input buffer)
Ask_User:
lea dx, ptr_msgWhatIsVolumeId?
call std_printf
call user_string
call crlf
; If the user just pressed ENTER, then there must be no label
cmp inbuff+1, 0
jne CompareVolumeIds
cmp oldVolumeId, 0
jne BadVolumeId
ret
CompareVolumeIds:
; pad the reponse with blanks
; The buffer is big enough so just add 11 blanks to what the user typed in
push ds
pop es
mov cx, 11
xor bx,bx
mov bl, inbuff + 1
lea di, inbuff + 2
add di, bx
mov al, ' '
rep stosb
; Make the reply all uppercase
mov cl, inbuff + 1
xor ch,ch
lea si, inbuff + 2
VolumeToUpper:
mov al, [si]
cmp al, 'a'
jb NextLetter
cmp al, 'z'
ja NextLetter
sub al, 'a' - 'A'
mov [si],al
NextLetter:
inc si
loop VolumeToUpper
; Now compare what the user specified with what is really out there
mov cx, 11
lea si, inbuff + 2
lea di, oldVolumeId
repe cmpsb
jne BadVolumeId
ret
BadVolumeId:
lea dx, msgBadVolumeId
call PrintString
stc
ret
CheckVolumeId endp
code ends
end