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.
1168 lines
26 KiB
1168 lines
26 KiB
; SCCSID = @(#)sys.asm 1.12 85/10/06
|
|
TITLE MS-DOS SYS Program
|
|
; SYS - Copies system programs IBMBIO.COM/IO.SYS and IBMDOS.COM/MSDOS.SYS
|
|
; 1.6 05/21/82 Added rev number message
|
|
; 1.61 06/04/82 Allow SYS to blank disk TimP at SCP
|
|
; 1.70 06/30/82 NON contiguous DOS allowed on 2.00 IBM. Allows SYS to
|
|
; 1.0 1.1 disks.
|
|
; 1.71 07/02/82 Put in CHDIRs to make sure everything done in root dir.
|
|
; 1.80 04/26/83 MZ make sys work in small machines; use full 2.0
|
|
; system calls
|
|
; 1.81 07/22/83 ARR Added check in IBM version for valid FAT ID on
|
|
; destination because of IBM problem with SYSing to
|
|
; unformatted disks which are really formatted. Prints
|
|
; NoDest message for ridic IBM reasons, should have a
|
|
; better message.
|
|
; 1.82 08/12/83 ARR ZIBOed again. Mark fails to check for errors on
|
|
; his file I/O. Results in SYS saying system
|
|
; transferred when it hasn't been.
|
|
; 1.83 09/08/83 EKE Added code to quit if sys called on a drive across
|
|
; a net.
|
|
; 1.84 09/09/83 CHRISP grabbed against his will to make this stupid
|
|
; program write out a boot sector
|
|
; 1.85 10/18/83 NP Printf to print messages and it's now an .EXE file
|
|
; 1.86 11/8/83 MZ fix hard file output of boot sector
|
|
; 1.87 5/1/84 MZ make sys prompt for system disk in default drive.
|
|
; 3.20 11/9/84 RS make sys write out a correct boot sector for the
|
|
; version of DOS. It grabs the boot sector off the system
|
|
; disk and inserts the correct BPB.
|
|
; Uses IOCTL Get Device Parms to get BPB for a Hard drive.
|
|
; 3.20 08/5/85 RS Allow FAT ID byte of 0F0H for 'strange' media
|
|
; layouts. These come about because of /T /N switches in
|
|
; FORMAT.
|
|
; 3.20 09/16/85 Incorporate tables of filenames to allow system files
|
|
; used by other OEMs to be SYSed onto disks formatted on
|
|
; other MSDOS systems. Allows the flexibility to replace
|
|
; system files for one OEM by system files for another.
|
|
;
|
|
;
|
|
; 3.30 06/04/86 MT removes initial check for IBMBIO and DOS - not needed
|
|
; because of later search of dirs
|
|
; 3.30 06/16/86 MT only force part of IBMBIO contig - do this by assuming
|
|
; contig part smaller than 1.10 BIOS
|
|
; 3.30 06/16/86 MT Check diks space for enough room to install BIO and DOS
|
|
.xlist
|
|
.xcref
|
|
include version.inc
|
|
INCLUDE DOSSYM.INC ;also defines version of dos
|
|
include ioctl.INC
|
|
.cref
|
|
.list
|
|
|
|
;IBMJAPVER EQU FALSE ; this and the following are mutually
|
|
;IBMVER EQU TRUE ; exclusive
|
|
;IBMCOPYRIGHT EQU FALSE
|
|
|
|
printf_code segment public
|
|
extrn printf:far
|
|
printf_code ends
|
|
|
|
CODE SEGMENT PARA PUBLIC
|
|
CODE ENDS
|
|
|
|
CONST SEGMENT BYTE PUBLIC
|
|
EXTRN BIOSNamesTable:byte, DOSNamesTable:byte
|
|
EXTRN SourceBIOSFile:byte, SourceDOSFile:byte
|
|
CONST ENDS
|
|
|
|
cstack segment stack
|
|
db 278 + 80h dup (?) ; 278 == IBM's ROM requirements
|
|
cstack ends
|
|
|
|
DATA SEGMENT BYTE PUBLIC
|
|
|
|
DG GROUP CODE,DATA,CONST,cstack
|
|
|
|
EXTRN BADDRV_ptr:byte, BADPARM_ptr:byte, GETSYS_ptr:byte
|
|
EXTRN SYSDRV:byte, NODEST_ptr:byte, BADSIZ_ptr:byte, DONE_ptr:byte
|
|
EXTRN BADVER:byte, Crlf_ptr:byte, NoSYS_PTR:byte, GetTarg_ptr:byte
|
|
EXTRN TargDrv:byte
|
|
|
|
EXTRN NotNetM_ptr:byte
|
|
|
|
|
|
DEFALT DB 0
|
|
|
|
IF IBMCOPYRIGHT
|
|
BIOSName DB "A:\IBMBIO.COM",0
|
|
DOSName DB "A:\IBMDOS.COM",0
|
|
|
|
SourceBIOSName DB "A:\IBMBIO.COM",0
|
|
SourceDOSName DB "A:\IBMDOS.COM",0
|
|
ELSE
|
|
BIOSName DB "A:\IO.SYS",0
|
|
DOSName DB "A:\MSDOS.SYS",0
|
|
|
|
SourceBIOSName DB "A:\IO.SYS",0
|
|
SourceDOSName DB "A:\MSDOS.SYS",0
|
|
ENDIF
|
|
|
|
IBMBIO_LOW DW 0 ;length of IBMBIO on disk
|
|
IBMBIO_HIGH DW 0
|
|
IBMDOS_LOW DW 0 ;length of old IBMDOS on disk
|
|
IBMDOS_HIGH DW 0
|
|
|
|
SIZE_OLD_HIGH DW 0
|
|
SIZE_OLD_LOW DW 0
|
|
|
|
NEWBIO_SIZE_LOW DW 0
|
|
NEWBIO_SIZE_HIGH DW 0
|
|
NEWDOS_SIZE_LOW DW 0
|
|
NEWDOS_SIZE_HIGH DW 0
|
|
|
|
|
|
Need_Clusters dw 0
|
|
Bytes_Per_Cluster dw 0
|
|
Number_Free_Clusters dw 0
|
|
|
|
|
|
;*** WARNING ***
|
|
; KEEP THE FOLLOWING ITEMS IN THE EXACT ORDER BELOW!!!
|
|
DOSEntFree DB 1
|
|
BIOSEntFree DB 1
|
|
|
|
BIOSInFH DW ? ; file handle of source BIOS
|
|
BIOSLenLow DW 2 DUP (?) ; 32-bit length of BIOS
|
|
BIOSLenHigh DW 2 DUP (?) ; 32-bit length of BIOS
|
|
BIOSTime DW 2 DUP (?) ; place to store time of BIOS write
|
|
BIOSOutFH DW ? ; fh of BIOS destination
|
|
|
|
DOSInFH DW ? ; file handle of source DOS
|
|
DOSLenLow DW 2 DUP (?) ; 32-bit length of DOS
|
|
DOSLenHigh DW 2 DUP (?) ; 32-bit length of DOS
|
|
DOSTime DW 2 DUP (?) ; place to store time of DOS write
|
|
DOSOutFH DW ? ; fh of DOS destination
|
|
|
|
|
|
AllName DB "A:\*.*",0
|
|
|
|
;******************************************
|
|
;FCB SNOT
|
|
|
|
fcb_copy db 32 dup(?)
|
|
|
|
IF IBMCOPYRIGHT
|
|
FCBDOS DB "IBMDOS COM"
|
|
FCBBIO DB "IBMBIO COM"
|
|
ELSE
|
|
FCBDOS DB "MSDOS SYS"
|
|
FCBBIO DB "IO SYS"
|
|
ENDIF
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
DOSFile_Offset dw 0 ; Index for system file names in Tables
|
|
|
|
DirEnt DB 80h DUP (?)
|
|
cbBuf DW ? ; number of bytes in buffer
|
|
pDOS DW ? ; offset of beginning of DOS in buffer
|
|
pDOSEnd DW ? ; offset of end of DOS in buffer
|
|
|
|
BIOSEG EQU 70H ; STARTING LOCATION OF BIOS
|
|
BPBLEN EQU 19
|
|
|
|
BPB LABEL DWORD ; POINTER TO HARDFILE BPB
|
|
DW 0000
|
|
DW BIOSEG
|
|
|
|
public boot
|
|
BOOT DB 0,0,0 ; SKIP THE THREE BYTE JUMP
|
|
DB "MSDOS3.3"
|
|
SECSIZ DW 512 ; SECTOR SIZE
|
|
SECALL DB 1 ; SECTOS PER ALLOCATION UNIT
|
|
RESNUM DW 1 ; RESERVED SECTORS
|
|
FATNUM DB 2 ; NUMBER OF FATS
|
|
DIRNUM DW 64 ; NUMBER OF DIRECTORY ENTRIES
|
|
SECNUM DW 1*8*40 ; NUMBER OF SECTORS
|
|
FATID DB 0FEH
|
|
FATSIZE DW 1
|
|
SECLIM DW 8
|
|
HDLIM DW 1
|
|
HIDDEN DW 0
|
|
PHYDRV DB 0
|
|
DB 510-($-boot) dup (?)
|
|
DB 55H,0AAH ; MAGIC WORD
|
|
REORG LABEL BYTE
|
|
ORG BOOT
|
|
INCLUDE ..\BOOT\BOOT.INC
|
|
ORG REORG
|
|
FATID_TABLE LABEL WORD
|
|
DW 0 ; F8 FIXED DISK
|
|
DW -2 ; F9
|
|
DW -1 ; FA
|
|
DW -1 ; FB
|
|
DW OFFSET DG:BPB91 ; FC
|
|
DW OFFSET DG:BPB92 ; FD
|
|
DW OFFSET DG:BPB81 ; FE
|
|
DW OFFSET DG:BPB82 ; FF
|
|
|
|
; BIOS PARAMETER BLOCKS FOR THE VARIOUS MEDIA
|
|
|
|
BPB81 DB 1
|
|
DW 1
|
|
DB 2
|
|
DW 64
|
|
DW 1*8*40
|
|
DB 0FEH
|
|
DW 1
|
|
DW 8
|
|
DW 1
|
|
DW 0
|
|
DB 0
|
|
|
|
BPB82 DB 2
|
|
DW 1
|
|
DB 2
|
|
DW 112
|
|
DW 2*8*40
|
|
DB 0FFH
|
|
DW 1
|
|
DW 8
|
|
DW 2
|
|
DW 0
|
|
DB 0
|
|
|
|
BPB91 DB 1
|
|
DW 1
|
|
DB 2
|
|
DW 64
|
|
DW 1*9*40
|
|
DB 0FCH
|
|
DW 2
|
|
DW 9
|
|
DW 1
|
|
DW 0
|
|
DB 0
|
|
|
|
BPB92 DB 2
|
|
DW 1
|
|
DB 2
|
|
DW 112
|
|
DW 2*9*40
|
|
DB 0FDH
|
|
DW 2
|
|
DW 9
|
|
DW 2
|
|
DW 0
|
|
DB 0
|
|
|
|
BPB96T DB 1 ; mjb001
|
|
DW 1
|
|
DB 2
|
|
DW 224
|
|
DW 2*15*80
|
|
DB 0f9H
|
|
DW 7
|
|
DW 15
|
|
DW 2
|
|
DW 0
|
|
DB 0
|
|
BPBSIZ = $-BPB96T
|
|
|
|
BPB325 DB 2 ; mjb001
|
|
DW 1
|
|
DB 2
|
|
DW 70h
|
|
cSec325 DW 2*9*80
|
|
DB 0f9H
|
|
DW 3
|
|
DW 9
|
|
DW 2
|
|
DW 0
|
|
DB 0
|
|
|
|
|
|
|
|
;
|
|
; Following structure used by Generic IOCTL call Get Device Parameters to get
|
|
; the BPB of a hard disk. It 'overflows' into area of BUF.
|
|
;
|
|
DeviceParameters a_DeviceParameters <0,DEV_HARDDISK>
|
|
|
|
BUF LABEL BYTE ; beginning of area for file reads
|
|
|
|
DATA ENDS
|
|
|
|
CODE SEGMENT PUBLIC PARA
|
|
|
|
ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:CSTACK
|
|
|
|
start:
|
|
JMP SHORT CheckVersion
|
|
|
|
DW OFFSET DG:BOOT
|
|
|
|
HEADER DB "SYS 3.30"
|
|
|
|
CheckVersion:
|
|
PUSH AX ; save drive letter validity
|
|
MOV AH,GET_VERSION
|
|
INT 21H ; get dos version
|
|
|
|
cmp ax,expected_version
|
|
jne gotbaddos
|
|
|
|
; XCHG AH,AL ; Turn it around to AH.AL
|
|
; CMP AX,DOSVER_LOW ; is it too low?
|
|
; JNE GOTBADDOS ; yes, error
|
|
|
|
pop ax
|
|
ASSUME DS:NOTHING,ES:NOTHING
|
|
push cs
|
|
pop es
|
|
ASSUME ES:DG
|
|
mov si,5ch
|
|
mov di,offset dg:fcb_copy
|
|
mov cx,32
|
|
rep movsb
|
|
push cs
|
|
pop ds
|
|
ASSUME DS:DG
|
|
MOV DX,OFFSET DG:DirEnt
|
|
MOV AH,SET_DMA
|
|
INT 21h
|
|
jmp sys
|
|
|
|
GOTBADDOS:
|
|
push cs
|
|
pop ds
|
|
ASSUME DS:DG
|
|
MOV DX,OFFSET DG:BADVER ; message to dump
|
|
mov ah,std_con_string_output
|
|
int 21h
|
|
push es
|
|
xor ax,ax
|
|
push ax
|
|
|
|
foo proc far
|
|
ret ; Must use this method, version may be < 2.00
|
|
foo endp
|
|
|
|
ERR0:
|
|
ASSUME DS:DG,ES:DG
|
|
MOV DX,OFFSET DG:BADPARM_ptr ; no drive letter
|
|
JMP xerror
|
|
|
|
ERR1:
|
|
ASSUME DS:DG,ES:DG
|
|
MOV DX,OFFSET DG:BADDRV_ptr ; drive letter invalid
|
|
JMP xerror
|
|
|
|
;
|
|
; We do not have a disk that has an available system in the root. See if the
|
|
; media is removable and if so, ask the user for a replacement. If the media
|
|
; is not removable, then die gracefully.
|
|
;
|
|
ERR2:
|
|
ASSUME DS:DG,ES:DG
|
|
MOV AH,GET_DEFAULT_DRIVE ;Will find out the default drive
|
|
INT 21H ;Default now in AL
|
|
MOV BL,AL
|
|
INC BL ; A = 1
|
|
Call IsRemovable
|
|
jnc DoPrompt
|
|
MOV DX,OFFSET DG:NoSys_PTR
|
|
PUSH DX
|
|
CALL PRINTF
|
|
MOV AX,4C01h
|
|
INT 21h
|
|
DoPrompt:
|
|
MOV AL,DEFALT ; get default drive number
|
|
ADD AL,'A'-1 ; turn into letter
|
|
MOV SYSDRV,AL
|
|
MOV DX,OFFSET DG:GETSYS_ptr
|
|
push dx
|
|
call printf
|
|
CALL GetKeystroke ; wait for him to type simething
|
|
XOR AL,AL ; valid drive spec now...
|
|
SYS:
|
|
ASSUME DS:DG,ES:DG
|
|
mov DOSEntFree,1
|
|
mov BIOSEntFree,1
|
|
CMP BYTE PTR fcb_copy+1," " ; Was file specified?
|
|
JNZ ERR0 ; yes, no files are allowed -> error
|
|
CMP AL,-1 ; Invalid drive spec?
|
|
JZ ERR1 ; yes, must have valid drive -> error
|
|
CMP BYTE PTR fcb_copy,0 ; No drive specified?
|
|
JZ ERR1 ; yes, cannot sys to default drive error
|
|
MOV AH,GET_DEFAULT_DRIVE ; Get default drive
|
|
INT 21H
|
|
INC AL ; turn from phys drive to logical drive
|
|
MOV DEFALT,AL ; save it for possible printing
|
|
CMP BYTE PTR fcb_copy,AL ; did he specify the default drive?
|
|
JZ ERR1 ; yes, default drive not allowed
|
|
|
|
;------Code to quit if sys called on a drive across a net-----------------------
|
|
CheckNet:
|
|
MOV BL,BYTE PTR fcb_copy ; x = IOCTL (getdrive, Drive+1);
|
|
MOV AX,(IOCTL SHL 8) + 9
|
|
INT 21H
|
|
JC NotNet
|
|
TEST DX,1200H ; if(x & 0x1000)(redirected or shared)
|
|
JZ NotNet
|
|
MOV DX,OFFSET DG:NotNetM_ptr ; Fatal ("Can't do over net");
|
|
JMP xerror
|
|
|
|
;-------Load up BIOS and DOS at this point ---------------------------------
|
|
NotNet:
|
|
MOV AL,DEFALT
|
|
ADD AL,'A'-1 ; turn into letter
|
|
MOV SourceBIOSName,AL ; twiddle source name
|
|
MOV SourceDOSName,AL ; twiddle source name
|
|
CLD
|
|
MOV DX,OFFSET DG:SourceBIOSName ; source name
|
|
MOV CX,7
|
|
MOV AH,4Eh
|
|
INT 21h
|
|
JC ERR2J
|
|
MOV AX,WORD PTR DG:DIRENt+26
|
|
MOV WORD PTR NEWBIO_SIZE_LOW,AX
|
|
MOV AX,WORD PTR DG:DIRENt+28
|
|
MOV WORD PTR NEWBIO_SIZE_HIGH,AX
|
|
MOV DX,OFFSET DG:SourceBIOSName ; source name
|
|
MOV DI,OFFSET DG:BIOSInFH ; pointer to block of data
|
|
CALL OpenFile
|
|
JNC NotERR2
|
|
ERR2J:
|
|
JMP Err2 ; not found, go and try again
|
|
|
|
NotERR2:
|
|
MOV DX,OFFSET DG:SourceDOSName ; source name
|
|
MOV CX,7
|
|
MOV AH,4Eh
|
|
INT 21h
|
|
JC ERR2J
|
|
MOV AX,WORD PTR DG:DIRENt+26
|
|
MOV WORD PTR NEWDOS_SIZE_LOW,AX
|
|
MOV AX,WORD PTR DG:DIRENt+28
|
|
MOV WORD PTR NEWDOS_SIZE_HIGH,AX
|
|
MOV DX,OFFSET DG:SourceDOSName ; source of DOS
|
|
MOV DI,OFFSET DG:DOSInFH ; pointer to block of data
|
|
CALL OpenFile ; Look for DOS
|
|
JC ERR2J ; not there, go ask for a system disk
|
|
MOV CX,SP ; get lowest available spot
|
|
SUB CX,0200h+(OFFSET DG:BUF); leave room for all sorts of things
|
|
MOV cbBuf,CX ; store length away
|
|
CALL FillMem ; load up memory with files
|
|
JC ERR2J ; Some kind of error reading system
|
|
|
|
|
|
CheckDest:
|
|
;------------Check for "valid" destination-----------------------------------
|
|
MOV AH,0Dh
|
|
INT 21h
|
|
MOV AL,BYTE PTR fcb_copy
|
|
DEC AL
|
|
MOV BX,OFFSET DG:buf ; Temp space
|
|
MOV DX,1 ; Sector 1 (first sec of FAT)
|
|
MOV CX,DX ; One sector
|
|
INT 25H ; Read Fat sector
|
|
POP AX ; Flags
|
|
JC PromptDest ; Issue prompt to insert Destination
|
|
; disk
|
|
CMP BYTE PTR [BUF],0F8H
|
|
JAE OKFAT
|
|
;---------Treat 0F0H as a valid 'IBM' FAT ID byte--------------------------------
|
|
cmp BYTE PTR [BUF],0F0H
|
|
je OKFAT
|
|
JMP ERR3
|
|
|
|
|
|
PromptDest:
|
|
push ax
|
|
|
|
mov al,Byte ptr fcb_copy ; Get destination ID
|
|
ADD AL,'A'-1 ; turn into letter
|
|
MOV TargDrv,AL
|
|
|
|
MOV DX,OFFSET DG:GetTarg_ptr
|
|
push dx
|
|
call printf
|
|
|
|
CALL GetKeystroke ; wait for him to type simething
|
|
|
|
pop ax
|
|
jmp CheckDest
|
|
|
|
;-------The Fat appears to be OK... See if DOS/Bios there-----------------
|
|
|
|
|
|
|
|
|
|
OKFAT:
|
|
;
|
|
;Set up drive letter in destignation filespecs
|
|
;
|
|
|
|
MOV AL,BYTE PTR fcb_copy
|
|
ADD AL,'A'-1 ; convert to letter
|
|
MOV BIOSName,AL ; point names at destination drive
|
|
MOV DOSName,AL
|
|
|
|
;
|
|
; Read in first sector of directory
|
|
;
|
|
; The reason that we do the direct read of the directory is the find first/next
|
|
; or search first/next do an exclusive search for volume labels. By using these
|
|
; calls, there is no way to determine if a volume label occupies the first
|
|
; location in the directory. Hence we get sleazy and read the directory directly
|
|
; (no pun intended) to get this info. While its in there, go ahead and grab the file
|
|
; sizes. -MT
|
|
;
|
|
GetDir:
|
|
MOV DL,Byte PTR fcb_copy
|
|
MOV AH,Get_DPB
|
|
PUSH DS
|
|
INT 21h
|
|
|
|
; DS:BX point to DPB
|
|
|
|
MOV DX,[BX.dpb_dir_sector]
|
|
POP DS
|
|
MOV AL,BYTE PTR fcb_copy
|
|
DEC AL
|
|
MOV BX,OFFSET DG:BUF ; Temp space
|
|
MOV CX,1 ; Sector 1 (first sec of FAT)
|
|
INT 25H ; Read Fat sector
|
|
POP AX ; Flags
|
|
JNC Skip
|
|
|
|
;
|
|
;NOTE!!!! This next jump is actually a bug left over from the MS days - if the
|
|
;dir is not read successfully then the SYS should be canned at that point -
|
|
;however, up thru 3.20 this would just jump to the actual sys. To make things
|
|
; a little better I jump to an error - this needs to be DCR'd for a real error
|
|
;
|
|
|
|
JMP Err3
|
|
Skip:
|
|
|
|
;
|
|
; Now see if the first two directory entries are available... First check
|
|
; for being free:
|
|
;
|
|
MOV SI,OFFSET DG:BUF
|
|
CMP BYTE PTR [SI],0 ; empty dir?
|
|
JE Get_Space ; yes, go check for conflicts
|
|
CLD
|
|
CMP BYTE PTR [SI],0E5h
|
|
JE SecondFree
|
|
;
|
|
; The first entry is not free. See if the BIOS is there
|
|
;
|
|
MOV DI,OFFSET DG:FCBBIO
|
|
MOV CX,11
|
|
REP CMPSB
|
|
JNE Err3jj ; not BIOS
|
|
DEC BIOSEntFree
|
|
|
|
; added by dcl 8/24/86 - most cases solution
|
|
|
|
mov ax,0002 ; is ibmbio allocated the 1st cluster?
|
|
cmp ax,word ptr DG:BUF+26 ; that being cluster 2???
|
|
JNE Err3jj ; not cluster 2 - error; go display
|
|
|
|
; end added by dcl 8/24/86
|
|
|
|
;
|
|
; IBM change - MT 6/16/86
|
|
; Get the size of the file for IBMBIO
|
|
;
|
|
MOV ax,word ptr DG:BUF+28
|
|
MOV word ptr IBMBIO_Low,ax
|
|
MOV ax,word ptr DG:BUF+30
|
|
MOV word ptr IBMBIO_High,ax
|
|
|
|
; Check the second entry
|
|
;
|
|
SecondFree:
|
|
MOV SI,OFFSET DG:BUF+32
|
|
CMP BYTE PTR [SI],0 ; empty dir?
|
|
JE Get_Space ; yes, go check for conflicts
|
|
CMP BYTE PTR [SI],0E5h ; how about second?
|
|
JE Get_Space
|
|
;
|
|
; This entry is not free. Check it for IBMDOS
|
|
;
|
|
MOV DI,OFFSET DG:FCBDOS
|
|
MOV CX,11
|
|
REP CMPSB
|
|
Err3jj: JNZ Err3j1 ; not DOS
|
|
DEC DOSEntFree
|
|
;
|
|
; IBM change - MT 6/16/86
|
|
; Get the file size for IBMDOS
|
|
;
|
|
MOV ax,word ptr DG:BUF+60
|
|
MOV word ptr IBMDOS_Low,ax
|
|
MOV ax,word ptr DG:BUF+62
|
|
MOV word ptr IBMDOS_High,ax
|
|
|
|
;
|
|
; We now have the following:
|
|
; Whether or not there is a DOS/BIOS on the disk
|
|
; Whether or not the appropriate entry is free
|
|
; We are guaranteed that if the entry is free, then it has the correct file in
|
|
|
|
|
|
;
|
|
;IBM CHANGE - MT 6/16/86
|
|
;
|
|
; Here we make some VERY IMPORTANT assumptions.
|
|
;
|
|
;1) If IBMBIO exists on the disk currently, we assume it is in the correct
|
|
; place, i.e. at the front of the data area and contiguous.
|
|
;2) The stub loader portion of IBMBIO is less than 2048 bytes long. This
|
|
; number comes about by assuming we will never overlay anything smaller
|
|
; than 1920 bytes (DOS 1.10 IBMBIO size). This can be expanded to 2048 if
|
|
; we also assume the smallest possible cluster length is 512 bytes.
|
|
;
|
|
; Therefore, if we have an empty disk or IBMBIO exists, then we have enough
|
|
; contiguous room to install the portion of IBMBIO that requires itself to
|
|
; be contiguous.
|
|
|
|
|
|
;
|
|
;IBM CHANGE - MT 6/16/86
|
|
;
|
|
;See if enough free space for IBMBIO and IBMDOS
|
|
;
|
|
|
|
GET_SPACE:
|
|
MOV AH,36H ;Get free space
|
|
MOV DL,byte ptr fcb_copy ;Get the drive letter
|
|
INT 21h
|
|
|
|
;16 bit math okay here, no danger of overflow
|
|
|
|
MUL CX ;Get bytes/cluster
|
|
;Result left in AX
|
|
PUSH AX ;Save it for later
|
|
MOV Bytes_Per_Cluster,AX
|
|
MOV Number_Free_Clusters,BX
|
|
|
|
;Low result in AX, High result in DX
|
|
;Get IBMBIO size
|
|
|
|
MOV AX,IBMBIO_Low
|
|
MOV DX,IBMBIO_High
|
|
|
|
CALL Get_Clusters
|
|
ADD Number_Free_Clusters,AX
|
|
|
|
;Low result in AX, High result in DX
|
|
;Get IBMDOS size
|
|
|
|
MOV AX,IBMDOS_Low
|
|
MOV DX,IBMDOS_High
|
|
CALL Get_Clusters
|
|
ADD Number_Free_Clusters,AX
|
|
|
|
|
|
;Find the total size of new DOS and BIOS
|
|
|
|
MOV AX,NEWBIO_Size_Low
|
|
MOV DX,NEWBIO_Size_High
|
|
|
|
CALL Get_Clusters
|
|
|
|
Got_NEW_BIO_Clusters:
|
|
MOV Need_Clusters,AX
|
|
|
|
MOV AX,NEWDOS_Size_Low
|
|
MOV DX,NEWDOS_Size_High
|
|
CALL Get_Clusters
|
|
ADD AX,Need_Clusters
|
|
|
|
;Now see if there is enough room for all of it on the disk
|
|
|
|
CMP AX,Number_Free_Clusters
|
|
JBE PUT_SYS
|
|
|
|
ERR3J1:
|
|
JMP ERR3
|
|
|
|
;Go do the sys
|
|
PUT_SYS:
|
|
CMP BIOSEntFree,0
|
|
JNE GetRidDOS
|
|
MOV DX,OFFSET DG:BIOSName ; who to change mode
|
|
MOV CX,0 ; undo attributes
|
|
MOV AX,(ChMod SHL 8) + 1 ; set the attributes
|
|
INT 21h
|
|
MOV DX,OFFSET DG:BIOSName
|
|
MOV AX,(UNLINK SHL 8)
|
|
INT 21H ; Delete BIOS file
|
|
GetRidDOS:
|
|
CMP DOSEntFree,0
|
|
JNE CreateBIOS
|
|
MOV DX,OFFSET DG:DOSName ; who to change mode
|
|
MOV CX,0 ; undo attributes
|
|
MOV AX,(ChMod SHL 8) + 1 ; set the attributes
|
|
INT 21h
|
|
MOV DX,OFFSET DG:DOSName
|
|
MOV AX,(UNLINK SHL 8)
|
|
INT 21H ; Delete DOS file
|
|
CreateBIOS:
|
|
MOV DX,OFFSET DG:BIOSName ; destination of BIOS
|
|
MOV CX,7 ; fancy attributes
|
|
MOV AH,Creat ; make a new one
|
|
INT 21h
|
|
JC err3j2
|
|
MOV BIOSOutFH,AX ; save handle
|
|
MOV DX,OFFSET DG:DOSName ; destination of DOS
|
|
MOV AH,Creat ; make a new one
|
|
INT 21h
|
|
JC err3j2
|
|
MOV DOSOutFH,AX ; save handle
|
|
PUSH DS
|
|
MOV AH,GET_DPB
|
|
MOV DL,BYTE PTR fcb_copy ; Target drive
|
|
INT 21H
|
|
MOV [BX.dpb_next_free],0 ; Reset Allocation to start of disk
|
|
; so BIOS goes in right place!
|
|
POP DS
|
|
Copy:
|
|
CALL DumpMem ; flush out memory
|
|
JC ERR3J2 ; Disk full or some other error
|
|
MOV AX,DOSLenHigh ; more DOS?
|
|
OR AX,DOSLenLow ; more low dos
|
|
OR AX,BIOSLenHigh ; more high BIOS
|
|
OR AX,BIOSLenLow ; more low BIOS
|
|
JZ AllDone ; nope, all done
|
|
CALL FillMem ; reload world
|
|
JNC Copy
|
|
JMP ERR2 ; Start over again
|
|
|
|
ERR3J2:
|
|
JMP ERR3
|
|
|
|
ERR4:
|
|
MOV DX,OFFSET DG:BADSIZ_ptr
|
|
JMP xerror
|
|
|
|
AllDone:
|
|
MOV CX,BIOSTime ; get time and date
|
|
MOV DX,BIOSTime+2
|
|
MOV BX,BIOSOutFH ; where to stuff the time
|
|
MOV AX,(File_Times SHL 8) + 1
|
|
INT 21h
|
|
MOV AH,Close
|
|
INT 21h
|
|
MOV CX,DOSTime ; get time and date
|
|
MOV DX,DOSTime+2
|
|
MOV BX,DOSOutFH ; where to stuff the time
|
|
MOV AX,(File_Times SHL 8) + 1
|
|
INT 21h
|
|
MOV AH,Close
|
|
INT 21h
|
|
|
|
CALL PUTBOOT ; copy the boot sector also
|
|
|
|
MOV DX,OFFSET DG:DONE_ptr ; all finished message
|
|
push dx
|
|
call printf
|
|
XOR AL,AL ; ok error code
|
|
jmp short rexit
|
|
|
|
xerror:
|
|
push dx
|
|
call printf
|
|
mov dx,offset dg:crlf_ptr
|
|
push dx
|
|
call printf
|
|
mov al,0ffh
|
|
rexit:
|
|
MOV AH,EXIT ; bye and return error code
|
|
INT 21h
|
|
|
|
POPRET:
|
|
POP CX
|
|
SETERR:
|
|
STC
|
|
return
|
|
|
|
|
|
Get_Clusters:
|
|
;Round up to the next cluster size
|
|
|
|
MOV BX,Bytes_Per_Cluster ;Bytes/cluster
|
|
DIV BX ;If there is a remainder in DX, then
|
|
;we have another cluster to round up
|
|
CMP DX,0
|
|
JE Got_CLUSTERS
|
|
INC AX ;Round up to next cluster
|
|
Got_Clusters:
|
|
RET
|
|
|
|
|
|
FillMem:
|
|
MOV CX,cbBuf ; get length of buffer
|
|
MOV BX,BIOSInFH ; get bios source handle
|
|
MOV DX,OFFSET DG:BUF+512 ; point to beginning of buffer
|
|
; past area to read in boot rec
|
|
PUSH CX ; save away total length
|
|
CMP BIOSLenHigh,0 ; > 64K to read?
|
|
JA UseCX ; use CX
|
|
CMP BIOSLenLow,CX ; more left to read?
|
|
JA UseCX ; use CX
|
|
MOV CX,BIOSLenLow ; move new
|
|
UseCX:
|
|
MOV AH,Read
|
|
INT 21h ; read in what we can
|
|
JC POPRET ; Error
|
|
CMP AX,CX ; Did we get it all?
|
|
JNZ POPRET ; No, error
|
|
ADD DX,AX ; update pointer for DOS Read
|
|
MOV pDOS,DX ; point to beginning of DOS
|
|
SUB BIOSLenLow,AX ; decrement remaining
|
|
SBB BIOSLenHigh,0 ; do 32 bit
|
|
POP CX ; get original length
|
|
SUB CX,AX ; this much is left
|
|
MOV BX,DOSInFH ; get bios source handle
|
|
CMP DOSLenHigh,0 ; > 64K to read?
|
|
JA UseCXDOS ; use CX
|
|
CMP DOSLenLow,CX ; more left to read?
|
|
JA UseCXDOS ; use CX
|
|
MOV CX,DOSLenLow ; move new
|
|
UseCXDOS:
|
|
MOV AH,Read
|
|
INT 21h ; read in what we can
|
|
retc ; error
|
|
CMP AX,CX
|
|
JNZ SETERR ; Didn't read it all
|
|
ADD DX,AX ; update pointer for DOS Read
|
|
MOV pDOSEnd,DX ; point to End of dos DOS
|
|
SUB DOSLenLow,AX ; decrement remaining
|
|
SBB DOSLenHigh,0 ; do 32 bit arithmetic
|
|
CLC
|
|
return
|
|
|
|
OpenFile:
|
|
MOV AX,(OPEN SHL 8) + 0 ; open for reading only
|
|
INT 21H ; Look for BIOS
|
|
retc ; not found, go and try again
|
|
STOSW ; stash away handle
|
|
MOV BX,AX ; get ready for seeks
|
|
MOV AX,(LSeek SHL 8) + 2 ; seek relative to eof
|
|
XOR CX,CX ; zero offset
|
|
XOR DX,DX ; zero offset
|
|
INT 21h ; get offsets
|
|
STOSW ; save low part of size
|
|
STOSW ; save low part of size
|
|
MOV AX,DX
|
|
STOSW ; save high part of size
|
|
STOSW ; save high part of size
|
|
XOR DX,DX ; zero offset
|
|
MOV AX,(LSeek SHL 8) + 0 ; seek relative to beginning
|
|
INT 21h
|
|
MOV AX,(File_Times SHL 8) + 0
|
|
INT 21h ; get last write times
|
|
MOV AX,CX
|
|
STOSW ; save time
|
|
MOV AX,DX
|
|
STOSW ; save date
|
|
return
|
|
|
|
ERR3:
|
|
MOV DX,OFFSET DG:NODEST_ptr
|
|
JMP xerror
|
|
|
|
DumpMem:
|
|
MOV DX,OFFSET DG:BUF+512 ; get offset of bios start
|
|
MOV CX,pDOS ; beginning of next guy
|
|
SUB CX,DX ; difference is length
|
|
JZ DumpDos ; no bios to move
|
|
MOV BX,BIOSOutFH ; where to output
|
|
MOV AH,Write
|
|
INT 21h ; wham
|
|
retc ; error
|
|
CMP AX,CX ; Did it work?
|
|
JNZ WRERR ; No
|
|
DumpDos:
|
|
MOV DX,pDOS ; beginning of dos
|
|
MOV CX,pDOSEnd ; end of dos
|
|
SUB CX,DX ; difference is length
|
|
retz ; if zero no write
|
|
MOV BX,DOSOutFH ; where to output
|
|
MOV AH,Write
|
|
INT 21h ; wham
|
|
retc ; error
|
|
CMP AX,CX ; Did it work?
|
|
retz ; Yes, carry clear
|
|
WRERR:
|
|
STC
|
|
return
|
|
|
|
|
|
|
|
;
|
|
; Output a boot sector apporpriate to the supposed version of DOS. We do this
|
|
; by reading in the boot sector for the drive and getting the BPB from there.
|
|
; This works fine until we get a 1.x diskette, when we have to grab the media
|
|
; descriptor byte and select the correct BPB using that.
|
|
;
|
|
public putboot
|
|
PUTBOOT:
|
|
mov ax,dg ; initialize DS.
|
|
mov ds,ax
|
|
mov al,byte ptr fcb_copy ; target drive 1-based
|
|
dec al ; convert to 0-based
|
|
mov dx,0000H ; get relative sector 0
|
|
call Read_Sec
|
|
jc Do_Media_Byte
|
|
cmp word ptr DG:[Buf+1FEH], 0AA55H ; Is it a 1.x disk?
|
|
jnz Do_Media_Byte
|
|
PB0:
|
|
mov si,(offset DG:Buf)+13 ; Set up SI to point to 'SECALL' in
|
|
; the BPB just read in.
|
|
jmp PB7
|
|
;
|
|
; We were unable to use the BPB in the boot sector, so we must now get a
|
|
; valid BPB by examining the media descriptor byte.
|
|
;
|
|
Do_Media_Byte:
|
|
MOV AH,GET_DPB
|
|
MOV DL,BYTE PTR fcb_copy ; Target drive
|
|
INT 21H
|
|
MOV AL,[BX.dpb_media] ; Media byte
|
|
PUSH CS
|
|
POP DS
|
|
SUB AL,0F8H
|
|
CBW
|
|
MOV BX,AX ; BX has offset into bpb table
|
|
SHL BX,1 ; Word table, mult by 2
|
|
MOV SI,[BX+FATID_TABLE] ; get pointer to bpb
|
|
OR SI,SI ; hardfile?
|
|
JNZ PB3 ; nope.
|
|
|
|
;
|
|
; We have a hard drive. We can use the IOCTL Get Device Parameters to get the
|
|
; BPB for the hard drive.
|
|
;
|
|
mov bl,byte ptr fcb_copy ; Drive number
|
|
mov dx,offset DeviceParameters
|
|
mov ah,IOCTL
|
|
mov al,GENERIC_IOCTL
|
|
mov ch,RAWIO
|
|
mov cl,Get_Device_Parameters
|
|
int 21H
|
|
mov bx,dx ; ds:bx-> DeviceParameters
|
|
lea si,byte ptr [bx].DP_BPB ; SI -> BPB returned
|
|
inc si
|
|
inc si ; si-> secall in BPB
|
|
|
|
PB3: CMP SI,-1 ; weird internal error?
|
|
JZ PB9
|
|
CMP SI,-2 ; new multi-value FAT ID?
|
|
JNZ PB7 ; nope.
|
|
;
|
|
; We may have a FAT ID of F9. This may represent TWO different media in two
|
|
; incompatible drives. We do a get free space to determine which.
|
|
;
|
|
MOV AH,Get_Drive_freespace
|
|
MOV DL,BYTE PTR FCB_copy
|
|
INT 21h
|
|
MOV BX,DX
|
|
MUL BX ; compute total sectors
|
|
CMP AX,cSec325
|
|
MOV SI,OFFSET DG:BPB325
|
|
JB PB7
|
|
MOV SI,OFFSET DG:BPB96T
|
|
|
|
PB7: PUSH DS ; COPY IN THE NEW STUFF
|
|
POP ES
|
|
MOV DI,OFFSET DG:SECALL
|
|
MOV CX,BPBSIZ
|
|
CLD
|
|
REP MOVSB
|
|
|
|
PB8:
|
|
cmp dg:FATID,0F8H ; Hard drive?
|
|
jnz not_hard
|
|
; NOTE:
|
|
; The physical hard drive number is placed in the third byte from the end in the
|
|
; boot sector in DOS 3.2. This is a change from the previous DOS versions.
|
|
;
|
|
mov byte ptr dg:[boot+1FDH],80H ; set physical hard drive number
|
|
not_hard:
|
|
MOV AL,BYTE PTR fcb_copy
|
|
DEC AL
|
|
MOV BX,OFFSET DG:BOOT ; Boot sector
|
|
XOR DX,DX ; Sector 0
|
|
MOV CX,DX
|
|
INC CX ; One sector
|
|
INT 26H ; Write out 8 sector boot sector
|
|
jnc pb9
|
|
PB9: POP AX ; Flags
|
|
RET
|
|
|
|
;
|
|
; Read_Sec reads the sector and track specified in DX from the drive in AL.
|
|
; The sector is read into location Buf. Carry set if error.
|
|
;
|
|
|
|
READ_SEC:
|
|
push ax ; save registers
|
|
mov cx,0001H
|
|
mov bx,Offset DG:Buf ; temp. buffer
|
|
int 25H
|
|
pop ax ; Pop flags pushed by Int 25
|
|
Read_Ret:
|
|
pop ax
|
|
ret
|
|
|
|
|
|
|
|
GetKeystroke:
|
|
MOV AX,(Std_CON_Input_Flush SHL 8) + Std_CON_Input_No_Echo
|
|
INT 21H
|
|
MOV AX,(Std_CON_Input_Flush SHL 8) + 0
|
|
INT 21H
|
|
mov dx,offset dg:crlf_ptr
|
|
push dx
|
|
call printf
|
|
return
|
|
|
|
;
|
|
; Determine if the drive indicated in BX is removable or not.
|
|
;
|
|
; Inputs: BX has drive (0=default, 1=A)
|
|
; Outputs: Carry clear => removable
|
|
; Carry set => non-removable
|
|
;
|
|
; Registers modified: none
|
|
;
|
|
IsRemovable:
|
|
SaveReg <AX>
|
|
mov AX,(IOCTL SHL 8) OR 8 ; do a media check
|
|
INT 21H
|
|
jnc CheckRemove
|
|
MOV AX,(IOCTL SHL 8) OR 9 ; Is it a net drive
|
|
INT 21H
|
|
jc NotRemove ; Yipe! Say non-removable
|
|
TEST DX,1000H
|
|
jnz NotRemove ; Is NET drive. Say non-removable.
|
|
JMP IsRemove
|
|
CheckRemove:
|
|
TEST ax,1
|
|
jnz NotRemove
|
|
IsRemove:
|
|
CLC
|
|
RestoreReg <AX>
|
|
return
|
|
NotRemove:
|
|
STC
|
|
RestoreReg <AX>
|
|
return
|
|
|
|
;
|
|
; Moves the name at the current locations in the system file name tables into
|
|
; the relevant system variables for later use.
|
|
; Preserves all registers (except flags).
|
|
;
|
|
MoveNames:
|
|
push bx
|
|
push cx
|
|
push di
|
|
push si
|
|
cld
|
|
mov bx,word ptr DOSFile_Offset
|
|
mov si,offset DG:BIOSNamesTable
|
|
add si,bx
|
|
mov di,offset DG:BIOSName
|
|
add di,3 ; skip over drive,colon,back-slash
|
|
mov cx,11
|
|
repe movsb
|
|
mov si,offset DG:DOSNamesTable
|
|
add si,bx
|
|
mov di,offset DG:DOSName
|
|
add di,3 ; skip over drive,colon,back-slash
|
|
mov cx,11
|
|
repe movsb
|
|
pop si
|
|
pop di
|
|
pop cx
|
|
pop bx
|
|
ret
|
|
|
|
;
|
|
; Set up filename in FCB variables for searching directory entries.
|
|
;
|
|
SetUpFCB:
|
|
push si
|
|
push di
|
|
push bx
|
|
mov si,offset DG:BIOSNamesTable
|
|
mov bx,word ptr DOSFile_Offset
|
|
add si,bx
|
|
mov di,offset DG:FCBBIO
|
|
call MoveToFCB
|
|
mov si,offset DG:DOSNamesTable
|
|
mov bx,word ptr DOSFile_Offset
|
|
add si,bx
|
|
mov di,offset DG:FCBDOS
|
|
call MoveToFCB
|
|
pop bx
|
|
pop di
|
|
pop si
|
|
ret
|
|
|
|
;
|
|
; Move ASCIZ filename to FCB-type filename from [SI] to [DI].
|
|
;
|
|
MoveToFCB:
|
|
xor cx,cx
|
|
NextChar:
|
|
lodsb
|
|
cmp al,'.'
|
|
jz Fill_Blanks
|
|
stosb
|
|
inc cx
|
|
jmp short NextChar
|
|
|
|
Fill_Blanks:
|
|
mov al,' '
|
|
cmp cx,8
|
|
jge See_Ext
|
|
stosb
|
|
inc cx
|
|
jmp short Fill_Blanks
|
|
|
|
See_Ext:
|
|
mov cx,3
|
|
Next_Ext:
|
|
lodsb
|
|
stosb
|
|
dec cx
|
|
jnz Next_Ext
|
|
RET
|
|
|
|
;
|
|
; Gets source file names from SourceBIOSFile and SourceDOSFile and puts them
|
|
; into the ASCIZ strings SourceBIOSName and SourceDOSName.
|
|
;
|
|
GetSourceNames:
|
|
push si
|
|
push di
|
|
push cx
|
|
mov si,offset DG:SourceBIOSFile
|
|
mov di,offset DG:SourceBIOSName
|
|
add di,3 ; skip over drive,colon,back-slash
|
|
mov cx,12
|
|
repe movsb
|
|
mov si,offset DG:SourceDOSFile
|
|
mov di,offset DG:SourceDOSName
|
|
add di,3 ; skip over drive,colon,back-slash
|
|
mov cx,12
|
|
repe movsb
|
|
pop cx
|
|
pop di
|
|
pop si
|
|
ret
|
|
|
|
|
|
|
|
CODE ENDS
|
|
END START
|
|
|