From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/SYS.ASM | 587 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 v2.0/source/SYS.ASM (limited to 'v2.0/source/SYS.ASM') diff --git a/v2.0/source/SYS.ASM b/v2.0/source/SYS.ASM new file mode 100644 index 0000000..e15758e --- /dev/null +++ b/v2.0/source/SYS.ASM @@ -0,0 +1,587 @@ +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. + +FALSE EQU 0 +TRUE EQU NOT FALSE + +IBMJAPVER EQU FALSE +IBMVER EQU FALSE +MSVER EQU TRUE + +.xlist +.xcref + INCLUDE DOSSYM.ASM +.cref +.list + + +DOSVER_LOW EQU 0136H ; Lowest acceptable DOS version number +DOSVER_HIGH EQU 020BH ; Highest acceptable DOS version + +CODE SEGMENT WORD PUBLIC +CODE ENDS + +CONST SEGMENT BYTE PUBLIC +CONST ENDS + +DATA SEGMENT BYTE PUBLIC +DATA ENDS + +DG GROUP CODE,DATA,CONST + +DATA SEGMENT PUBLIC BYTE + + EXTRN BADDRV:BYTE, BADDRVLen:WORD + EXTRN BADPARM:BYTE, BADPARMLen:WORD + EXTRN GETSYS:BYTE, GETSYSLen:WORD + EXTRN SYSDRV:BYTE + EXTRN NODEST:BYTE, NODESTLen:WORD + EXTRN BADSIZ:BYTE, BADSIZLen:WORD + EXTRN DONE:BYTE, DONELen:WORD + EXTRN BADVER:BYTE + + IF IBMJAPVER + EXTRN BADDISK:BYTE, BADDISKLen:WORD + ENDIF + +DEFALT DB 0 + IF MSVER +BIOSName DB "A:\IO.SYS",0 +DOSName DB "A:\MSDOS.SYS",0 + ENDIF + IF IBMVER OR IBMJAPVER +BIOSName DB "A:\IBMBIO.COM",0 +DOSName DB "A:\IBMDOS.COM",0 + ENDIF + +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 + +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 + + IF IBMVER OR IBMJAPVER +BOOT DW 256 DUP (0) + IF IBMJAPVER +LLISTBUF DW 256 DUP (0) + ENDIF + ENDIF + + IF IBMJAPVER +RELOC DW 1 DUP(?) +STARTSECTOR DW 1 DUP(?) + ENDIF + +BUF LABEL BYTE ; beginning of area for file reads + +DATA ENDS + +CODE SEGMENT PUBLIC + + ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + ORG 100H + +Start: + JMP SHORT CheckVersion + + IF IBMVER + DW OFFSET DG:BOOT + ENDIF +HEADER DB "Vers 1.81" +CheckVersion: + PUSH AX ; save drive letter validity + MOV AH,GET_VERSION + INT 21H ; get dos version + XCHG AH,AL ; Turn it around to AH.AL + CMP AX,DOSVER_LOW ; is it too low? + JB GOTBADDOS ; yes, error + CMP AX,DOSVER_HIGH ; too high? + JBE OKDOS ; yes, go check drive letter +GOTBADDOS: + MOV DX,OFFSET DG:BADVER ; message to dump + MOV AH,STD_CON_STRING_OUTPUT ; standard output device + INT 21H + INT 20H ; old style exit for compatability + +OKDOS: POP AX ; get drive validity + JMP SHORT SYS ; go process + +ERR0: MOV DX,OFFSET DG:BADPARM ; no drive letter + MOV CX,BadParmLen + JMP DisplayError + +ERR1: MOV DX,OFFSET DG:BADDRV ; drive letter invalid + MOV CX,BadDrvLen + JMP DisplayError + +ERR2: MOV AL,DEFALT ; get default drive number + ADD AL,'A'-1 ; turn into letter + MOV SYSDRV,AL ; place into middle of message + MOV DX,OFFSET DG:GETSYS + MOV CX,GETSYSLen ; length for output + MOV BX,stderr ; use stderr + MOV AH,Write ; Ask for system disk + INT 21H + CALL GetKeystroke ; wait for him to type simething + XOR AL,AL ; valid drive spec now... +SYS: + CMP DS:(BYTE PTR 5DH)," " ; 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 DS:(BYTE PTR 5CH),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 DS:(BYTE PTR 5CH),AL ; did he specify the default drive? + JZ ERR1 ; yes, default drive not allowed + + IF IBMVER ; Check for "valid" destination + PUSH AX + MOV AL,BYTE PTR DS:[5Ch] + 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 + POP AX ; Real AX + JC OKFAT ; Don't error here, let a CREATE or + ; some other call to the dest + ; generate a more useful INT 24H + ; error + CMP BYTE PTR [BUF],0F8H + JAE OKFAT + JMP ERR3 +OKFAT: + ENDIF + + ADD AL,'A'-1 ; turn into letter + MOV BIOSName,AL ; twiddle source name + MOV DOSName,AL ; twiddle source name + CLD + MOV DX,OFFSET DG:BIOSName ; source name + MOV DI,OFFSET DG:BIOSInFH ; pointer to block of data + CALL OpenFile + JC Err2 ; not found, go and try again + MOV DX,OFFSET DG:DOSName ; source of DOS + MOV DI,OFFSET DG:DOSInFH ; pointer to block of data + CALL OpenFile ; Look for DOS + JC ERR2 ; 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 + + IF IBMJAPVER + CALL READ_BOOT ; need to copy boot sector too + ENDIF + + MOV AL,DS:(BYTE PTR 5CH) ; get drive of destination + + IF IBMJAPVER + CALL CHECK_TRAN ; check for bootable device + JZ DOSWRT ; ok to boot + MOV DX,OFFSET DG:BADDISK ; incorrect format to boot + MOV CX,BadDiskLen + JMP DisplayError ; go error and quit +DOSWRT: + ENDIF + + ADD AL,'A'-1 ; convert to letter + MOV BIOSName,AL ; point names at destination drive + MOV DOSName,AL + MOV AllName,AL ; look for any files + + MOV AH,Find_First ; look for files + MOV DX,OFFSET DG:AllName ; path of where to look + MOV CX,Attr_Hidden+Attr_System ; attributes to find + INT 21H + JC PutSys ; no files - go and copy + + IF MSVER + MOV DL,DS:(BYTE PTR 5CH) ; get drive number + MOV AH,GET_DRIVE_FREESPACE ; get free space available + INT 21H + MUL CX ; Compute size of cluster (secsiz*secperclus) + XCHG CX,AX ; move it to correct spot + MOV DX,OFFSET DG:BIOSName ; who to open + MOV AX,BIOSLenLow+2 ; get low part of size + MOV BX,BIOSLenHigh+2 ; get high size + CALL CHKLEN ; open and snoop size + JNZ ERR4 ; Must fit exact so MSDOS is in right place + MOV DX,OFFSET DG:DOSName ; other guy to open + MOV AX,DOSLenLow+2 ; get low part of size + MOV BX,DOSLenHigh+2 ; get high size + CALL CHKLEN ; open and snoop second size + JA ERR4 ; Must be enough (or too much) space + ENDIF + + IF IBMVER OR IBMJAPVER + MOV DX,OFFSET DG:BIOSName ; open BIOS + MOV CX,7 ; attributes + MOV AH,Find_First + INT 21H + JNC FindDos +Err3J: JMP Err3 ; not found, go and complain +FindDos: + MOV DX,OFFSET DG:DOSName ; open DOS + MOV AH,Find_First + INT 21H + JC Err3J ; Not found, go complain + ENDIF + +PUTSYS: + 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: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:BIOSName ; destination of BIOS + MOV CX,7 ; fancy attributes + MOV AH,Creat ; make a new one + INT 21h + MOV BIOSOutFH,AX ; save handle + MOV DX,OFFSET DG:DOSName ; destination of DOS + MOV AH,Creat ; make a new one + INT 21h + MOV DOSOutFH,AX ; save handle +Copy: + CALL DumpMem ; flush out memory + 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 + JMP Copy +ERR4: + MOV DX,OFFSET DG:BADSIZ + MOV CX,BadSizLen + JMP DisplayError +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 + + IF IBMVER OR IBMJAPVER + CALL PUTBOOT ; copy the boot sector also + ENDIF + + MOV DX,OFFSET DG:DONE ; all finished message + MOV CX,DoneLen + XOR AL,AL ; ok error code +SERROR: + PUSH AX + MOV BX,stderr + MOV AH,Write ; convenient place to display message + INT 21H + POP AX +ErrorExit: + MOV AH,EXIT ; bye and return error code + INT 21h + +DisplayError: + MOV AL,1 + JMP SERROR +FillMem: + MOV CX,cbBuf ; get length of buffer + MOV BX,BIOSInFH ; get bios source handle + MOV DX,OFFSET DG:BUF ; point to beginning of buffer + 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 + 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 + 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 + 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 + MOV CX,NoDestLen + JMP DisplayError + +DumpMem: + MOV DX,OFFSET DG:BUF ; 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 +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 + ret + + IF MSVER +CHKLEN: +; CX has size of cluster, DX has pointer to file name +; Returns with flags set on (size of file) - (size of hole) + PUSH AX ; old size low + PUSH BX ; old size high + PUSH CX ; old cluster size + MOV AH,Find_First + MOV CX,7 ; attributes to search for + INT 21H + JC ERR3 ; cannot find file, error + POP CX ; get cluster size back + MOV DX,DS:[80h+find_buf_size_h] ; get destination size high + MOV AX,DS:[80h+find_buf_size_l] ; get size low + ADD AX,CX ; add cluster size + ADC DX,0 ; 32 bit add + SUB AX,1 ; adding CLUSSIZE-1 + SBB DX,0 ; 32 bit dec + DIV CX ; compute new cluster size + POP DX ; get old high + POP BX ; get old low + PUSH AX ; save away dividend + MOV AX,BX ; put into correct register + ADD AX,CX ; do the same as above (+CLUSSIZE-1)/CLUSSIZE + ADC DX,0 ; 32 bit add + SUB AX,1 ; adding CLUSSIZE-1 + SBB DX,0 ; 32 bit dec + DIV CX ; compute old cluster size + POP DX ; get new size + CMP AX,DX ; is old >= new? + return + ENDIF + + IF IBMJAPVER +PUTBOOT: + CALL READ_LLIST ; Get the list sector and set new boot sector + MOV AL,DS:(BYTE PTR 5CH) + DEC AL ; A=0 + MOV CX,1 + XOR DX,DX + MOV BX,OFFSET DG:BOOT + INT 26H ; Write out new boot sector + POPF + CALL WRITE_LLIST ; Make and write out new list sector + RET + ENDIF + + IF IBMVER +PUTBOOT: + MOV AH,GET_DPB + MOV DL,BYTE PTR DS:[5Ch] ; Target drive + INT 21H +ASSUME DS:NOTHING + MOV AL,[BX+16H] ; Media byte + PUSH CS + POP DS +ASSUME DS:DG + CMP AL,0FEH + JB RET1 + TEST AL,1 + JZ GOTBOOT + MOV BX,OFFSET DG:BOOT + MOV WORD PTR [BX+17],112 ; Set number of dir entries + MOV WORD PTR [BX+19],2*8*40 ; Set number of sectors + INC BYTE PTR [BX+21] ; Media = ff + INC WORD PTR [BX+26] ; Number of heads = 2 + +GOTBOOT: + MOV AL,BYTE PTR DS:[5Ch] + 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 + POP AX ; Flags +RET1: RET + ENDIF + + IF IBMJAPVER +READ_BOOT: + MOV AL,[DEFALT] + DEC AL ; A=0 + MOV CX,1 + XOR DX,DX + MOV BX,OFFSET DG:BOOT + INT 25H + POPF + MOV AX,[BOOT+108H] ; Get old first sector of data + MOV [RELOC],AX + RET + +READ_LLIST: + MOV AL,DS:(BYTE PTR 5CH) + DEC AL ; A=0 + MOV CX,1 + MOV DX,[STARTSECTOR] + MOV BX,OFFSET DG:LLISTBUF + INT 25H + POPF + RET + +WRITE_LLIST: + MOV AX,[STARTSECTOR] + MOV DX,AX + SUB AX,[RELOC] ; True reloc factor + MOV CL,BYTE PTR [LLISTBUF+0CH] ; Number of entries needing reloc + XOR CH,CH + JCXZ NO_RELOCS + MOV BX,OFFSET DG:LLISTBUF + 10H +RELLOOP: + ADD WORD PTR [BX+2],AX + ADD BX,10H + LOOP RELLOOP +NO_RELOCS: + MOV AL,DS:(BYTE PTR 5CH) + DEC AL ; A=0 + MOV CX,1 + MOV BX,OFFSET DG:LLISTBUF + INT 26H + POPF + RET + +CHECK_TRAN: +; All registers preserved. Returns zero if SYS OK, NZ if SYS FAIL +; AL is drive (1=A,...) AL=0 is not valid + + PUSH BX + PUSH AX + PUSH DS + MOV DL,AL + MOV AH,GET_DPB + INT 21H + MOV AX,[BX.dpb_first_sector] ; Get new first sector of data + MOV BH,[BX.dpb_media] + POP DS + MOV [STARTSECTOR],AX + MOV [BOOT+108H],AX ; Set new start of data in boot + POP AX + PUSH AX + MOV BL,AL + INT 11H ; IBM EQUIP CALL + ROL AL,1 + ROL AL,1 + AND AL,3 + JNZ NOT_SINGLE + INC AL +NOT_SINGLE: + INC AL ; AL is now MAX floppy # + CMP BL,AL + POP AX + JBE CHECK_FLOP ; Is a floppy + XOR BL,BL ; Is Hard file + POP BX + RET + +CHECK_FLOP: + CMP BH,0FBH ; Only floppy that boots + POP BX + RET + ENDIF + +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 + + return + +CODE ENDS + END START + + + \ No newline at end of file -- cgit v1.2.3