]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/SYS/SYS1.ASM
8 DATA SEGMENT PARA
PUBLIC
10 public TargDrvNum
, TargSpec
, bio_owns_it
, DOS_VER
11 public packet
, packet_sectors
, packet_buffer
12 extrn THIS_DPB
:dword, BUF
:word, DIR_SECTOR
:word, first_dir_sector
:word
16 DOS_VER
DB 0 ; DOS Version - 0 = current
18 DEFALT
DB 0 ; Default Drive (source - NUMBER
19 TargDrvNum
DB 0 ; Target Drive (destination) - NUMBER
20 TargDrv
DB 0 ; Target Drive (destination) - LETTER
21 TargSpec
DB "A:\",0 ; z string for target name
23 BIOSName DB "A
:\IBMBIO
.COM
",0 ; z string for target name
24 DOSName DB "A
:\IBMDOS
.COM
",0 ; z string for target name
26 BIOSName DB "A
:\IO
.SYS
",0
27 DOSName DB "A
:\MSDOS
.SYS
",0
30 SourceBIOSName LABEL WORD
34 SourceBIOS DB "\IBMBIO
.COM
",0
36 SourceBIOS DB "\IO
.SYS
",0
40 NameLen equ $ - SourceBios
42 BiosNameLen equ $ - SourceBios
48 SourceDOS DB "\IBMDOS
.COM
",0
50 SourceDOS DB "\MSDOS
.SYS
",0
55 DosNameLen equ $ - SourceDOS
61 IBMBIO_LOW DW 0 ;length of IBMBIO on disk
63 IBMDOS_LOW DW 0 ;length of old IBMDOS on disk
76 Bytes_Per_Cluster dw 0
77 Number_Free_Clusters dw 0
80 ;---------------------------------------
81 ; SRORAGE FOR COMMAND LINE PARAMETERS
82 ;---------------------------------------
85 DW OFFSET PARMSX ; POINTER TO PARMS STRUCTURE
86 DB 0 ; NO DELIMITER LIST FOLLOWS
87 DB 0 ; NUMBER OF ADDITIONAL DELIMITERS
89 ;---------------------------------------
90 ; STRUCTURE TO DEFINE SYS SYNTAX REQUIREMENT
91 ;---------------------------------------
94 PAR_MIN DB 1 ; MINIMUM POSITIONAL PARAMETERS = 1 ;AC021;
95 DB 2 ; MAXIMUM PARAMETERS = 2 ;AC021;
96 DW OFFSET POS1 ; POINTER TO POSITIONAL DEFINITION
97 DW OFFSET POS1 ; POINTER TO SAME POSITIONAL DEFINITION;AC021;
98 DB 0 ; THERE ARE NO SWITCHES
99 DB 0 ; THERE ARE NO KEYWORDS IN PRINT SYNTAX
101 ;---------------------------------------
102 ; STRUCTURE TO DEFINE THE POSITIONAL PARAMETER (Drive ID)
103 ;---------------------------------------
106 POSREP DB reqd ; MATCH FLAG LOW ;AC021;
107 POSTYP DB f_spec + drv_id ; MATCH FLAG HIGH ;AC021;
108 DW 0001H ; CAPS BY FILE TABLE
109 DW OFFSET POS_BUFF ; PLACE RESULT IN POSITIONAL BUFFER
110 DW OFFSET NOVALS ; NO VALUES LIST REQUIRED
116 ;---------------------------------------
117 ; VALUE LIST FOR POSITIONAL
118 ;---------------------------------------
123 ; $SALUT (4,25,30,41)
125 ;---------------------------------------
126 ; RETURN BUFFER FOR POSITIONAL INFORMATION
127 ;---------------------------------------
129 POS_TYPE DB ? ; TYPE RETURNED
130 POS_ITEM_TAG DB ? ; SPACE FOR ITEM TAG
131 POS_SYN DW ? ; POINTER TO LIST ENTRY
133 POS_DRV_ID DB ? ; SPACE FOR DRIVE NUMBER (1=A, 2=B, ect)
135 POS_SEG DW ? ; ;AC021;
138 failopen equ 0 ; extended open 'does not exist action
139 openit equ 1 ; extended open 'exists' action
140 replaceit equ 2 ; extended open 'exists' action - replace
142 OPEN_PARMS label dword
144 open_off dw ? ; name pointer offset
145 open_seg dw ? ; name pointer segment
147 PACKET dw 0,0 ; CONTROL PACKET ;AN001;
148 packet_sectors dw 0 ; COUNT ;AN001;
149 PACKET_BUFFER dw 0,0 ; BUFFER ADDRESS ;AN001;
151 ;---------------------------------------
152 ; Buffer for IOCtl Get/Set Media
153 ;---------------------------------------
157 IOCtl_Level DW 0 ; INFO LEVEL (SET ON INPUT)
158 IOCtl_Ser_No_Low DW ? ; SERIAL #
159 IOCtl_Ser_No_Hi DW ? ; SERIAL #
160 IOCtl_Vol_ID DB "NO NAME
" ; VOLUME LABEL - 11 bytes
161 IOCTL_File_Sys DB 8 DUP(' ') ; FILE SYSTEM TYPE
163 IOCTL_Ser_Vol_Sys equ $ - IOCtl_Ser_No_Low
164 file_sys_size equ $ - IOCtl_File_Sys
166 File_Sys_End LABEL WORD
170 fat_12 DB "FAT12
" ; 12 bit FAT
171 FAT_len equ $ - fat_12
172 fat_16 DB "FAT16
" ; 16 or 32 bit FAT
174 ;---------------------------------------
175 ; SUBLIST for Message call
176 ;---------------------------------------
181 MSG_UTILNAME <SYS> ; ;AN000;
183 MSG_SERVICES <MSGDATA> ; ;AN000;
188 DB sub_size ; size of sublist
190 insert_ptr_off DW ? ; pointer to insert - offset
191 insert_ptr_seg DW ? ; pointer to insert - segment
192 insert_number DB 1 ; number of insert
193 DB Char_Field_ASCIIZ ;type flag
194 insert_max DB 3 ; maximum field size (limited to 3)
195 ; - this handles - SYS
197 DB 1 ; minimum field size
198 DB " " ; pad character
200 sub_size equ $ - SUBLIST ; size of sublist
205 EntryFree db 0 ; for create file
208 ; KEEP THE FOLLOWING ITEMS IN THE EXACT ORDER BELOW!!!
214 InFH DW ? ; file handle of source
215 LenLow DW ? ; 32-bit length of source
217 FTime DW ? ; place to store time of write
218 FDate DW ? ; place to store date of write
219 OutFH DW ? ; fh of destination
223 BIOSInFH DW ? ; file handle of source BIOS
224 BIOSLenLow DW ? ; 32-bit length of BIOS
226 BIOSTime DW 2 DUP (?) ; place to store time of BIOS write
227 BIOSOutFH DW ? ; fh of BIOS destination
228 BIOSPos dw 0,0 ;AN001;lseek position into file
230 DOSInFH DW ? ; file handle of source DOS
231 DOSLenLow DW ? ; 32-bit length of DOS
233 DOSTime DW 2 DUP (?) ; place to store time of DOS write
234 DOSOutFH DW ? ; fh of DOS destination
235 DOSPos dw 0,0 ;AN001;lseek position into file
238 FCBDOS DB "IBMDOS COM
"
239 FCBBIO DB "IBMBIO COM
"
241 FCBDOS DB "MSDOS SYS
"
245 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; The following is a Extended FCB
250 ExtFCB_Name db "???????????
"
252 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
254 DOS_BUFFER DB 80h DUP (?)
255 cbBuf DW ? ; number of bytes in buffer
256 pDOS DW ? ; offset of beginning of DOS in buffer
257 pDOSEnd DW ? ; offset of end of DOS in buffer
266 ; Following structure used by Generic IOCTL call Get Device Parameters to get
267 ; the BPB of a hard disk. It 'overflows' into area of BUF.
269 DeviceParameters a_DeviceParameters <1,DEV_HARDDISK>
273 CODE SEGMENT PARA PUBLIC
275 EXTRN SYSLOADMSG:near, SYSDISPMSG:near, SYSPARSE:near
276 EXTRN Data_Space:WORD, Find_DPB:near,
277 EXTRN Move_DIR_Entry:near, Free_Cluster:near, Direct_Access:near
280 ;******************* START OF SPECIFICATIONS ***********************************
282 ;*******************************************************************************
284 ;Description: Main control routine. Subroutines are structured so that they
285 ; will pass back an error return code (message number) and set
286 ; the fail flag (CF) if there was a fatal error.
290 ; 1 - This program uses its own internal stack. The stack space provided
291 ; by DOS is used as an input buffer for transfering IBMBIO and IBMDOS.
293 ; SYS is linked with the CODE segment followed by the DATA segment. The
294 ; last symbol in DATA is BUF. It marks the end end of data and the
295 ; start of the BUFfer. The BUFfer extends from here to SP. The first
296 ; 6.5Kb (13 sectors) in BUFfer are used for up to 12 sectors of the FAT
297 ; or the directory. In Main, the remaining space is set
299 ; cdBuf = SP - ( FAT_BUF + BUF )
301 ; 2 - The main line program calls 1 routine that loops until specific
302 ; requirements are met. It is:
303 ; Get_System_Files - if default drive has replaceable
304 ; media this routine loops until
305 ; a diskette with the correct system
308 ; 3 - Great effort is expended to keep the number of open files to a minimum.
309 ; This is required in case output is directed to NULL. (See DOS 4.00
312 ;Called Procedures: Init_Input_Output
313 ; Validate_Target_Drive
315 ; Check_SYS_Conditions
319 ;Input: Command line input in PSP
321 ;Ouput: no error - System transfered to target media
322 ; error - Appropriate error message displayed
324 ;Change History: Created 5/01/87 FG
326 ;******************* END OF SPECIFICATIONS *************************************
327 ;******************+ START OF PSEUDOCODE +**************************************
331 ; setup messages and parsing (CALL Init_Input_Output)
332 ; if there is no error and
333 ; verify target drive is valid (CALL Validate_Target_Drive)
334 ; if there is no error and
335 ; get system files loaded (CALL Get_System_Files)
336 ; if there is no error and
337 ; verify target drive is SYSable (Check_SYS_Conditions)
338 ; if there is no error and
339 ; perform SYS operation (CALL Do_SYS)
341 ; clean up loose ends (CALL Do_End)
343 ; load return code (System transfered)
345 ; display message (CALL Message)
350 ;******************- END OF PSEUDOCODE -**************************************
352 ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
356 PSP_PRAM DB 128 DUP(?)
360 DB " - SYS
- Utility
"
365 db 510 dup(0) ; stack
378 mov ax,OFFSET Data_Space
379 add ax,15 ; round up to next segment
380 mov cl,4 ; convert to segment value
383 add ax,cx ; generate DATA segment value
386 ASSUME DS:DATA,ES:NOTHING
388 mov cx,sp ; get lowest available spot
389 mov sp,OFFSET EOS ; set up internal stack
390 sub cx,FAT_BUF + (OFFSET BUF) ; leave room for:
393 ; FAT_BUF (12 sectors of FAT)
395 mov cbBuf,cx ; store length of Xfer buffer
397 mov dx,OFFSET DOS_BUFFER ; set up DTA
401 call Init_Input_Output ; setup messages and parsing ;AN000;
403 ; $if nc,and ; there is no error and ;AN000;
406 call Validate_Target_Drive ; verify target drive is valid ;AN000;
408 ; $if nc,and ; there is no error ;AN000;
411 call Get_System_Files ; get system files loaded ;AN000;
413 ; $if nc,and ; there is no error ;AN000;
416 call Check_SYS_Conditions ; verify target drive is SYSable ;AN000;
418 ; $if nc,and ; there is no error ;AN000;
421 call Do_SYS ; perform SYS operation ;AN000;
423 ; $if nc,and ; no error and ;AN000;
426 call Do_End ; clean up loose ends ;AN000;
428 ; $if nc ; no error ;AN000;
431 mov ax,(util_B shl 8) + done ; load return code (System transfered) ;AN000;
436 call Message ; display message ;AN000;
438 mov ah,exit ; just set function - RC set by MAIN
439 int 21h ; if version is < DOS 2.0 the int 21
441 ret ; ret if version < 2.00
445 BREAK <SYS - Init_Input_Output >
446 ;******************* START OF SPECIFICATIONS ***********************************
447 ;Routine name: Init_Input_Output
448 ;*******************************************************************************
450 ;Description: Initialize messages and Parse command line.
452 ;Called Procedures: Preload_Messages
455 ;Input: PSP command line at 81h and length at 80h
457 ;Output: no error - CF = 0 AX = 0
458 ; error - CF = 1 AX = return code (message #)
460 ;Change History: Created 5/01/87 FG
462 ;******************* END OF SPECIFICATIONS *************************************
463 ;******************+ START OF PSEUDOCODE +**************************************
465 ; START Init_Input_Output
467 ; load messages (CALL Preload_Messages)
470 ; if not = current and
471 ; set not current flag
472 ; if not = current - 1
473 ; load incorrect DOS version message
477 ; parse the saved command line (CALL Parse_Command_Line)
479 ; load return code (success)
485 ; END Init_Input_Output
487 ;******************- END OF PSEUDOCODE -**************************************
489 public Init_Input_Output
491 Init_Input_Output PROC NEAR
493 call SysLoadMsg ; preload all error messages ;AN000;
495 ; $if c ; if error - set to Utility ;AN000;
501 mov ax,(GET_VERSION shl 8) ; ;AN019;
504 cmp ax,(major_version shl 8) + minor_version ; ;AN019;
507 mov DOS_VER,0ffh ; keep track that DOS is down a level ;AN019;
508 ; 0 = current (default)
509 ; $endif ; ff = down one level ;AN021;
511 ; $if be,and ; ;AN019;
513 cmp ax,DOS_low ; ;AC023;
519 cmp ax,(3 shl 8) + 40 ;;;; to
522 mov DOS_VER,0 ;;;; 4.00
523 ; $endif ;;;; this must be remover
533 mov ax,(util shl 8) + DOS_error ; ;AN019;
538 ; $if nc,and ; no error and ;AN000;
541 xor cx,cx ; zero out # of parms processed so far ;AN000;
542 mov si,command_line ; move here to loop thru twice ;AN000;
543 call Parse_Command_Line ; parse the saved command line ;AN000;
545 ; $if nc ; no error ;AN000;
548 mov al,noerror ; load return code (success) ;AN000;
557 ENDPROC Init_Input_Output
559 BREAK <SYS - Parse_Command_Line >
560 ;******************* START OF SPECIFICATIONS ***********************************
561 ;Routine name: Parse_Command_Line
562 ;*******************************************************************************
564 ;Description: Parse the command line. Check for errors, loading return code and
565 ; setting fail flag if found. Use parse error messages except in
566 ; case of no parameters, which has its own message.
568 ;Called Procedures: SysParse
572 ;Output: no error - CF = 0
573 ; error - CF = 1 AX = return code (Parse error + error #)
575 ;Change History: Created 5/01/87 FG
577 ;******************* END OF SPECIFICATIONS *************************************
578 ;******************+ START OF PSEUDOCODE +**************************************
580 ; START Parse_Command_Line
582 ; parse command line (Call Do_Parse)
584 ; call GetError to find out what happened
588 ; set up to move filespec into SourceBIOSName
589 ; call Move_It to do the move
590 ; save size of filespec
591 ; set source spec flag
593 ; call Set_Target to process drive id (only other non error
595 ; turn off filespec as valid input
596 ; if first parm was NOT a filespec (ie a drive id)
597 ; turn on optional bit
599 ; force required parms to 2
603 ; call Set_Target to initialize drive id
604 ; call Do_Parse to look for EOF or error
608 ; call Get_Error to see what went wrong
612 ; call Get_Error to see what went wrong
621 ; END Parse_Command_Line
623 ;******************- END OF PSEUDOCODE -**************************************
625 public Parse_Command_Line
627 Parse_Command_Line PROC NEAR
628 ;---------------------------------------
630 ;---------------------------------------
631 ; $SALUT (4,27,34,41)
633 eol equ -1 ; Indicator for End-Of-Line ;AN000;
634 noerror equ 0 ; Return Indicator for No Errors ;AN000;
635 command_line equ 081H ; offset of command line in PSP ;AN000;
636 Syntax_Error equ 9 ; PARSE syntax error ;AN000;
640 ;---------------------------------------
641 ; Get address of command line
642 ;---------------------------------------
646 lea di,PARMS ; ;AC021:
648 call Do_Parse ; ;AC021:
650 cmp ax,0 ; did we find our required parm? ;AN000;
652 ; $if ne ; no -check what happened ;AN000;
655 call Get_Error ; ;AC021;
661 cmp POS_TYPE,5 ; is it a file spec? ;AN021;
662 ; $if e ; if it is a file spec ;AN021;
664 push ds ; copy spec into source ;AN021;
667 lea di,SourceSpec ; ;AN021;
668 mov si,word ptr POS_OFF ; ;AN021;
669 mov ax,POS_SEG ; ;AN021;
672 ASSUME ds:nothing,es:DATA
676 call Move_Source ; ;AN021;
682 ASSUME ds:DATA,es:nothing
684 mov SourceSize,bx ; ;AN021;
685 mov Spec_Flag,1 ; set spec flag ;AN021;
686 ; $else ; must be a drive id ;AN021;
689 call Set_Target ; initialize target just in case ;AN021;
690 mov SourceSpec,al ; save Source Spec ;AN000;
691 ; remember that the colon and size
694 and POSTYP,drv_id ; off filespec bit - on drive bit ;AN021;
695 cmp Spec_Flag,0 ; do we have a source spec ? ;AN021;
696 ; $if e ; if spec flag not set ;AN021;
698 inc POSREP ; turn on optional ;AN021;
702 inc PAR_MIN ; must have the second parm. ;AN021;
706 call Do_Parse ; ;AN021;
708 cmp ax,0 ; no parse errors? ;AN000;
710 ; $if e ; if no error - must be a drive id ;AN021;
712 call Set_Target ; initialize target ;AN021;
713 cmp Spec_Flag,0 ; do we have a source spec ? ;AN021;
714 ; $if e ; if spec flag not set ;AN021;
716 inc Spec_Flag ; turn it on ;AN021;
720 call Do_Parse ; make sure there are no extra parms. ;AN021;
728 call Get_Error ; ;AN021;
731 ; $else ; could be EOL or error ;AN021;
734 cmp ax,eol ; is it EOL ? ;AN021;
735 ; $if ne ; if it is not eol ;AN021;
737 call Get_Error ; error - make sure it makes sense ;AN021;
752 Move_Source PROC NEAR
759 cmp bl,54 ; are we past the maximum? ;AN021;
760 ; $exitif a ; ;AN021;
762 mov ax,(util_B SHL 8) + bad_path ; Invalid path ;AN021;
768 ; $endloop z ; ;AN021;
781 mov insert_ptr_off,si ; save it in case of error ;AN024;
786 ASSUME ds:nothing,es:DATA
788 call SysParse ; parse command line ;AN000;
793 ASSUME ds:DATA,es:nothing
802 mov al,byte ptr pos_drv_id ; initalize drive id ;AN000;
803 mov TargDrvNum,al ; save it for later ;AN000;
804 mov ExtFCB_Drive,al ; save it for finding VOL id ;AN000;
805 or al,num_2_letter ; convert to a drive letter ;AC000;
806 mov TargSpec,al ; save it for later ;AN000;
807 mov TargDrv,al ; ;AC000;
814 lea bx,Parse_Ret_Code ; error - make sure it makes sense ;AN000;
815 xlat cs:[bx] ; ;AN000;
816 mov ah,parse_error ; indicate parse error CLASS ;AN000;
817 stc ; set fail flag ;AN000;
822 Parse_Ret_Code label byte
824 db 0 ; Ret Code 0 - ;AN000;
825 db 1 ; Ret Code 1 - Too many operands ;AN000;
826 db 2 ; Ret Code 2 - Required operand missing;AC002;
827 db 9 ; Ret Code 3 - Not in switch list provided ;AC002;
828 db 9 ; Ret Code 4 - Not in keyword list provided;AC002;
829 db 9 ; Ret Code 5 - (not used) ;AN000;
830 db 9 ; Ret Code 6 - Out of range specified ;AN000;
831 db 9 ; Ret Code 7 - Not in value list provided
832 db 9 ; Ret Code 8 - Not in string list provided
833 db 9 ; Ret Code 9 - Syntax error
835 ENDPROC Parse_Command_Line
837 BREAK <SYS - Validate_Target_Drive >
838 ;******************* START OF SPECIFICATIONS ***********************************
839 ;Routine name: Validate_Target_Drive
840 ;*******************************************************************************
842 ;Description: Verify that target drive was specified, is not default drive,
843 ; is a valid drive letter, and is not a network drive
845 ;Called Procedures: Check_Default_Drive
851 ;Output: no error - CF = 0 AX = 0
852 ; error - CF = 1 AX = return code (message #)
854 ;Change History: Created 5/01/87 FG
856 ;******************* END OF SPECIFICATIONS *************************************
857 ;******************+ START OF PSEUDOCODE +**************************************
859 ; START Validate_Target_Drive
861 ; can't have target as default (CALL Check_Default_Drive)
863 ; can't have target as network (CALL Check_For_Network)
865 ; see if valid drive letter (CALL Check_Target_Drive)
868 ; END Validate_Target_Drive
870 ;******************- END OF PSEUDOCODE -**************************************
872 public Validate_Target_Drive
874 Validate_Target_Drive PROC NEAR
876 call Check_Default_Drive ; can't have target as default ;AN000;
878 ; $if nc,and ; no error and ;AN000;
881 call Check_For_Network ; can't have target as network ;AC022;
883 ; $if nc ; no error ;AN000;
886 call Check_Target_Drive ; see if valid drive letter ;AC022;
893 ENDPROC Validate_Target_Drive
895 BREAK <SYS - Check_Default_Drive >
896 ;******************* START OF SPECIFICATIONS ***********************************
897 ;Routine name: Check_Default_Drive
898 ;*******************************************************************************
900 ;Description: Check to see if drive specified is default drive. If it is,
901 ; load return code and set fail flag.
903 ;Called Procedures: None
907 ;Output: no error - CF = 0
908 ; error - CF = 1 AX = 16d - Can not specify default drive
910 ;Change History: Created 5/01/87 FG
911 ;Change History: Ax021 2/22/88 FG
913 ;******************* END OF SPECIFICATIONS *************************************
914 ;******************+ START OF PSEUDOCODE +**************************************
916 ; START Check_Default_Drive
918 ; initialize BIO and DOS found flags
919 ; if source specified
920 ; copy source into SourceDOSName from SourceBIOName
922 ; get_default_drive (INT21 Get_Default_Drive + 00 <1900>)
923 ; if target drive = default drive
924 ; load return code (Can not specify default drive)
927 ; initialize SourceBIOName and SourceDOSName
931 ; remove blanks in \IBMBIO.COM
932 ; remove blanks in \IBMDOS.COM
935 ; END Check_Default_Drive
937 ;******************- END OF PSEUDOCODE -**************************************
939 public Check_Default_Drive
941 Check_Default_Drive PROC NEAR
946 ASSUME DS:DATA,ES:DATA
948 mov DOSEntFree,1 ; set to not found ;AC021;
949 mov BIOSEntFree,1 ; set to not found ;AC021;
950 cmp Spec_Flag,1 ; was a source specified ? ;AN021;
951 ; $if e ; if a source was specified ;AN021;
953 lea si,SourceSpec ; copy source for IBMDOS.COM ;AN021;
954 mov al,[si] ; get the drive ID ;AN025;
955 sub al,num_2_letter ; convert it to a 1 base number ;AN025;
956 mov DEFALT,al ; save it in case its removable ;AN025;
957 lea di,SourceDOSName ; ;AN021;
958 mov cx,SourceSize ; set up size to move ;AN021;
959 rep movsb ; move it! ;AN021;
961 ; $else ; figure out what the default is ;AN021;
965 mov ax,(Get_Default_Drive shl 8) + not_used ; get_default_drive
966 INT 21h ; Get_Default_Drive <1900>
967 inc al ; turn from phys drive to logical drive
968 mov DEFALT,al ; save default for later
970 or SourceSpec,num_2_letter ; covert number to letter
971 cmp al,TargDrvNum ; is target drive = default drive
972 ; $if e ; if it is the same - we have a problem;AC000;
975 mov ax,(util_B shl 8) + not_on_default ; load return code
976 ; - Can not specify default drive
979 ; $else ; it wasn't = so its ok ;AC000;
983 ; initalize SourceBIOSNane, SourceDOSName
985 or al,num_2_letter ; turn into letter
986 mov byte ptr SourceBIOSName,AL ; twiddle source name
987 mov SourceDOSName,AL ; twiddle source name
988 clc ; reset fail flag ;AN000;
994 ; $if nc ; if no error to this point ;AN021;
999 mov bx,NameLen ; ;AN021;
1005 lea di,SourceBiosName ; move IBMBIO.COM into place ;AN021;
1006 add di,SourceSize ; move to end of specified part ;AN021;
1007 lea si,SourceBIOS ; point to system file name ;AN021;
1016 lea di,SourceDOSName ; move IBMDOS.COM into place ;AN021;
1017 add di,SourceSize ; move to end of specified part ;AN021;
1018 lea si,SourceDOS ; point to system file name ;AN021;
1025 ENDPROC Check_Default_Drive
1027 BREAK <SYS - Check_Target_Drive >
1028 ;******************* START OF SPECIFICATIONS ***********************************
1029 ;Routine name: Check_Target_Drive
1030 ;*******************************************************************************
1032 ;Description: Determine if target drive is valid. To do this, we will make an
1033 ; IOCTL - check media ID call.
1037 ;Input: Default_Drive
1039 ;Output: no error - CF = 0
1040 ; error - CF = 1 AX = 16d - Can not specify default drive
1042 ;Change History: Created 5/01/87 FG
1044 ;******************* END OF SPECIFICATIONS *************************************
1045 ;******************+ START OF PSEUDOCODE +**************************************
1047 ; START Check_Target_Drive
1049 ; Check media ID (INT21 IOCTL + IOCTL_CHANGEABLE? <4408>)
1060 ; if ASSIGNed or SUBSTd drive
1070 ; END Check_Target_Drive
1072 ;******************- END OF PSEUDOCODE -**************************************
1074 public Check_Target_Drive
1076 Check_Target_Drive PROC NEAR
1078 mov bl,TargDrvNum ; get the target drive number ;AN000;
1079 mov ax,(IOCTL SHL 8) + IOCTL_CHANGEABLE? ; do a media check ;AC000;
1080 INT 21h ; IOCtl + 08 <4408> ;AC000;
1082 cmp ax,0fh ; is it invalid - al = F (CF may be set;AC000;
1087 mov ax,(DOS_error shl 8) + extended_15 ; load return code ;AC000;
1091 ; $else ; if valid device so far - make sure ;AN012;
1094 ; its not ASSIGNed or SUBSTed drive
1095 mov si,offset TargSpec ; point to Target Spec ;AN012;
1096 mov di,offset DIR_SECTOR ; point at output buffer ;AN012;
1097 mov ax,(xNameTrans SHL 8) ; check for name translation ;AN012;
1098 int 21h ; get real path ;AN012;
1101 mov bl,byte ptr [TargSpec] ; get drive letter from path ;AN012;
1102 cmp bl,byte ptr DIR_SECTOR ; did drive letter change? ;AN012;
1103 ; $if ne ; if not the same, it be bad ;AN012;
1105 lea si,sys_ptr ; set insert pointer in SUBLIST ;AN012;
1106 mov [insert_ptr_off],si ; ;AN012;
1107 mov [insert_ptr_seg],ds ; ;AN012;
1108 lea si,sublist ; set pointer to SUBLIST ;AN012;
1109 mov ax,(util_C shl 8) + cant_assign ; load ret cd (Cannot..SUB);AN012;
1110 stc ; tell user ;AN012;
1111 ; $else ; - its ok ;AN012;
1114 clc ; keep going ;AN012;
1117 ; $else ; - its a critical error ;AN012;
1120 xor ah,ah ; set up for extended error call ;AN012;
1129 ENDPROC Check_Target_Drive
1131 BREAK <SYS - Check_For_Network >
1132 ;******************* START OF SPECIFICATIONS ***********************************
1133 ;Routine name: Check_For_Network
1134 ;*******************************************************************************
1136 ;Description: Verify that the target drive is local, and not a shared drive.
1137 ; If shared,load return code and set fail flag.
1139 ; NOTE: This is a design point on how to determine net
1141 ;CALLed Procedures: None
1145 ;Output: no error - CF = 0
1146 ; error - CF = 1 AX = return code = 7 - Cannot SYS to a Network drive
1148 ;Change History: Created 5/01/87 FG
1150 ;******************* END OF SPECIFICATIONS *************************************
1151 ;******************+ START OF PSEUDOCODE +**************************************
1153 ; START Check_For_Network
1155 ; IOCtl call to see if target drive is local
1156 ; if target drive not local (INT21 IOCtl + 09 <4409>) and
1157 ; if return code indicates network drive (test 1200h)
1158 ; set insert pointer in SUBLIST
1159 ; set pointer to SUBLIST
1160 ; load return code (Cannot SYS to a Network drive)
1167 ; END Check_For_Network
1169 ;******************- END OF PSEUDOCODE -**************************************
1171 public Check_For_Network
1173 Check_For_Network PROC NEAR
1175 ; IOCtl call to see if target drive is local
1176 mov bl,TargDrvNum ; x = IOCTL (getdrive, Drive+1) ;AC022;
1177 mov ax,(IOCTL SHL 8) + dev_local
1178 INT 21h ; IOCtl + dev_local <4409>
1180 ; $if nc,and ; target drive local and ;AC000;
1183 test dx,1200H ; check if (x & 0x1000)
1184 ; (redirected or shared)
1185 ; $if nz ; return code indicates network drive ;AC000;
1188 lea si,sys_ptr ; set insert pointer in SUBLIST ;AN000;
1189 mov [insert_ptr_off],si ; ;AN000;
1190 mov [insert_ptr_seg],ds ; ;AN000;
1191 lea si,sublist ; set pointer to SUBLIST ;AN000;
1192 mov ax,(util_C shl 8) + cant_network ; load return code (Cannot SYS to.;AC000;
1193 stc ; set fail flag ;AN000;
1199 clc ; reset fail flag ;AC000;
1206 ENDPROC Check_For_Network
1208 BREAK <SYS - Get_System_Files >
1209 ;******************* START OF SPECIFICATIONS ***********************************
1210 ;Routine name: Get_System_Files
1211 ;*******************************************************************************
1213 ;Description: Ensure that the the files IBMBIO and IBMDOS are available
1214 ; on the source media. If they are not on the source media,
1215 ; and the media is removeable, a prompt will be issued to
1216 ; insert a new source.
1218 ;Called Procedures: Prompt_For_Media Open_File
1219 ; Check_Removable Fill_Memory
1221 ;Input: IBMBIO and IBMDOS on source media
1223 ;Output: no error - CF = 0
1224 ; error - CF = 1 AX = return code (message #)
1226 ;Change History: Created 5/01/87 FG
1227 ; Major change 1/07/88 FG Ax019 now makes SYS check
1228 ; for the CORRECT version
1230 ; IBMBIO looks like this:
1233 ; ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄ
1234 ; ³ JMP ³ LO ³ HI ³extected_version³
1235 ; ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄ
1236 ;******************* END OF SPECIFICATIONS *************************************
1237 ;******************+ START OF PSEUDOCODE +**************************************
1239 ; START Get_System_Files
1241 ; initalize SourceBIOSNane, SourceDOSName
1245 ; open file (CALL Open_File)
1249 ; open file (CALL Open_File)
1251 ; load memory with files (CALL Fill_Memory)
1253 ; if correct version of IBMBIO
1255 ; load success return code
1257 ; check if source media replaceable (CALL Check_Removeable)
1258 ; if fail flag reset (replaceable)
1259 ; load message number (Insert system disk....)
1260 ; and class (utility)
1261 ; set up pointer to insert (drive id)
1262 ; prompt for source media (CALL Prompt_For_Media)
1263 ; if fail flag reset
1264 ; load return code (try again)
1268 ; leave if success return code
1269 ; leave if fail flag set
1273 ; END Get_System_Files
1275 ;******************- END OF PSEUDOCODE -**************************************
1277 public Get_System_Files
1279 Get_System_Files PROC NEAR
1285 lea si,DOS_BUFFER ; set up addressability
1286 mov dx,OFFSET SourceBIOSName ; look on source for IBMBIOS
1287 mov CX,DOS_system_atrib ; its an 'everything' file
1288 mov ah,Find_First ; do a find first INT21
1289 INT 21h ; Find_First <4Exx>
1291 ; $if nc,and ; if found and..................... ;AC000;
1293 mov ax,ds:[si].find_buf_size_l ; move size (low and high) ;AC000;
1294 mov WORD PTR NEWBIO_SIZE_LOW,AX ; from DTA
1295 mov ax,ds:[si].find_buf_size_h ; to ;AC000;
1296 mov WORD PTR NEWBIO_SIZE_HIGH,AX ; SYS data space
1297 mov dx,OFFSET SourceBIOSName ; point to source name
1298 mov di,OFFSET BIOSInFH ; pointer to block of data
1300 call Open_File ; open file
1302 ; $if nc,and ; if no error and.................... ;AC000;
1305 mov dx,OFFSET SourceDOSName ; look on source for IBMDOS
1306 mov CX,DOS_system_atrib ; its an 'everything' file
1307 mov ah,Find_First ; do a find first INT21
1308 INT 21h ; Find_First <4Exx>
1310 ; $if nc,and ; if found and....................... ;AC000;
1313 mov ax,ds:[si].find_buf_size_l ; move size (low and high) ;AC000;
1314 mov WORD PTR NEWDOS_SIZE_LOW,AX ; from DTA
1315 mov ax,ds:[si].find_buf_size_h ; to ;AC000;
1316 mov WORD PTR NEWDOS_SIZE_HIGH,AX ; SYS data space
1317 mov dx,OFFSET SourceDOSName ; pointer to source of DOS
1318 mov di,OFFSET DOSInFH ; pointer to block of data
1320 call Open_File ; open file
1322 ; $if nc,and ; if no error and......................;AC000;
1325 call Fill_Memory ; load memory with files
1327 ; $if nc,and ; if no error..................: ;AC019;
1330 cmp WORD PTR BUF+FAT_BUF+3,expected_version ; point to beginning ;AN019;
1331 ; of buffer + near jump instruction
1333 ; $if e ; if correct version of IBMBIO ;AN019;
1336 clc ; reset fail flag ;AN019:
1337 mov al,noerror ; load success return code ;AN000;
1339 ; $else ; ELSE - something wrong with source ;AC000;
1343 mov bl,defalt ;; specify drive ;;dcl ;AN001;
1344 call Check_Removeable ; check if source media replaceable ;AC000;
1346 ; $if nc ; fail flag reset (replaceable) ;AC000;
1349 mov ax,(util_C shl 8) + sys_disk ; load message number ;AC000;
1350 ; - Insert system disk....
1351 lea si,SourceSpec ; set insert pointer to DRIVE ID ;AC000;
1352 mov bx,SourceSize ; only display correct path length ;AN025;
1354 call Prompt_For_Media ; prompt for source media ;AN000;
1356 ; $if nc ; fail flag reset ;AC000;
1359 mov ax,error_RC ; load return code (try again) ;AN000;
1370 ; $leave c ; if fail flag set ;AC018;
1373 cmp al,noerror ; is it an error return code? ;AC018;
1375 ; $exitif e ; quit if success return code ;AC018;
1378 mov bx,BIOSInFH ; ;AC018;
1379 mov ah,Close ; ;AC018;
1382 mov bx,DOSInFH ; ;AC018;
1383 mov ah,Close ; ;AC018;
1390 ; $endloop long ; ;AC018;
1393 ; $endsrch ; ;AN018;
1400 ENDPROC Get_System_Files
1402 BREAK <SYS - Prompt_For_Media >
1403 ;******************* START OF SPECIFICATIONS ***********************************
1404 ;Routine name: Prompt_For_Media
1405 ;*******************************************************************************
1407 ;Description: Make call to Message to display:
1409 ; Insert system disk in drive %1
1410 ; and strike any key when ready
1412 ;Called Procedures: Message
1414 ;Input: (AL) = message #
1415 ; (BL) = drive/path length
1416 ; (SI) = insert pointer
1418 ;Output: no error - CF = 0
1419 ; error - CF = 1 AX = return code (DOS error)
1421 ;Change History: Created 5/01/87 FG
1423 ;******************* END OF SPECIFICATIONS *************************************
1424 ;******************+ START OF PSEUDOCODE +**************************************
1426 ; START Prompt_For_Media
1428 ; set up for message call
1429 ; call Message - display first line
1431 ; clear insert indicator
1432 ; load Message #x - Press any key to continue
1433 ; ask for keystroke response (direct CON in no echo)
1434 ; call Message - display second line
1437 ; load return code (DOS extended error)
1441 ; END Prompt_For_Media
1443 ;******************- END OF PSEUDOCODE -**************************************
1445 public Prompt_For_Media
1447 Prompt_For_Media PROC NEAR
1449 mov [insert_ptr_off],si ; set up for message call ;AN000;
1450 mov [insert_ptr_seg],ds
1451 mov insert_max,bl ; only display correct path length ;AN025;
1452 lea si,sublist ; set pointer to SUBLIST ;AN000;
1454 call Message ; display first line ;AN000;
1456 ; $if nc ; if no error ;AN000;
1459 mov ax,(util_D shl 8) + press_key ; load Message ;AN000;
1460 ; - Press any key to continue
1461 ; the class will signal to ask for
1462 ; keystroke response
1463 ; (direct CON in no echo)
1464 call Message ; display second line ;AN000;
1469 ; $if c ; if an error occured ;AN000;
1472 mov ah,DOS_error ; load return code (DOS extended error);AN000;
1479 ENDPROC Prompt_For_Media
1481 BREAK <SYS - Check_Removeable >
1482 ;******************* START OF SPECIFICATIONS ***********************************
1483 ;Routine name: Check_Removeable
1484 ;*******************************************************************************
1486 ;Description: Make IOCtl call to see if media in the drive indicated in
1489 ;Called Procedures: None
1491 ;Input: BX has drive (0=default, 1=A)
1493 ;Output: removeable - CF = 0
1494 ; nonremovable or error - CF = 1
1495 ; AX = 11d - No system on default drive
1497 ;Change History: Created 5/01/87 FG
1499 ;******************* END OF SPECIFICATIONS *************************************
1500 ;******************+ START OF PSEUDOCODE +**************************************
1502 ; START Check_Removeable
1504 ; if source not specified
1505 ; do an IOCTL changeable check (INT21 IOCtl + 08 <4408>)
1507 ; test if removeable
1511 ; load return code (No system on default drive)
1516 ; load return code (No system on specified path)
1521 ; END Check_Removeable
1523 ;******************- END OF PSEUDOCODE -**************************************
1525 public Check_Removeable
1527 Check_Removeable PROC NEAR
1529 mov ax,(IOCTL SHL 8) + IOCTL_CHANGEABLE? ; do a media check
1530 INT 21h ; IOCtl + 08 <4408>
1531 ; cy set if remote or invalid device ;;dcl;;
1541 cmp Spec_Flag,1 ; ;AC025;
1544 mov ax,(util_B shl 8) + no_sys_on_def ; No system on... ;AC000;
1548 mov ax,(util_B shl 8) + system_not_found ; Invalid path or Sy..;AN021;
1559 ENDPROC Check_Removeable
1561 BREAK <SYS - Open_File >
1562 ;******************* START OF SPECIFICATIONS ***********************************
1563 ;Routine name: Open_File
1564 ;*****************************************************************************
1566 ;Description: Opens file and gets size and date
1568 ;Called Procedures: None
1570 ;Input: ES:DI = Data space for DOS operations
1572 ;Output: no error - CF = 0
1573 ; error - CF = 1 AX = DOS extended errors
1575 ;Change History: Created 5/01/87 FG
1577 ;******************* END OF SPECIFICATIONS *************************************
1578 ;******************+ START OF PSEUDOCODE +**************************************
1582 ; open file for read (INT21 Read + 00 <3D00>)
1585 ; find End Of File (INT21 LSeak + 02 <4202>)
1587 ; get offsets (INT21)
1588 ; save low part of size
1589 ; save high part of size
1590 ; find start of file (INT21 LSeak + 00 <4200>)
1591 ; find last write time(INT21 File_Times + 00 <5700>)
1595 ; load return code (DOS extended errors)
1601 ;******************- END OF PSEUDOCODE -**************************************
1607 mov ax,(OPEN SHL 8) + not_used ; open file for read
1608 INT 21h ; Read + not_used <3D00>
1610 ; $if nc ; no error ;AC000;
1613 mov es:[di].InFH,ax ; save file handle ;AC000;
1614 mov bx,ax ; get ready for seeks
1615 mov ax,(LSeek SHL 8) + LSeek_EOF ; seek relative to eof
1616 xor cx,cx ; zero offset
1617 xor dx,dx ; zero offset
1618 INT 21h ; find End Of File to get offsets
1619 ; LSeak + LSeek_EOF <4202>
1620 mov es:[di].LenLow,ax ; save low part of size ;AC000;
1621 mov es:[di].LenHigh,dx ; save high part of size ;AC000;
1622 xor dx,dx ; zero offset
1623 mov ax,(LSeek SHL 8) + LSeek_Start ; seek relative to beginning
1624 INT 21h ; LSeak + LSeek_Start <4200>
1625 mov ax,(File_Times SHL 8) + 0 ; find last write time
1626 INT 21h ; File_Times + not_used <5700>
1627 mov es:[di].FTime,cx ; save time ;AC000;
1628 mov es:[di].FDate,dx ; save date ;AC000;
1634 mov ah,DOS_error ; load return code (DOS extended error);AC000;
1643 BREAK <SYS - Fill_Memory >
1644 ;******************* START OF SPECIFICATIONS ***********************************
1645 ;Routine name: Fill_Memory
1646 ;*******************************************************************************
1648 ;Description: Read in as much of IBMBIOS and IBMDOS as room permits
1650 ;Called Procedures: None
1654 ;Output: no error - CF = 0
1657 ;Change History: Created 5/01/87 FG
1659 ;******************* END OF SPECIFICATIONS *************************************
1660 ;******************+ START OF PSEUDOCODE +**************************************
1664 ; get length of buffer
1665 ; get BIOS source handle
1666 ; point to beginning of buffer
1667 ; save total buffer length
1668 ; if < 64k to read and
1669 ; if amount to read < buffer
1670 ; set length to IBMBIO length
1672 ; if amount to read > 0
1673 ; read the file (INT21 read +00 <3F00>)
1676 ; clear error flag (CF)
1679 ; if not all of file read
1683 ; update pointer for dos read
1685 ; calculate remainder
1686 ; get DOS source handle
1687 ; if < 64k to read and
1688 ; if amount to read < buffer
1689 ; set length to IBMBIO length
1691 ; read the file (INT21 read +00 <3F00>)
1693 ; if all of file read
1694 ; update pointer for DOS read
1702 ;******************- END OF PSEUDOCODE -**************************************
1706 Fill_Memory PROC NEAR
1708 mov ax,4200h ; LSEEK to end of last read ;AN001;
1709 mov bx,BIOSInFH ; ;AN001;
1710 mov cx,BIOSPos[2] ; ;AN001;
1711 mov dx,BIOSPos[0] ; ;AN001;
1713 mov ax,4200h ; LSEEK to end of last read ;AN001;
1714 mov bx,DOSInFH ; ;AN001;
1715 mov cx,DOSPos[2] ; ;AN001;
1716 mov dx,DOSPos[0] ; ;AN001;
1719 mov cx,cbBuf ; get length of buffer
1720 mov bx,BIOSInFH ; get bios source handle
1721 mov dx,OFFSET BUF+FAT_BUF ; point to beginning of buffer
1722 ; past area to read in boot rec
1723 push cx ; save away total length
1724 cmp BIOSLenHigh,0 ; is there < 64K to read?
1726 ; $if e,and ; if so - or................... ;AC000;
1729 cmp BIOSLenLow,cx ; more left to read? :
1730 ; ie: is amount to read < buffer
1731 ; $if b ; if amount to read < buffer..: ;AC000;
1734 mov cx,BIOSLenLow ; set length to IBMBIO length
1739 cmp cx,0 ; is there anything to read?
1741 ; $if a ; if so - read it
1744 mov ah,Read ; read the file
1745 int 21h ; read + not_used <3F00>)
1747 ; $else ; don't bother
1757 ; $if c,or ; if error or.................. ;AC000;
1760 cmp ax,cx ; Did we get it all? :
1762 ; $if nz ; if not all of file read.....: ;AC000;
1766 pop cx ; recover size
1773 add BIOSPos[0],ax ; save amount read for later lseek ;AN001;
1774 adc BIOSPos[2],0 ; save amount read for later lseek ;AN001;
1776 add dx,ax ; update pointer for DOS Read
1777 mov pDOS,dx ; point to beginning of DOS
1778 sub BIOSLenLow,ax ; decrement remaining
1779 sbb BIOSLenHigh,0 ; do 32 bit
1780 pop cx ; get original length
1781 sub cx,ax ; this much is left
1782 mov bx,DOSInFH ; get bios source handle
1783 cmp DOSLenHigh,0 ; > 64K to read?
1784 ; $if e,and ; if < 64k to read and.......... ;AC000;
1786 cmp DOSLenLow,cx ; is amount to read < buffer :
1788 ; $if b ; if its less .................: ;AC000;
1791 mov cx,DOSLenLow ; set length to IBMDOS length
1796 mov ah,Read ; read the file
1797 INT 21h ; read + not_used <3F00>)
1799 ; $if nc,and ; no error and................... ;AC000;
1802 cmp ax,cx ; is all of file read ? :
1804 ; $if z ; all of file read..............: ;AC000;
1807 add DOSPos[0],ax ; save amount read for later lseek ;AN001;
1808 adc DOSPos[2],0 ; save amount read for later lseek ;AN001;
1810 add dx,ax ; update pointer for DOS Read
1811 mov pDOSEnd,DX ; point to End of dos DOS
1812 sub DOSLenLow,AX ; decrement remaining
1813 sbb DOSLenHigh,0 ; do 32 bit arithmetic
1814 clc ; reset fail flag
1826 BREAK <SYS - Check_SYS_Conditions >
1827 ;******************* START OF SPECIFICATIONS ***********************************
1828 ;Routine name: Check_SYS_Conditions
1829 ;*******************************************************************************
1831 ;Description: Verify that the target disk is in a state that a SYS to it will
1832 ; be allowed. If an error occurs in any of the called routines,
1833 ; the return code will already be loaded by the failing routine.
1835 ;Called Procedures: Verify_File_System
1837 ; Verify_File_Location
1838 ; Determine_Free_Space
1842 ;Output: no error - CF = 0
1843 ; error - CF = 1 AX = return code (message #)
1845 ;Change History: Created 5/01/87 FG
1847 ;******************* END OF SPECIFICATIONS *************************************
1848 ;******************+ START OF PSEUDOCODE +**************************************
1850 ; START Check_SYS_Conditions
1852 ; verify target is a FAT file system (CALL Verify_File_System)
1854 ; load root directory of target (CALL Read_Directory)
1856 ; check that IBMBIO,IBMDOS are in right place (CALL Verify_File_Location)
1858 ; check for sufficient space for system files (CALL Determine_Free_Space)
1860 ; load return code (success)
1865 ; END Check_SYS_Conditions
1867 ;******************- END OF PSEUDOCODE -**************************************
1869 public Check_SYS_Conditions
1871 Check_SYS_Conditions PROC NEAR
1873 call Verify_File_System ; verify target is a FAT file system ;AN000;
1875 ; $if nc,and ; no error and ;AN000;
1878 call Read_Directory ; load root directory of target ;AN000;
1880 ; $if nc,and ; no error and ;AN000;
1883 call Verify_File_Location ; check that IBMBIO,IBMDOS are in right;AN000;
1885 ; $if nc ; no error and ;AN000;
1888 call Determine_Free_Space ; check if enough space for system file;AN000;
1895 ENDPROC Check_SYS_Conditions
1897 BREAK <SYS - Verify_File_System >
1898 ;******************* START OF SPECIFICATIONS ***********************************
1899 ;Routine name: Verify_File_System
1900 ;*******************************************************************************
1902 ;Description: Get the file system for the specified drive, then compare to
1903 ; FAT. If not, issue message and exit. Must ensure that target
1904 ; drive has media in it before this routine is called
1906 ;Note: This routine contains code that is specifically required for
1907 ; operation on DOS 3.3. This code must be removed for later releases
1910 ;Called Procedures: None
1912 ;Input: Drive Number (0=default, 1=A, 2=B) in BL
1914 ;Output: no error - CF = 0
1917 ; AH = utility messages
1918 ; AL = 15d - Not able to SYS to xxx file system
1919 ; CX = 1 - only one substitution
1920 ; DS:SI = sublist for substitution
1922 ;Change History: Created 5/01/87 FG
1924 ;******************* END OF SPECIFICATIONS *************************************
1925 ;******************+ START OF PSEUDOCODE +**************************************
1927 ; START Verify_File_System
1930 ; load drive id (BL)
1931 ; get_extended_device_parameters (INT21 IOCtl + 0Dh <440D> CX=086E) for drive
1932 ; if error - check if old version destination
1933 ; find out what the error was (CALL Get_DOS_Error)
1934 ; if not old version error
1935 ; load return code (DOS Extended Error Class)
1941 ; if returned file system type = "FAT12
" or
1942 ; if returned file system type = "FAT16
"
1945 ; indicate insert required
1946 ; set up pointer for insert - sublist
1947 ; load return code (Unable to SYS to xxxxxxxx file system)
1955 ; END Verify_File_System
1957 ;******************- END OF PSEUDOCODE -**************************************
1959 public Verify_File_System
1961 Verify_File_System PROC NEAR
1963 cmp DOS_VER,0 ; running on current DOS ? ;AN019;
1964 ; $if e ; if we are ;AN019;
1966 mov bl,TargDrvNum ; load drive id (BL) ;AN000;
1967 lea dx,IOCtl_Buf ; point to output buffer ;AN000;
1968 mov ax,(GetSetMediaID shl 8) + 0 ; get volid, ser# and filetype ;AC019;
1969 INT 21h ; INT 21 GetSetMediaID request <6900> ;AC019;
1971 ; $if c ; error - check if old version dest ;AN000;
1974 call Get_DOS_Error ; find out what the error was ;AN000;
1976 cmp al,old_type_media ; is it IBM but < 4.0 ? ;AN000;
1978 ; $if ne ; not old version error ;AN000;
1981 mov ah,DOS_error ; load return code (DOS Extended Error);AN000;
1982 stc ; set fail flag ;AN000;
1988 clc ; reset fail flag ;AN000;
1993 ; $else ; ELSE it is => 4.00 ;AN000;
1997 lea si,IOCtl_File_Sys ; see if file type is fat12 ;AN000;
1998 lea di,fat_12 ; ;AN000;
1999 mov cx,file_sys_size ; ;AN000;
2001 repe cmpsb ; ;AN000;
2002 cmp cx,3 ; did it fail at the 2 in fat12 ? ;AN000;
2004 ; $if e,and ; if it did and............ ;AN000;
2007 cmp BYTE PTR ds:[si-1],"6" ; was it a 6 ? : ;AN000;
2009 ; $if e ; if it was...............: ;AN000;
2012 repe cmpsb ; then keep going ;AN000;
2017 cmp cx,0 ; did we reach the end ? ;AN000;
2019 ; $if e ; if we did it was "FAT12
" or ;AN000;
2021 ; "FAT16
" so its OK to SYS
2023 clc ; reset fail flag ;AN000;
2029 lea di,File_Sys_End ; set up pointer to end of insert ;AN000;
2030 dec di ; back up to last character ;AN000;
2031 mov cx,file_sys_size ; strip off trailing blanks ;AN017;
2032 mov al," " ; strip off trailing blanks ;AN017;
2033 std ; scan backwards ;AN017;
2034 repe scas IOCTL_File_Sys ; ;AN017;
2035 cld ; stops at 2 past last " " ;AN017;
2036 inc di ; 1 past ;AN017;
2037 inc di ; last (first) blank ;AN017;
2038 xor al,al ; make it an ASCIIZ ;AN017;
2039 stos IOCTL_File_Sys ; ;AN017;
2040 lea si,IOCTL_File_Sys ; set up pointer to the insert ;AN000;
2041 mov [insert_ptr_off],si ; ;AN017;
2042 mov [insert_ptr_seg],ds ; ;AN017;
2043 lea si,sublist ; set pointer to SUBLIST ;AN017;
2044 mov ax,(util_C shl 8) + cant_sys ; load return code ;AN000;
2045 ; - Unable to SYS to xxx file system
2046 stc ; set fail flag ;AN000;
2054 ; $else ; not running on current DOS ;AN019;
2058 clc ; keep going ;AN019;
2060 ; $endif ; running on current DOS ;AN019;
2065 ENDPROC Verify_File_System
2067 BREAK <SYS - Read_Directory >
2068 ;******************* START OF SPECIFICATIONS ***********************************
2069 ;Routine name: Read_Directory
2070 ;*******************************************************************************
2072 ;Description: Read in first sector of directory. The reason that we do the
2073 ; direct read of the directory is the find first/next or search
2074 ; first/next do an exclusive search for volume labels. By using
2075 ; these CALLs, there is no way to determine if a volume label
2076 ; occupies the first location in the directory. Hence we get sleazy
2077 ; and read the directory directly (no pun intended) to get this
2078 ; info. Only read in the first sector of directory. Also, this
2079 ; ensures there is a media in the drive.
2081 ;CALLed Procedures: Prompt_for_Media, Find_DPB
2085 ;Output: no error - CF = 0
2086 ; error - CF = 1 AX = return code (message #)
2088 ;Change History: Created 5/01/87 FG
2090 ;******************* END OF SPECIFICATIONS *************************************
2091 ;******************+ START OF PSEUDOCODE +**************************************
2093 ; START Read_Directory
2095 ; set up drive letter in destignation filespecs
2096 ; call Find_DPB to get directory location
2097 ; load first DIR sector number
2098 ; point at buffer for directory
2099 ; read first sector of directory (INT 25h)
2102 ; END Read_Directory
2104 ;******************- END OF PSEUDOCODE -**************************************
2106 public Read_Directory
2108 Read_Directory PROC NEAR
2110 mov al,TargDrv ; set up drive letter in destignation filespecs
2111 mov BIOSName,al ; point names at destination drive
2114 MOV DL,TargDrvNum ; load drive
2115 PUSH DS ; save register
2116 call Find_DPB ; initalize DPB parameters
2120 xor ax,ax ; request a read
2121 mov dx,[first_dir_sector] ; read starting dir sector
2122 mov [packet],dx ; get starting dir sector ;AN001;
2123 mov bx,offset DIR_SECTOR
2124 mov PACKET_BUFFER[0],bx ; ;AN001;
2125 mov PACKET_BUFFER[2],ds ; ;AN001;
2126 mov word ptr [packet_sectors],1 ; ;AN001;
2127 call Direct_Access ; to read the sector
2129 mov ax, (util_B shl 8) + write_fail ; load message ;AC000;
2130 ; - Write failure, diskette unuseable
2131 ; in case an error occured
2134 ENDPROC Read_Directory
2136 BREAK <SYS - Verify_File_Location >
2137 ;******************* START OF SPECIFICATIONS ***********************************
2138 ;Routine name: Verify_File_Location
2139 ;*******************************************************************************
2141 ;Last Update: 09/22/87
2143 ;Description: Determines if IBMBIO and IBMDOS are the first two directory
2144 ; entries, or if these entries are empty. If so, find the size
2145 ; of the files if they exist. If spaces not empty and don't
2146 ; contain IBMBIO and IBMDOS, set fail flag and load return code.
2147 ; Also determines if existing IBMBIO starts in cluster 2. If not
2148 ; set fail flag and load return code.
2150 ;CALLed Procedures: None
2152 ;Input: DIR in BUFFER
2154 ;Output: no error - CF = 0
2157 ; AH = utility \1dessages
2158 ; AL = 8 - No room for system on destination disk
2159 ; 9 - Incompatible system size
2161 ;Change History: Created 5/01/87 FG
2163 ;******************* END OF SPECIFICATIONS *************************************
2164 ;******************+ START OF PSEUDOCODE +**************************************
2166 ; START Verify_File_Location
2168 ; if all files deleted (Dir_Name in dir is 00h)
2171 ; if first file deleted (Dir_Name is 0E5h)
2174 ; if first file IBMBIO.COM
2176 ; indicate we found IBMBIO
2179 ; call Move_DIR_Entry
2183 ; if no error so far and
2187 ; if no error so far
2188 ; if all files deleted starting at second location or
2189 ; if second file deleted (Dir_Name is 0E5h)
2192 ; if second file IBMDOS.COM
2194 ; indicate we found IBMDOS
2197 ; call Move_DIR_Entry
2205 ; END Verify_File_Location
2206 ;******************- END OF PSEUDOCODE -**************************************
2208 public Verify_File_Location
2210 Verify_File_Location PROC NEAR
2211 ;---------------------------------------
2212 ; Now see if the first two directory
2213 ; entries are available...
2214 ; First check for being free:
2215 ;---------------------------------------
2216 mov bp,OFFSET DIR_SECTOR
2218 cmp BYTE PTR [si],empty ; empty dir?
2220 ; $if e,or ; if all files deleted ;AC012;
2222 ; (Dir_Name in dir is 00h)
2224 cmp BYTE PTR [si],deleted ; is first file deleted ?
2226 ; $if e ; if it is ;AC012;
2229 ; (Dir_Name is 0E5h)................:
2230 clc ; clear error flag ;AN003;
2231 call Free_Cluster ; check the cluster chain just in case ;AC012;
2233 ; $else long ; not empty ;AC000;
2236 ;---------------------------------------
2237 ; The first entry is not free. See if
2238 ; the BIOS is there.
2239 ;---------------------------------------
2240 mov di,OFFSET FCBBIO ; pointer to name
2241 mov cx,file_spec_length ; length of name
2243 rep cmpsb ; check it
2245 ; $if e ; first file IBMBIO.COM ;AC000;
2248 dec BIOSEntFree ; indicate we found IBMBIO ( = 0)
2250 mov ax,word ptr ds:[si].dir_size_l ; Get the size of IBMBIO ;AC000;
2251 mov word ptr IBMBIO_Low,ax
2252 mov ax,word ptr ds:[si].dir_size_h ; ;AC000;
2253 mov word ptr IBMBIO_High,ax
2254 cmp ds:[si].dir_first,2 ; does IBMBIO own Clust 2? ;AC005;
2255 ; $if e ; if so ;AC005;
2257 inc [bio_owns_it] ; - keep track ;AC005;
2261 call Free_Cluster ; ;AN003;
2263 ; $else ; its not IBMBIO ;AC000;
2267 mov si,bp ; restore pointer to start of entry ;AN003;
2268 call Move_DIR_Entry ; move the entry out of the way ;AN003;
2270 ; $if nc,and ; ;AN003;
2273 call Free_Cluster ; make sure reqd. clusters are free ;AN003;
2284 mov ax,(util_B shl 8) + no_room ; load return code in case we fail;AN000;
2285 stc ; - No room for system on dest... ;AC000;
2296 ;---------------------------------------
2297 ; Check the second entry
2298 ;---------------------------------------
2300 ; $if nc ; if no errors so far ;AC000;
2303 ; ensure that the first sector of root ;AN003;
2305 mov ax,[first_dir_sector] ; get starting dir sector ;AN001;
2306 mov packet,ax ; ;AN001;
2307 mov [packet_buffer],offset DIR_SECTOR ; ;AN001;
2308 mov word ptr [packet_sectors],1 ; ;AN001;
2309 xor ax,ax ; request a read
2310 call Direct_Access ; to read the root
2315 add bp,TYPE dir_entry ; ;AC000;
2317 mov ax,(util_B shl 8) + no_room ; load return code in case we fail ;AC000;
2318 ; - No room for system on dest..
2319 cmp BYTE PTR [si],empty ; empty dir entry?
2321 ; $if e,or ; if deleted starting at 2nd entry or. ;AC000;
2324 cmp BYTE PTR [si],deleted ; deleted ? :
2326 ; $if e ; if deleted (0E5h)...................:;AC000;
2330 clc ; reset fail flag
2336 ; This entry is not free.
2337 mov di,OFFSET FCBDOS ; see if it is IBMDOS
2338 mov cx,file_spec_length ; length of name
2339 rep cmpsb ; compare it
2340 mov si,bp ; restore pointer to start ;AC000;
2342 ; $if e ; if second file is IBMDOS.COM. ;AC000;
2345 dec DOSEntFree ; indicate we found IBMDOS
2346 mov ax,word ptr ds:[si].dir_size_l ; Get the size of ;AC000;
2347 mov word ptr IBMDOS_Low,ax ; file for IBMDOS
2348 mov ax,word ptr ds:[si].dir_size_h ; ;AC000;
2349 mov word ptr IBMDOS_High,ax
2350 clc ; reset fail flag ;AN000;
2352 ; $else ; error condition ;AC000;
2356 call Move_DIR_Entry ; ;AN003;
2367 mov ax,(util_B shl 8) + no_room ; load return code in case we fail ;AN000;
2376 ENDPROC Verify_File_Location
2378 BREAK <SYS - Determine_Free_Space >
2379 ;******************* START OF SPECIFICATIONS ***********************************
2380 ;Routine name: Determine_Free_Space
2381 ;*******************************************************************************
2383 ;Last Update: 3/18/87
2385 ;Description: Determine if there is enough space on the disk, given the free
2386 ; space and the space taken up by IBMBIO and IBMDOS to install the
2387 ; new IBMBIO and IBMDOS. Routine will set fail flag and load return
2388 ; code if there is not enough room.
2390 ; Here we make some VERY IMPORTANT assumptions.
2392 ; 1) If IBMBIO exists on the disk currently, we assume it is in the
2393 ; correct place, i.e. at the front of the data area & contiguous.
2394 ; 2) The stub loader portion of IBMBIO is less than 2048 bytes long.
2395 ; This number comes about by assuming we will never overlay
2396 ; anything smaller than 1920 bytes (DOS 1.10 IBMBIO size). This
2397 ; can be expanded to 2048 if we also assume the smallest possible
2398 ; cluster length is 512 bytes.
2400 ; Therefore, if we have an empty disk or IBMBIO exists, then we have
2401 ; enough contiguous room to install the portion of IBMBIO that
2402 ; requires itself to be contiguous.
2404 ;CALLed Procedures: None
2408 ;Output: no error - CF = 0
2411 ; AH = utility messages
2412 ; AL = 8d - No room for system on destination disk
2414 ;Change History: Created 5/01/87 FG
2416 ;******************* END OF SPECIFICATIONS *************************************
2417 ;******************+ START OF PSEUDOCODE +**************************************
2419 ; START Determine_Free_Space
2421 ; get disk free space (INT21 Get_Drive_Freespace + 00 <3600>)
2422 ; compute Bytes/Cluster (32bit math required)
2423 ; convert current IBMBIO into cluster size (CALL Get_Cluster)
2424 ; convert current IBMDOS into cluster size (CALL Get_Cluster)
2425 ; get total number of clusters available
2426 ; convert new IBMBIO into cluster size (CALL Get_Cluster)
2427 ; convert new IBMDOS into cluster size (CALL Get_Cluster)
2428 ; get total number of clusters needed
2429 ; if available clusters < needed clusters
2430 ; load return code (No room for system on destination disk)
2437 ; END Determine_Free_Space
2439 ;******************- END OF PSEUDOCODE -**************************************
2441 public Determine_Free_Space
2443 Determine_Free_Space PROC NEAR
2445 mov ah,Get_Drive_Freespace ; get disk free space
2446 mov dl,TargDrvNum ; get the drive number
2447 INT 21h ; Get_Drive_Freespace <36xx>
2448 ; compute Bytes/Cluster - 16 bit math ok
2449 ; AX = sectors / cluster
2450 ; CX = bytes / sector
2451 ; BX = available clusters
2452 mul cx ; get bytes/cluster
2454 mov Bytes_Per_Cluster,ax ; save this value for Get_Clusters
2455 mov Number_Free_Clusters,bx ; save available space
2457 mov ax,IBMBIO_Low ; low result in AX, High result in DX
2459 call Get_Cluster ; convert old IBMBIO into cluster size
2461 add Number_Free_Clusters,ax ; add it to available space
2463 mov ax,IBMDOS_Low ; low result in AX, High result in DX
2465 call Get_Cluster ; convert old IBMDOS into cluster size
2467 add Number_Free_Clusters,AX ; get total number of clusters available
2469 mov ax,NEWBIO_Size_Low ; find total size of new DOS and BIOS
2470 mov dx,NEWBIO_Size_High
2472 call Get_Cluster ; convert new IBMBIO into cluster size
2474 mov Need_Clusters,ax ;save new BIO clusters
2476 mov ax,NEWDOS_Size_Low
2477 mov dx,NEWDOS_Size_High
2479 call Get_Cluster ; convert new IBMDOS into cluster size
2481 add AX,Need_Clusters ; get total number of clusters needed
2483 cmp AX,Number_Free_Clusters ;Now see if there is enough room
2484 ; for all of it on the disk
2485 ; $if a ; if needed > available clusters ;AC000;
2488 mov ax,(util_B shl 8) + no_room ; load return code ;AC000;
2489 ; - No room for system on dest..
2496 clc ; reset fail flag
2503 ENDPROC Determine_Free_Space
2505 BREAK <SYS - Get_Cluster >
2506 ;******************* START OF SPECIFICATIONS ***********************************
2507 ;Routine name: Get_Cluster
2508 ;*******************************************************************************
2510 ;Description: Convert bytes to clusters, rounding up to the next
2511 ; cluster size if needed.
2513 ;Called Procedures: None
2515 ;Input: (AX) = Number of bytes
2516 ; Bytes_Per_Cluster = # of bytes per cluster
2518 ;Output: (AX) = Number of clusters
2520 ;Registers used: AX BX DX
2522 ;Change History: Created 5/01/87 FG
2524 ;******************* END OF SPECIFICATIONS *************************************
2525 ;******************+ START OF PSEUDOCODE +**************************************
2529 ; divide size by bytes_per_cluster
2530 ; if there is a remainder
2531 ; round up to next cluster
2537 ;******************- END OF PSEUDOCODE -**************************************
2541 Get_Cluster PROC NEAR
2543 mov bx,Bytes_Per_Cluster ; Bytes/cluster
2544 div bx ; divide size by bytes_per_cluster
2545 cmp dx,0 ; is there a remainder in DX?
2547 ; $if ne ; if there is a remainder ;AC000;
2549 ; we have another cluster to round up
2550 inc ax ; round up to next cluster
2559 BREAK <SYS - Do_SYS >
2560 ;******************* START OF SPECIFICATIONS ***********************************
2561 ;Routine name: Do_SYS
2562 ;*******************************************************************************
2564 ;Description: Control routine to handle the transfer of system files from
2565 ; memory to target drive.
2567 ;Called Procedures: Create_System
2571 ;Input: IBMBIO_Size_Loaded
2572 ; IBMDOS_Size_Loaded
2574 ;Output: no error - CF = 0
2575 ; error - CF = 1 AX = return code (message #)
2577 ;Change History: Created 5/01/87 FG
2579 ;******************* END OF SPECIFICATIONS *************************************
2580 ;******************+ START OF PSEUDOCODE +**************************************
2584 ; create new IBMBIO and IBMDOS, in place if exist (CALL CREATE_SYSTEM)
2587 ; write out contents of memory to file (CALL Dump_Memory)
2588 ; load error return code (assume error)
2590 ; exit if if all files copied
2593 ; read in file from source (CALL Fill_Memory)
2594 ; load error return code (assume error)
2604 ;******************- END OF PSEUDOCODE -**************************************
2610 call CREATE_SYSTEM ; create IBMBIO and IBMDOS, in place ;AN000;
2612 ; $if nc ; no error ;AC000;
2616 lds bx,THIS_DPB ; set up pointer to DPB ;AC000;
2617 mov [bx.dpb_next_free],2 ; reset Allocation to start of disk ;AC000;
2618 pop ds ; so BIOS goes in right place!
2623 call Dump_Memory ; write out contents of memory to file
2625 mov ax,(util_B shl 8) + no_room ; load error RC (assume error) ;AC000;
2627 ; $leave c ; quit if error ;AC000;
2630 mov ax,DOSLenHigh ; more DOS to move ?
2631 or AX,DOSLenLow ; more low dos
2632 or AX,BIOSLenHigh ; more high BIOS
2633 or AX,BIOSLenLow ; more low BIOS
2635 ; $exitif z ; if all files copied ;AC000;
2638 clc ; reset fail flag ;AC000;
2644 call get_rest_of_system
2646 mov ax,(util_B shl 8) + no_room ; load error RC (assume error) ;AC000;
2648 ; $leave c ; if error ;AC000;
2651 ; $endloop ; ;AC000;
2655 ; $endsrch ; ;AC000;
2665 PUBLIC Get_Rest_of_System
2667 Get_Rest_of_System Proc near
2671 mov bx,BIOSOutFH ; ;AN001;
2672 mov ah,Close ; ;AN001;
2675 mov bx,DOSOutFH ; ;AN001;
2676 mov ah,Close ; ;AN001;
2679 mov dx,offset SourceBIOSName ; ;AN001;
2680 mov ax,(OPEN SHL 8) + not_used ; open file for read
2684 mov dx,offset SourceDOSName ; ;AN001;
2685 mov ax,(OPEN SHL 8) + not_used ; open file for read
2689 call Fill_Memory ; read in file from source
2691 mov bx,BIOSInFH ; ;AN001;
2692 mov ah,Close ; ;AN001;
2695 mov bx,DOSInFH ; ;AN001;
2696 mov ah,Close ; ;AN001;
2699 mov dx,offset BIOSName ; ;AN001;
2700 mov ax,(Open shl 8) + 2 ; Open file
2704 mov dx,offset DOSName ; ;AN001;
2705 mov ax,(Open shl 8) + 2 ; Open file
2713 endproc get_rest_of_system
2715 BREAK <SYS - Create_System >
2716 ;******************* START OF SPECIFICATIONS ***********************************
2717 ;Routine name: Create_System
2718 ;*******************************************************************************
2722 ;Called Procedures: Create_File
2726 ;Output: IBMBIO_Handle
2729 ;Change History: Created 5/01/87 FG
2731 ;******************* END OF SPECIFICATIONS *************************************
2732 ;******************+ START OF PSEUDOCODE +**************************************
2734 ; START Create_System
2736 ; create IBMBIO (CALL Create_File)
2738 ; save handle to IBMBIO_Handle
2739 ; create IBMDOS (CALL Create_File)
2741 ; save handle to IBMDOS_Handle
2748 ;******************- END OF PSEUDOCODE -**************************************
2750 public Create_System
2752 Create_System PROC NEAR
2755 mov dx,OFFSET BIOSName ; point to IBMBIO ASCIIZ string
2756 mov al,[BIOSEntFree] ; get status of IBMBIO ;AN006;
2757 mov [EntryFree],al ; update file status (0 = found,1 = not;AN006;
2759 call Create_File ; create IBMBIO ;AN000;
2761 ; $if nc,and ; no error and ;AC000;
2764 mov BIOSOutFH,ax ; save handle to IBMBIO_Handle
2765 mov dx,OFFSET DOSName ; pointer to IBMDOS ASCIIZ string
2766 mov al,[DOSEntFree] ; get status of IBMDOS ;AN006;
2767 mov [EntryFree],al ; update file status (0 = found,1 = not;AN006;
2769 call Create_File ; create IBMDOS ;AN000;
2771 ; $if nc ; no error ;AC000;
2774 mov DOSOutFH,ax ; save handle to IBMDOS_Handle
2781 ENDPROC Create_System
2783 BREAK <SYS - Create_File >
2784 ;******************* START OF SPECIFICATIONS ***********************************
2785 ;Routine name: Create_File
2786 ;*******************************************************************************
2788 ;Last Update: 9/23/87
2790 ;Description: Remove the read only attribute from IBMBIO and IBMDOS. If
2791 ; file not found error occurs, it is okay, because it just
2792 ; means the file was not there. Do create with read-only
2793 ; hidden, and system file attributes. This is an in place
2794 ; create if the file exists already.
2797 ;Called Procedures: None
2799 ;Input: DS:DX = pointer to ASCIIZ string for file create
2801 ;Output: no error - CF = 0
2805 ; AH = extended DOS errors
2807 ;Change History: Created 5/01/87 FG
2809 ;******************* END OF SPECIFICATIONS *************************************
2810 ;******************+ START OF PSEUDOCODE +**************************************
2814 ; set file attributes to 0 (INT21 CHMod + SetAtrib <4301>)
2816 ; if error = file not found and
2817 ; ext Open file with attributes of 7 (INT21 ExtOpen + SetAtrib <6C12> CX=7)
2821 ; load return code (DOS Extended Error)
2828 ;******************- END OF PSEUDOCODE -**************************************
2832 Create_File PROC NEAR
2834 mov ax,(CHMod shl 8) + SetAtrib ; set file attributes to 0
2835 xor cx,cx ; set attributes to 0
2836 mov [open_off],dx ; save pointer to ASCIIZ for OPEN
2837 INT 21h ; CHMod + SetAtrib <4301>)
2839 ; $if nc ; no error ;AC000;
2842 cmp [EntryFree],0 ; is file in the correct spot? ;AN006;
2843 ; $if ne ; if it is not - we have a problem ;AN006;
2845 mov dx,[open_off] ; get pointer to ASCIIZ for UNLINK ;AN006;
2846 mov ax,(UNLINK shl 8) ; UNLINK the file
2847 INT 21h ; UNLINK <4100>) ;AN006;
2850 ; $else ; - check the error ;AN006;
2853 call Get_DOS_Error ; find out what went wrong ;AN000;
2854 cmp al,file_not_found ; not there?
2856 ; $if e ; IBMBIO was not there ;AC000;
2858 clc ; ok to open ;AC000;
2862 stc ; some other error - quit ;AC000;
2867 ; $if nc ; if no error ;AC006;
2870 lds si,OPEN_PARMS ; ;AC005;
2871 xor cx,cx ; DOS system file atributes ;AC005;
2872 cmp DOS_VER,0 ; running on current DOS ? ;AN019;
2874 ; $if ne ; if on old DOS ;AN019;
2876 mov dx,si ; DS:DX - file name ;AN019;
2877 mov ax,(Creat shl 8) + 0 ; Create file <3D00> ;AN019;
2883 mov bx,open_mode ; set up for mode ;AN000;
2884 mov dx,(openit shl 4) + replaceit ; create if does not exist, ;AN000;
2885 ; replace it if it does
2886 mov ax,(ExtOpen shl 8) + 0 ; ext Open file with attributes of 0 ;AN000;
2887 ; ExtOpen + SetAtrib <6C12> CX=0
2891 INT 21h ; do the open
2896 ; $if c ; if error ;AN000;
2899 call Get_DOS_Error ; find out what went wrong ;AN000;
2900 mov ah,DOS_error ; load return code (DOS Extended Error);AN000;
2910 BREAK <SYS - Dump_Memory >
2911 ;******************* START OF SPECIFICATIONS ***********************************
2912 ;Routine name: Dump_Memory
2913 ;*******************************************************************************
2915 ;Description: Write out as much of IBMBIOS and IBMDOS as is in memory.
2917 ;Called Procedures: None
2921 ;Output: no error - CF = 0
2924 ;Change History: Created 5/01/87 FG
2926 ;******************* END OF SPECIFICATIONS *************************************
2927 ;******************+ START OF PSEUDOCODE +**************************************
2931 ; get pointer to start of buffer
2932 ; subtract the start of IBMDOS
2933 ; if lenght is non-zero and . . . . . . . . . . . . . . . .
2934 ; load IBMBIOS handle :
2935 ; write out IBMBIOS (INT21 Write + 00 <4000>) :
2936 ; if no error and . . . . . . . . . . . . . . . . . . . . :
2937 ; if not all data written . . . . . . . . . . . . . . . . :
2940 ; if no error so far
2941 ; get beginning of dos
2942 ; subtract end of dos
2943 ; if lenght is non-zero and
2944 ; load IBMDOS handle
2945 ; write out IBMDOS (INT21 Write + 00 <4000>)
2947 ; if not all data written . . . . . . . . . . . . . . . . :
2955 ;******************- END OF PSEUDOCODE -**************************************
2959 Dump_Memory PROC NEAR
2961 mov ax,4202h ; LSEEK to end of file ;AN001;
2962 mov bx,BIOSOutFH ; ;AN001;
2966 mov ax,4202h ; LSEEK to end of file ;AN001;
2967 mov bx,DOSOutFH ; ;AN001;
2972 mov dx,OFFSET BUF+FAT_BUF ; get pointer to start of buffer
2973 mov cx,pDOS ; beginning of next guy
2974 sub cx,dx ; difference is length
2976 ; $if nz,and ; if lenght is non-zero and....... ;AC000;
2979 mov bx,BIOSOutFH ; load IBMBIOS handle :
2980 mov ah,Write ; write out IBMBIOS :
2981 INT 21h ; Write + 00 <4000> :
2983 ; $if nc,and ; if no error and.................: ;AC000;
2986 cmp ax,cx ; Did it work? :
2988 ; $if ne ; all data written................: ;AC000;
2996 ; $if nc ; if no error so far ;AC000;
2999 mov dx,pDOS ; get beginning of dos
3000 mov cx,pDOSEnd ; subtract end of dos
3001 sub cx,dx ; difference is length
3003 ; $if nz,and ; if lenght is non-zero and........ ;AC000;
3006 mov bx,DOSOutFH ; load IBMDOS handle :
3007 mov ah,Write ; write out IBMDOS :
3008 INT 21h ; Write + 00 <4000> :
3010 ; $if nc,and ; if no error.....................: ;AC000;
3013 cmp ax,cx ; Did it work? :
3015 ; $if ne ; all data written................: ;AC000;
3031 BREAK <SYS - Do_End >
3032 ;******************* START OF SPECIFICATIONS ***********************************
3033 ;Routine name: Do_End
3034 ;*******************************************************************************
3036 ;Description: Finish off with IBMBIOS and IBMDOS
3038 ;Called Procedures: Close_File
3043 ;Output: no error - CF = 0
3045 ;Change History: Created 5/01/87 FG
3047 ;******************* END OF SPECIFICATIONS *************************************
3048 ;******************+ START OF PSEUDOCODE +**************************************
3052 ; finish off and close IBMBIOS and IBMDOS (CALL Close_Files)
3053 ; update boot record (CALL Write_Boot_Record)
3058 ;******************- END OF PSEUDOCODE -**************************************
3064 call Close_File ; finish off & close IBMBIOS and IBMDOS;AN000;
3066 call Write_Boot_Record ; update boot record ;AN000;
3072 BREAK <SYS - Close_File >
3073 ;******************* START OF SPECIFICATIONS ***********************************
3074 ;Routine name: Close_File
3075 ;*******************************************************************************
3077 ;Description: Set date and time on IBMBIOS and IBMDOS and close
3080 ;Called Procedures: None
3082 ;Input: BIOSTime, BIOSOutFH, DOSTime. DOSOutFH
3084 ;Output: IBMBIOS and IBMDOS closed
3086 ;Change History: Created 5/01/87 FG
3088 ;******************* END OF SPECIFICATIONS *************************************
3089 ;******************+ START OF PSEUDOCODE +**************************************
3093 ; load IBMBIOS time and date
3094 ; load IBMBIOS handle
3095 ; update file times (INT21 File_Times + 01 <5701>)
3096 ; close file (INT21 Close + 00 <3E00>)
3097 ; load IBMDOS time and date
3098 ; load IBMDOS handle
3099 ; update file times (INT21 File_Times + 01 <5701>)
3100 ; close file (INT21 Close + 00 <3E00>)
3105 ;******************- END OF PSEUDOCODE -**************************************
3109 Close_File PROC NEAR
3111 mov cx,BIOSTime ; load IBMBIOS time and date
3113 mov bx,BIOSOutFH ; load IBMBIOS handle
3114 mov ax,(File_Times SHL 8) + set ; update file times
3115 INT 21h ; File_Times + 01 <5701>
3116 mov ah,Close ; close file IBMBIO
3117 INT 21h ; Close + not_used <3Exx>
3118 mov cx,DOSTime ; load IBMDOS time and date
3120 mov bx,DOSOutFH ; load IBMDOS handle
3121 mov ax,(File_Times SHL 8) + set ; update file times
3122 INT 21h ; File_Times + 01 <5701>
3123 mov ah,Close ; close file IBMDOS
3124 INT 21h ; Close + not_used <3Exx>
3126 mov dx,offset BIOSName ; ;AN001;
3127 mov ax,(CHMod shl 8) + SetAtrib ; set file attributes to 0
3128 mov cx,DOS_system_atrib ; DOS system file atributes
3129 INT 21h ; CHMod + SetAtrib <4301>)
3131 mov dx,offset DOSName ; ;AN001;
3132 mov ax,(CHMod shl 8) + SetAtrib ; set file attributes to 0
3133 mov cx,DOS_system_atrib ; DOS system file atributes
3134 INT 21h ; CHMod + SetAtrib <4301>)
3140 BREAK <SYS - Write_Boot_Record >
3141 ;******************* START OF SPECIFICATIONS ***********************************
3142 ;Routine name: Write_Boot_Record
3143 ;*******************************************************************************
3145 ;Description: Get a best guess EBPB and get the Media ID or fill the
3146 ; information in manually. Write out the canned boot record
3147 ; and then make IOCtl calls to set the EBPB and Media ID.
3149 ;Called Procedures: Create_Serial_ID
3153 ;Output: Boot record on destination media is installed.
3155 ;Change History: Created 5/01/87 FG
3157 ;******************* END OF SPECIFICATIONS *************************************
3158 ;******************+ START OF PSEUDOCODE +**************************************
3160 ; START Write_Boot_Record
3162 ; get BPB using IOCtl Get Device Parameters (INT21 IOCtl + 0Dh <440d> CX=0860)
3163 ; get volid, ser# and file type using IOCtl Get Media ID (INT21 IOCtl + 0Dh <440d> CX=086E)
3165 ; get Extended error
3166 ; if 'unknown media' - set fields manually
3167 ; compute serial id and put in field (CALL Create_Serial_ID)
3168 ; copy in volume label if available
3169 ; set pointer to FAT1x (CALL FAT_Size)
3170 ; move file system string into Boot_System_ID field
3173 ; load return code (DOS error)
3177 ; fill in Ext_PhyDrv in canned boot record
3179 ; set BPB using data from GET BPB IOCTL
3180 ; write out canned boot record (INT26)
3181 ; set volid, ser# and file type using Set Media ID (INT21 SetID <6900> CX=084E)
3185 ; END Write_Boot_Record
3187 ;******************- END OF PSEUDOCODE -**************************************
3189 public Write_Boot_Record
3191 Write_Boot_Record PROC NEAR
3193 mov bl,TargDrvNum ; Drive number ;AN000;
3194 mov dx,offset DeviceParameters ; ;AN000;
3195 mov cx,(rawio shl 8) + get_device_parameters ; Generic IOCtl Request ;AN000;
3197 mov ax,(IOCtl shl 8) + generic_ioctl ; get BPB using Set Device Parm ;AN000;
3198 INT 21h ; IOCtl + gen_IOCtl_request <440d> ;AN000;
3200 cmp DOS_VER,0ffh ; is it DOS 3.3? ;AN019;
3201 ; $if ne ; only do a GET if DOS 4.00 ;AN019;
3203 lea dx,IOCtl_Buf ; point to output buffer ;AN000;
3204 mov ax,(GetSetMediaID shl 8) + 0 ; get volid, ser# and file type ;AC008;
3205 INT 21h ; GetSetMediaID + 0 INT 21 <6900> ;AC008;
3207 ; $if c ; error - see if its 'unknown media' ;AN000;
3210 call Get_DOS_Error ; get error ;AN000;
3211 cmp al,old_type_media ; ;AN000;
3215 stc ; do it all manually ;AN019;
3219 clc ; some other dos error occured - le ;AN019;
3220 ; $endif ; it go by ;AN019;
3228 stc ; do it all manually ;AN019;
3232 ; $if c ; if it is pre 4.00 IBM format ;AN000;
3235 call Create_Serial_ID ; compute serial id and put in field ;AN000;
3237 ; find first with type = VOLUME ID
3239 mov dx,OFFSET ExtFCB ; set up for FCB call ;AN019;
3240 mov ah,Dir_Search_First ; do a find first INT21 ;AN019;
3242 INT 21h ; Find_First <11xx> ;AN000;
3244 cmp al,0 ; was a match found? al = 0 yes ;AN019;
3246 ; $if e ; if so - copy it in ;AN000;
3249 lea si,DOS_BUFFER + 8 ; source id is in DTA ;AN019;
3250 lea di,IOCtl_Vol_ID ; destination is in IOCtl_Buf ;AN000;
3251 mov cx,file_spec_length ; move 11 bytes worth ;AN000;
3252 cld ; copy it in ;AN000;
3259 clc ; leave it as default - NO NAME
3261 ; $endif ; endif ;AN000;
3265 ; since the GET MEDIA ID failed - its
3266 ; pre 32 bit fat - so no 32 bit math
3268 call FAT_Size ; set pointer to FAT1x ;AN000;
3270 mov cx,FAT_len ; move file system string into ;AN000;
3271 ; Boot_System_ID field
3272 lea di,IOCTL_File_Sys ; update buffer ;AN000;
3281 lea si,DeviceParameters.DP_BPB
3282 lea di,boot.EXT_BOOT_BPB
3283 mov cx,type EXT_BPB_INFO
3287 cmp DeviceParameters.DP_BPB.BPB_MediaDescriptor,hard_drive ; is it Hard drive?;AC000;
3289 ; $if e ; if its a hard drive ;AC000;
3292 ; NOTE: The physical hard drive number
3293 ; is placed in the third byte from
3294 ; the end in the boot sector in
3295 ; DOS 3.2. This is a change from
3296 ; the previous DOS versions.
3298 ; fill in PhyDrv in canned boot record
3299 mov al,80h ; (set physical hard drive number) ;AC016;
3303 xor al,al ; (set physical drive number to zero) ;AC016;
3307 mov BOOT.EXT_PHYDRV,al ; (set physical hard drive number) ;AC016;
3309 cmp DOS_VER,0 ; ;AN019;
3310 ; $if ne ; copy IOCTL stuff into boot record ;AN019;
3312 ; (no set ID available for 3.3)
3313 lea si,IOCtl_Ser_No_Low ; point to source buffer (IOCTL) ;AN000;
3314 lea di,BOOT.EXT_BOOT_SERIAL ; point to target buffer (BOOT record) ;AN000;
3316 mov cx,IOCTL_Ser_Vol_SyS ; move serial # , Volid , System ;AN019;
3322 xor cx,cx ; Sector 0 ;AN019;
3323 mov [packet],cx ; set starting sector as 0 ;AN019;
3324 mov bx,offset BOOT ; ;AN019;
3325 mov packet_buffer[0],bx ; ;AN019;
3326 mov word ptr [packet_sectors],1 ; ;AN019;
3327 mov ah,1 ; request a write ;AN019;
3328 call Direct_Access ; ;AN019;
3335 cmp DOS_VER,0 ; ;AN019
3336 ; $if e ; only do a SET if DOS 4.00
3338 mov bl,TargDrvNum ; Drive number ;AN000;
3339 lea dx,IOCtl_Buf ; point to output buffer ;AN000;
3340 mov ax,(GetSetMediaID shl 8) + 1 ; set volid, ser# and filetype ;AC008;
3341 INT 21h ; GetSetMediaID + 1 INT 21 <6901> ;AC008;
3350 ENDPROC Write_Boot_Record
3352 BREAK <SYS - FAT_Size >
3353 ;******************* START OF SPECIFICATIONS ***********************************
3354 ;Routine name: FAT_Size
3355 ;*******************************************************************************
3357 ;Description: Determine FAT Type (12 or 16)
3359 ; NOTE: This routine is only called if the IOCtl call for
3360 ; Get Media Type FAILS with an extended error of
3361 ; 'Unknown media type'. This indicates it is a
3362 ; pre DOS 4.00 media (ie: it MUST be a 12 or old style
3365 ; This is the same algorithm used by FORMAT
3369 ; UsedSectors = number of reserved sectors
3370 ; + number of FAT Sectors ( Number of FATS * Sectors Per FAT )
3371 ; + number of directory sectors ( 32* Root Entries / bytes Per Sector )
3373 ; t_clusters = ( (Total Sectors - Used Sector) / Sectors Per Cluster)
3375 ; if T_Clusters <= 4086 then it a FAT12 - else - its a FAT16
3377 ;Called Procedures: None
3379 ;Input: EBPB of Target media in memory
3381 ;Output: SI: points to "FAT12
"
3384 ;Change History: Created 5/01/87 FG
3386 ;******************* END OF SPECIFICATIONS *************************************
3387 ;******************+ START OF PSEUDOCODE +**************************************
3391 ; Calculate the number of directory sectors
3392 ; Calculate and add the number of FAT sectors
3393 ; Add in the number of boot sectors
3394 ; subtract used sectors from total sectors
3395 ; if <= FAT THRESHOLD then
3396 ; set pointer to FAT12
3398 ; set pointer to FAT12
3405 ;******************- END OF PSEUDOCODE -**************************************
3411 ;--------------------------
3412 ; Calculate UsedSectors
3413 ;---------------------------
3415 ; Calculate the number of directory sectors
3417 mov ax, deviceParameters.DP_BPB.BPB_RootEntries ; ;AN000;
3418 mov bx, TYPE dir_entry ; ;AN000;
3420 add ax, deviceParameters.DP_BPB.BPB_BytesPerSector ; ;AN000;
3423 div deviceParameters.DP_BPB.BPB_BytesPerSector ; ;AN000;
3426 ; Calculate the number of FAT sectors
3428 mov ax, deviceParameters.DP_BPB.BPB_SectorsPerFAT ; ;AN000;
3429 mul deviceParameters.DP_BPB.BPB_NumberOfFATs ; ;AN000;
3431 ; Add in the number of boot sectors
3433 add ax, deviceParameters.DP_BPB.BPB_ReservedSectors ; ;AN000;
3436 ;--------------------------
3437 ; Calculate t_clusters
3438 ;--------------------------
3440 mov ax, deviceParameters.DP_BPB.BPB_TotalSectors ; ;AN000;
3442 sub ax,cx ;Get sectors in data area ;AN000;
3445 mov bl,deviceParameters.DP_BPB.BPB_SectorsPerCluster ; ;AN000;
3446 div bx ;Get total clusters ;AN000;
3447 cmp ax,BIG_FAT_THRESHOLD ;Is clusters < 4086? ;AN000;
3449 ; $if be ; if less then its a FAT12 ;AN000;
3451 lea si,FAT_12 ; ;AN000;
3455 lea si,FAT_16 ; ;AN000;
3465 BREAK <SYS - Create_Serial_ID >
3466 ;******************* START OF SPECIFICATIONS ***********************************
3467 ;Routine name: Create_Serial_ID
3468 ;*******************************************************************************
3470 ;Description: Create unique 32 bit serial number by getting current date
3471 ; and time and then scrambling it around
3473 ;Called Procedures: None
3477 ;Output: serial number installed in Boot_Serial
3479 ;Change History: Created 5/01/87 FG
3481 ;******************* END OF SPECIFICATIONS *************************************
3482 ;******************+ START OF PSEUDOCODE +**************************************
3484 ; START Create_Serial_ID
3486 ; Get date (INT21 Get_Date + 00 <2A00>)
3487 ; Get time (INT21 Get_Time + 00 <2C00>)
3488 ; Boot_Serial+0 = DX reg date + DX reg date
3489 ; Boot_Serial+2 = CX reg time + CX reg time
3492 ; END Create_Serial_ID
3494 ;******************- END OF PSEUDOCODE -**************************************
3496 public Create_Serial_ID
3498 Create_Serial_ID PROC NEAR
3500 mov ax,(Get_Date shl 8) + not_used ; Get date ;AN000;
3501 INT 21h ; Get_Date + not_used <2A00> ;AN000;
3502 mov ax,(Get_Time shl 8) + not_used ; Get time ;AN000;
3503 INT 21h ; Get_Time + not_used <2C00> ;AN000;
3504 add dx,dx ; Boot_Serial+0 = DX (date) + DX (date);AN000;
3505 add cx,cx ; Boot_Serial+2 = CX (time) + CX (time);AN000;
3506 mov IOCtl_Ser_No_Low,dx ; SERIAL # - low ;AN000;
3507 mov IOCtl_Ser_No_Hi,cx ; SERIAL # - hi ;AN000;
3511 ENDPROC Create_Serial_ID
3513 BREAK <SYS - Message >
3514 ;******************* START OF SPECIFICATIONS ***********************************
3515 ;Routine name: Message
3516 ;*******************************************************************************
3518 ;Description: Display a message
3520 ;Called Procedures: SYSDISPMSG, Get_DOS_Error
3522 ;Input: (AL) message number
3523 ; (AH) message class
3524 ; = C - DS:SI points to sublist
3526 ;Output: no error AX = 0
3527 ; error - AX = error exit code
3529 ;Change History: Created 5/01/87 FG
3531 ;******************* END OF SPECIFICATIONS *************************************
3532 ;******************+ START OF PSEUDOCODE +**************************************
3537 ; call Get_DOS_error
3539 ; move message class into place
3541 ; reset response (DL)
3542 ; set output handle (BX)
3543 ; if CLASS requires insert
3544 ; load insert required
3545 ; if CLASS requires response
3546 ; flush keystroke buffer
3547 ; load response required (Dir CON in no echo)
3549 ; call SysDispMsg to display message
3551 ; call Get_DOS_error
3552 ; call SysDispMsg to try again
3553 ; if not success message
3554 ; load error exit code
3556 ; load success exit code
3562 ;******************- END OF PSEUDOCODE -**************************************
3568 xor dx,dx ; reset response (DL) ;AN000;
3569 xor cx,cx ; reset insert (CX) ;AC024;
3570 dec dh ; assume CLASS is Utility ;AN000;
3572 cmp ah,PARSE_Error ; ;AN000;
3574 ; $if be,and ; if DOS or PARSE error ;AN000;
3579 ; $if e,and ; if PARSE error ;AN024;
3581 cmp al,reqd_missing ; ;AC024;
3582 ; $if ne ; and if theres something there ;AC024;
3585 push cs ; set up for insert ;AN024;
3586 pop [insert_ptr_seg] ; (offset set by parse routine) ;AN024;
3587 mov cs:[si],dl ; make it an ASCIIZ string ;AN024;
3588 mov insert_number,dl ; zero out for %0
3589 mov insert_max,030h ; set length to something reasonable ;AN024;
3590 inc cx ; there's an insert ;AC024;
3591 lea si,SUBLIST ; point to the sublist ;AC024;
3597 cmp ah,DOS_Error ; ;AN000;
3599 ; $if be ; if DOS error ;AC019;
3602 call Get_DOS_error ; to find out what message to display ;AN000;
3603 mov dh,DOS_Error ; ensure message type is DOS_Error ;AN019;
3608 mov bx,STDERR ; set output handle (BX) ;AN000;
3610 cmp ah,util_C ; is it CLASS C ;AN000;
3612 ; $if e ; CLASS C requires insert ;AN000;
3615 inc cx ; load insert required ;AN000;
3620 cmp ah,util_D ; is it CLASS D ;AN000;
3622 ; $if e ; CLASS D requires response ;AN000;
3625 mov dl,DOS_CON_INP ; load response required - con: input ;AN000;
3633 call SysDispMsg ; to display message ;AN000;
3635 ; $if c,and ; error and............... ;AN000;
3638 call SysDispMsg ; to try again : ;AN000;
3640 ; $if c ; if reaaly bad .........: ;AN000;
3643 mov ax,return_error ; load error exit code ;AN000;
3649 mov ax,success ; load success exit code ;AN000;
3659 BREAK <SYS - Get_DOS_Error >
3660 ;******************* START OF SPECIFICATIONS ***********************************
3661 ;Routine name: Get_DOS_Error
3662 ;*******************************************************************************
3664 ;Description: Call DOS to obtain DOS extended error #
3666 ;Called Procedures: None
3670 ;Output: AX = error number
3672 ;Change History: Created 5/01/87 FG
3674 ;******************* END OF SPECIFICATIONS *************************************
3675 ;******************+ START OF PSEUDOCODE +**************************************
3677 ; START Get_DOS_Error
3679 ; call DOS for extended error (INT21 GetExtendedError + 00 <5900>)
3680 ; set up registers for return
3685 ;******************- END OF PSEUDOCODE -**************************************
3687 public Get_DOS_Error
3689 Get_DOS_Error PROC NEAR
3692 mov ax,(GetExtendedError shl 8) + not_used ; call DOS for extended error ;AN000;
3695 INT 21h ; GetExtendedError + not_used <5900>;AN000;
3698 xor cx,cx ; reset insert (CX) ;AC024;
3702 ENDPROC Get_DOS_Error