PAGE ,132 ; ; SCCSID = @(#)sysinit2.asm 1.13 85/10/15 TITLE BIOS SYSTEM INITIALIZATION %OUT ...SYSINIT2 ;============================================================================== ;REVISION HISTORY: ;AN000 - New for DOS Version 4.00 - J.K. ;AC000 - Changed for DOS Version 4.00 - J.K. ;AN00x - PTM number for DOS Version 4.00 - J.K. ;============================================================================== ;AN001; p132 Multiple character device installation problem. 6/27/87 J.K. ;AN002; d24 MultiTrack= command added. 6/29/87 J.K. ;AN003; p29 Extra space character in parameters passed. ; (Modification on ORGANIZE routine for COMMENT= fixed this ; problem too) 6/29/87 J.K. ;AN004; d41 REM command in CONFIG.SYS 7/7/87 J.K. ;AN005; d184 Set DEVMARK for MEM command 8/25/87 J.K. ;AN006; p1820 New Message SKL file 10/20/87 J.K. ;AN007; p1821 Include the COPYRIGH.INC file 10/22/87 J.K. ;AN008; p2210 IBMDOS returns incorrect DBCS vector table length 11/02/87 J.K. ;AN009; p2667 ccMono_Ptr problem 11/30/87 J.K. ;AN010; p2792 Device?driver.sys /d:2 command should not work 12/09/87 J.K. ;AN011; p3120 REM followed by CR, LF causes problem 01/13/88 J.K. ;AN012; p3111 Take out the order dependency of the INSTALL= 01/25/88 J.K. ;AN013; d479 New option to disable extended INT 16h function call 02/12/88 J.K. ;AN014; D486 SHARE installation for big media 02/23/88 J.K. ;AN015; D526 Add /NC parameter when installing SHARE.EXE 04/28/88 J.K. ;============================================================================== TRUE EQU 0FFFFh FALSE EQU 0 LF equ 10 CR equ 13 TAB equ 9 IBMVER EQU TRUE IBM EQU IBMVER STACKSW EQU TRUE ;Include Switchable Hardware Stacks IBMJAPVER EQU FALSE ;If TRUE set KANJI true also MSVER EQU FALSE ALTVECT EQU FALSE ;Switch to build ALTVECT version KANJI EQU FALSE IF IBMJAPVER NOEXEC EQU TRUE ELSE NOEXEC EQU FALSE ENDIF DOSSIZE EQU 0A000H .xlist ; INCLUDE dossym.INC include smdossym.inc ;J.K. Reduced version of DOSSYM.INC INCLUDE devsym.INC include ioctl.INC include DEVMARK.inc .list IF NOT IBM IF NOT IBMJAPVER EXTRN RE_INIT:FAR ENDIF ENDIF code segment public 'code' extrn EC35_Flag: byte code ends SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' BYTE ASSUME CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING EXTRN BADOPM:BYTE,CRLFM:BYTE,BADCOM:BYTE,BADMEM:BYTE,BADBLOCK:BYTE EXTRN BADSIZ_PRE:BYTE,BADLD_PRE:BYTE ; EXTRN BADSIZ_POST:BYTE,BADLD_POST:BYTE EXTRN SYSSIZE:BYTE,BADCOUNTRY:BYTE EXTRN dosinfo:dword,entry_point:dword, EXTRN MEMORY_SIZE:WORD,fcbs:byte,keep:byte EXTRN DEFAULT_DRIVE:BYTE,confbot:word,alloclim:word EXTRN BUFFERS:WORD,zero:byte,sepchr:byte EXTRN FILES:BYTE EXTRN count:word,chrptr:word EXTRN bufptr:byte,memlo:word,prmblk:byte,memhi:word EXTRN ldoff:word,area:word,PACKET:BYTE,UNITCOUNT:BYTE, EXTRN BREAK_ADDR:DWORD,BPB_ADDR:DWORD,drivenumber:byte extrn COM_Level:byte, CMMT:byte, CMMT1:byte, CMMT2:byte extrn Cmd_Indicator:byte extrn DoNotShowNum:byte extrn MultDeviceFlag:byte extrn DevMark_Addr:word ;AN005; extrn SetDevMarkFlag:byte ;AN005; extrn Org_Count:word ;AN012; EXTRN Stall:near EXTRN Error_Line:near PUBLIC Int24,Open_Dev,Organize,Mem_Err,Newline,CallDev,Badload PUBLIC PrnDev,AuxDev,Config,Commnd,Condev,GetNum,BadFil,PrnErr PUBLIC Round,Delim,Print,Set_Break PUBLIC SetParms, ParseLine, DiddleBack PUBLIC Skip_delim,SetDOSCountryInfo,Set_Country_Path,Move_Asciiz PUBLIC Cntry_Drv,Cntry_Root,Cntry_Path PUBLIC Delim public PathString ;AN014; public LShare ;AN014; ; ; The following set of routines is used to parse the DRIVPARM = command in ; the CONFIG.SYS file to change the default drive parameters. ; SetParms: push ds push ax push bx push cx push dx push cs pop ds ASSUME DS:SYSINITSEG xor bx,bx mov bl,byte ptr drive inc bl ; get it correct for IOCTL call (1=A,2=B...) mov dx,offset DeviceParameters mov ah, IOCTL mov al, GENERIC_IOCTL mov ch, RAWIO mov cl, SET_DEVICE_PARAMETERS int 21H test word ptr Switches, flagec35 jz Not_EC35 mov cl, byte ptr drive ; which drive was this for? mov ax, Code ; get Code segment mov ds, ax ; set code segment assume ds:code mov al, 1 ; assume drive 0 shl al, cl ; set proper bit depending on drive or ds:EC35_Flag, al ; set the bit in the permanent flags Not_EC35: pop dx ; fix up all the registers pop cx pop bx pop ax pop ds assume ds:nothing ret ; ; Replace default values for further DRIVPARM commands ; DiddleBack: push ds push cs pop ds assume ds:sysinitseg mov word ptr DeviceParameters.DP_Cylinders,80 mov byte ptr DeviceParameters.DP_DeviceType, DEV_3INCH720KB mov word ptr DeviceParameters.DP_DeviceAttributes,0 mov word ptr switches,0 ; zero all switches pop ds assume ds:nothing ret ; ; Entry point is ParseLine. AL contains the first character in command line. ; ParseLine: ; don't get character first time push ds push cs pop ds ASSUME DS:SYSINITSEG NextSwtch: cmp al,CR ; carriage return? jz done_line cmp al,LF ; linefeed? jz put_back ; put it back and done ; Anything less or equal to a space is ignored. cmp al,' ' ; space? jbe get_next ; skip over space cmp al,'/' jz getparm stc ; mark error invalid-character-in-input jmp short exitpl getparm: call Check_Switch mov word ptr Switches,BX ; save switches read so far jc swterr get_next: invoke getchr jc done_line jmp NextSwtch swterr: jmp exitpl ; exit if error done_line: test word ptr Switches,flagdrive ; see if drive specified jnz okay stc ; mark error no-drive-specified jmp short exitpl okay: mov ax,word ptr switches and ax,0003H ; get flag bits for changeline and non-rem mov word ptr DeviceParameters.DP_DeviceAttributes,ax mov word ptr DeviceParameters.DP_TrackTableEntries, 0 clc ; everything is fine call SetDeviceParameters exitpl: pop ds ret put_back: inc count ; one more char to scan dec chrptr ; back up over linefeed jmp short done_line ; ; Processes a switch in the input. It ensures that the switch is valid, and ; gets the number, if any required, following the switch. The switch and the ; number *must* be separated by a colon. Carry is set if there is any kind of ; error. ; Check_Switch: invoke getchr jc err_check and al,0DFH ; convert it to upper case cmp al,'A' jb err_check cmp al,'Z' ja err_check push es push cs pop es mov cl,byte ptr switchlist ; get number of valid switches mov ch,0 mov di,1+offset switchlist ; point to string of valid switches repne scasb pop es jnz err_check mov ax,1 shl ax,cl ; set bit to indicate switch mov bx,word ptr switches ; get switches so far or bx,ax ; save this with other switches mov cx,ax test ax, switchnum ; test against switches that require number to follow jz done_swtch invoke getchr jc err_Swtch cmp al,':' jnz err_swtch invoke getchr push bx ; preserve switches mov byte ptr cs:sepchr,' ' ; allow space separators call GetNum mov byte ptr cs:sepchr,0 pop bx ; restore switches ; Because GetNum does not consider carriage-return or line-feed as OK, we do ; not check for carry set here. If there is an error, it will be detected ; further on (hopefully). call Process_Num done_swtch: clc ret err_swtch: xor bx,cx ; remove this switch from the records err_check: stc ret ; ; This routine takes the switch just input, and the number following (if any), ; and sets the value in the appropriate variable. If the number input is zero ; then it does nothing - it assumes the default value that is present in the ; variable at the beginning. Zero is OK for form factor and drive, however. ; Process_Num: test word ptr Switches,cx ; if this switch has been done before, jnz done_ret ; ignore this one. test cx,flagdrive jz try_f mov byte ptr drive,al jmp short done_ret try_f: test cx,flagff jz try_t ; Ensure that we do not get bogus form factors that are not supported ;cmp al,Max_Dev_Type ;ja done_ret mov byte ptr DeviceParameters.DP_DeviceType,al jmp short done_ret try_t: or ax,ax jz done_ret ; if number entered was 0, assume default value test cx,flagcyln jz try_s mov word ptr DeviceParameters.DP_Cylinders,ax jmp short done_ret try_s: test cx,flagseclim jz try_h mov word ptr slim,ax jmp short done_ret ; ; Must be for number of heads try_h: mov word ptr hlim,ax done_ret: clc ret ; ; SetDeviceParameters sets up the recommended BPB in each BDS in the ; system based on the form factor. It is assumed that the BPBs for the ; various form factors are present in the BPBTable. For hard files, ; the Recommended BPB is the same as the BPB on the drive. ; No attempt is made to preserve registers since we are going to jump to ; SYSINIT straight after this routine. ; SetDeviceParameters: push es push cs pop es ASSUME ES:SYSINITSEG xor bx,bx mov bl,byte ptr DeviceParameters.DP_DeviceType cmp bl,DEV_5INCH jnz Got_80 mov cx,40 ; 48tpi has 40 cylinders mov word ptr DeviceParameters.DP_Cylinders,cx Got_80: shl bx,1 ; get index into BPB table mov si,offset BPBTable mov si,word ptr [si+bx] ; get address of BPB Set_RecBPB: mov di,offset DeviceParameters.DP_BPB ; es:di -> BPB mov cx,size a_BPB cld repe movsb pop es ASSUME ES:NOTHING test word ptr switches,flagseclim jz see_heads mov ax,word ptr slim mov word ptr DeviceParameters.DP_BPB.BPB_SectorsPerTrack,ax see_heads: test word ptr switches,flagheads jz Set_All_Done mov ax,word ptr hlim mov word ptr DeviceParameters.DP_BPB.BPB_Heads,ax ; ; We need to set the media byte and the total number of sectors to reflect the ; number of heads. We do this by multiplying the number of heads by the number ; of 'sectors per head'. This is not a fool-proof scheme!! ; mov cx,ax ; cx has number of heads dec cl ; get it 0-based mov ax,DeviceParameters.DP_BPB.BPB_TotalSectors ; this is OK for two heads sar ax,1 ; ax contains # of sectors/head sal ax,cl jc Set_All_Done ; We have too many sectors - overflow!! mov DeviceParameters.DP_BPB.BPB_TotalSectors,ax ; Set up correct Media Descriptor Byte cmp cl,1 mov bl,0F0H mov al,2 ; AL contains sectors/cluster ja Got_Correct_Mediad mov bl,byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor je Got_Correct_Mediad ; We have one head - OK for 48tpi medium mov al,1 ; AL contains sectors/cluster mov ch,DeviceParameters.DP_DeviceType cmp ch,DEV_5INCH jz Dec_Mediad mov bl,0F0H jmp short Got_Correct_Mediad Dec_Mediad: dec bl ; adjust for one head Got_Correct_Mediad: mov byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor,bl mov byte ptr DeviceParameters.DP_BPB.BPB_SectorsPerCluster,al clc Set_All_Done: RET ASSUME DS:NOTHING, ES:NOTHING NOCHAR1: STC return ORGANIZE: MOV CX,[COUNT] JCXZ NOCHAR1 CALL MAPCASE XOR SI,SI MOV DI,SI xor ax,ax mov COM_Level, 0 ;ORG1: CALL GET ;SKIP LEADING CONTROL CHARACTERS ; CMP AL,' ' ; JB ORG1 Org1: call Skip_Comment ;AN000; jz End_Commd_Line ;AN000; found a comment string and skipped. call Get2 ;AN000; Not a comment string. Then get a char. cmp al, LF ;AN000; je End_Commd_Line ;AN000; starts with a blank line. cmp al, ' ' ;AN000; jbe Org1 ;AN000; skip leading control characters jmp Findit ;AN000; End_Commd_Line: ;AN000; stosb ;AN000; store line feed char in buffer for the LineCount. mov COM_Level, 0 ;AN000; reset the command level. jmp Org1 ;AN000; Findit: ;AN000; PUSH CX PUSH SI PUSH DI MOV BP,SI DEC BP MOV SI,OFFSET COMTAB ;Prepare to search command table MOV CH,0 FINDCOM: MOV DI,BP MOV CL,[SI] INC SI JCXZ NOCOM REPE CMPSB LAHF ADD SI,CX ;Bump to next position without affecting flags SAHF LODSB ;Get indicator letter JNZ FINDCOM cmp byte ptr es:[di], CR ;AN011;The next char might be CR,LF je GotCom0 ;AN011; such as in "REM",CR,LF case. cmp byte ptr es:[di], LF ;AN011; je GotCom0 ;AN011; push ax ;AN010; mov al, byte ptr es:[di] ;AN010;Now the next char. should be a delim. call delim ;AN010; pop ax ;AN010; jnz findcom ;AN010; GotCom0: POP DI POP SI POP CX JMP SHORT GOTCOM NOCOM: POP DI POP SI POP CX MOV AL,'Z' stosb ;AN000; save indicator char. Skip_Line: ;AN000; call Get2 ;AN000; cmp al, LF ;AN000; skip this bad command line jne Skip_Line ;AN000; jmp End_Commd_Line ;AN000; handle next command line GOTCOM: STOSB ;SAVE INDICATOR CHAR IN BUFFER mov Cmd_Indicator, al ;AN000; save it for the future use. ORG2: CALL GET2 ;SKIP the commad name UNTIL DELIMITER cmp al, LF ;AN011; je Org21 ;AN011; cmp al, CR ;AN011; je Org21 ;AN011; CALL DELIM ; JNZ ORG2 jmp short Org3 ;AN011; Org21: ;AN011;if CR or LF then dec si ;AN011; undo SI, CX register inc cx ;AN011; and continue ;ORG4: CALL GET2 ; call Delim ;J.K. 5/30/86. To permit "device=filename/p..." stuff. ; jz ORG_EXT ;J.K. 5/30/86 ;Org4_Cont: ; STOSB ; CMP AL,' ' ; JA ORG4 ; CMP AL,10 ; JZ ORG1 ; ; MOV BYTE PTR ES:[DI-1],0 Org3: cmp Cmd_Indicator, 'Y' ;AN000; Comment= command? je Get_Cmt_Token ;AN000; cmp Cmd_Indicator, 'I' ;AN000; Install= command? je Org_file ;AN000; cmp Cmd_Indicator, 'D' ;AN000; Device= command? je Org_file ;AN000; cmp Cmd_Indicator, 'J' ;AN000; IFS= command? je Org_file ;AN000; cmp Cmd_Indicator, 'S' ;AN000; Shell= is a special one!!! je Org_file ;AN000; cmp Cmd_Indicator, '1' ;AN013; SWITCHES= command? je Org_Switch ;AN013; jmp Org4 ;AN000; Org_Switch: call Skip_Comment ;AN013; jz End_Commd_Line_Brdg ;AN013; call Get2 ;AN013; call Org_Delim ;AN013; jz Org_Switch ;AN013; stosb ;AN013; jmp Org5 ;AN013; Org_file: ;AN000; Get the filename and put 0 at end, call Skip_Comment ;AN000; jz Org_Put_Zero ;AN000; call Get2 ;AN000; Not a comment call Delim ;AN000; jz Org_file ;AN000; Skip the possible delimeters stosb ;AN000; copy the first non delim char found in buffer Org_Copy_File: ;AN000; call Skip_Comment ;AN000; comment char in the filename? jz Org_Put_Zero ;AN000; then stop copying filename at that point call Get2 ;AN000; cmp al, '/' ;AN000; a switch char? (device=filename/xxx) je End_File_slash ;AN000; this will be the special case. stosb ;AN000; save the char. in buffer call Delim ;AN000; jz End_Copy_File ;AN000; cmp al, ' ' ;AN000; ja Org_Copy_File ;AN000; keep copying jmp End_Copy_File ;AN000; otherwise, assume end of the filename. Get_Cmt_token: ;AN000; get the token. Just max. 2 char. call Get2 ;AN000; cmp al, ' ' ;AN000; skip white spaces or "=" char. je Get_Cmt_Token ;AN000; (we are allowing the other special cmp al, TAB ;AN000; charaters can used for comment id. je Get_Cmt_Token ;AN000; character.) cmp al, '=' ;AN000; = is special in this case. je Get_Cmt_Token ;AN000; cmp al, CR ;AN000; je Get_Cmt_End ;AN000; cannot accept the carridge return cmp al, LF ;AN000; je Get_Cmt_End ;AN000; mov CMMT1, al ;AN000; store it mov CMMT, 1 ;AN000; 1 char. so far. call Get2 ;AN000; cmp al, ' ' ;AN000; je Get_Cmt_End ;AN000; cmp al, TAB ;AN000; je Get_Cmt_End ;AN000; cmp al, CR ;AN000; je Get_Cmt_End ;AN000; cmp al, LF ;AN000; je End_Commd_Line_Brdg ;AN000; mov CMMT2, al ;AN000; inc CMMT ;AN000; Get_Cmt_End: ;AN000; call Get2 ;AN000; cmp al, LF ;AN000; jne Get_Cmt_End ;AN000; skip it. End_Commd_Line_Brdg: jmp End_Commd_Line ;AN000; else jmp to End_Commd_Line Org_Put_Zero: ;AN000; Make the filename in front of mov byte ptr es:[di], 0 ;AN000; the comment string to be an asciiz. inc di ;AN000; jmp End_Commd_Line ;AN000; (Maybe null if device=/*) End_file_slash: ;AN000; AL = "/" option char. mov byte ptr es:[di],0 ;AN000; make a filename an asciiz inc di ;AN000; and stosb ;AN000; store "/" after that. jmp Org5 ;AN000; continue with the rest of the line End_Copy_File: ;AN000; mov byte ptr es:[di-1], 0 ;AN000; make it an asciiz and handle the next char. cmp al, LF ;AN000; je End_Commd_Line_brdg ;AN000; jmp Org5 ;AN000; Org4: ;AN000; Org4 skips all delimiters after the command name except for '/' call Skip_Comment ;AN000; jz End_Commd_Line_brdg ;AN000; call Get2 ;AN000; call Org_Delim ;AN000; skip delimiters EXCEPT '/' (mrw 4/88) jz Org4 ;AN000; jmp Org51 ;AN000; Org5: ;AN000; rest of the line call Skip_Comment ;AN000; Comment? jz End_Commd_Line_brdg ;AN000; call Get2 ;AN000; Not a comment. Org51: ;AN000; stosb ;AN000; copy the character cmp al, '"' ;AN000; a quote ? je At_Quote ;AN000; cmp al, ' ' ;AN000; ja Org5 ;AN000; cmp al, LF ;AN000; line feed? je Org1_brdg ;AN000; handles the next command line. jmp Org5 ;AN000; handles next char in this line. Org1_brdg: jmp Org1 ;AN000; At_Quote: ;AN000; cmp COM_Level, 0 ;AN000; je Up_Level ;AN000; mov COM_Level, 0 ;AN000; reset it. jmp Org5 ;AN000; Up_Level: ;AN000; inc COM_level ;AN000; set it. jmp Org5 ;AN000; ;ORG5: CALL GET2 ; STOSB ; CMP AL,10 ; JNZ ORG5 ; JMP ORG1 ; ;ORG_EXT: ; cmp al,' ' ;space? ; je Org4_Cont ;then do not make an exception. Go back. ; cmp al,9 ;Tab? ; je Org4_Cont ; mov byte ptr es:[di], 0 ;put 0 at the current DI to make it an ASCIIZ ; inc DI ; ; stosb ;and copy the delimeter char. ; jmp short ORG5 ;and continue as usual. GET2: JCXZ NOGET MOV AL,ES:[SI] INC SI DEC CX return ;GET: JCXZ NOGET ; MOV AL,ES:[SI] ; INC SI ; DEC CX ; CALL Org_DELIM ; JZ GET ; return Skip_Comment: ;J.K.Skip the commented string until LF, if current es:si-> a comment string. ;J.K.In) ES:SI-> sting ;J.K. CX -> length. ;J.K.Out) Zero flag not set if not found a comment string. ;J.K. Zero flag set if found a comment string and skipped it. AL will contain ;J.K. the line feed charater at this moment when return. ;J.K. AX register destroyed. ;J.K. If found, SI, CX register adjusted accordingly. jcxz NoGet ;AN000; Get out of the Organize routine. cmp COM_Level, 0 ;AN000; only check it if parameter level is 0. jne No_Commt ;AN000; (Not inside quotations) cmp CMMT, 1 ;AN000; jb No_Commt ;AN000; mov al, es:[si] ;AN000; cmp CMMT1, al ;AN000; jne No_Commt ;AN000; cmp CMMT, 2 ;AN000; jne Skip_Cmmt ;AN000; mov al, es:[si+1] ;AN000; cmp CMMT2, al ;AN000; jne No_Commt ;AN000; Skip_Cmmt: ;AN000; jcxz NoGet ;AN000; get out of Organize routine. mov al, es:[si] ;AN000; inc si ;AN000; dec cx ;AN000; cmp al, LF ;AN000; line feed? jne Skip_Cmmt ;AN000; No_Commt: ;AN000; ret ;AN000; DELIM: CMP AL,'/' ;J.K. 5/30/86. IBM will assume "/" as an delimeter. retz cmp al, 0 ;J.K. 5/23/86 Special case for sysinit!!! retz Org_Delim: ;AN000; Used by Organize routine except for getting CMP AL,' ' ;the filename. retz CMP AL,9 retz CMP AL,'=' retz CMP AL,',' retz CMP AL,';' return NOGET: POP CX MOV COUNT,DI mov Org_Count, DI ;AN012; XOR SI,SI MOV CHRPTR,SI return ;Get3: jcxz NOGET ;J.K.do not consider '/',',' as a delim. ; mov al, es:[si] ; inc si ; dec cx ; call DELIM ; jnz Get3_ret ; cmp al,'/' ; je Get3_ret ; cmp al,',' ; jne Get3 ;Get3_ret: ; ret ; ; NEWLINE RETURNS WITH FIRST CHARACTER OF NEXT LINE ; NEWLINE:invoke GETCHR ;SKIP NON-CONTROL CHARACTERS retc CMP AL,LF ;LOOK FOR LINE FEED JNZ NEWLINE invoke GETCHR return MAPCASE: PUSH CX PUSH SI PUSH DS PUSH ES POP DS XOR SI,SI CONVLOOP: LODSB IF KANJI CALL TESTKANJ JZ NORMCONV INC SI ;Skip next char DEC CX JCXZ CONVDONE ;Just ignore 1/2 kanji error ;Fall through, know AL is not in 'a'-'z' range NORMCONV: ENDIF CMP AL,'a' JB NOCONV CMP AL,'z' JA NOCONV SUB AL,20H MOV [SI-1],AL NOCONV: LOOP CONVLOOP CONVDONE: POP DS POP SI POP CX return IF KANJI TESTKANJ: CMP AL,81H JB NOTLEAD CMP AL,9FH JBE ISLEAD CMP AL,0E0H JB NOTLEAD CMP AL,0FCH JBE ISLEAD NOTLEAD: PUSH AX XOR AX,AX ;Set zero POP AX return ISLEAD: PUSH AX XOR AX,AX ;Set zero INC AX ;Reset zero POP AX return ENDIF ASSUME DS:NOTHING Yes_Break_Failed: ;device driver Init failed and aborted. stc pop ax return SET_BREAK: ;J.K. 8/14/86 For DOS 3.3, this routine is modified to take care of the ;Device driver's initialization error and abort. ;If [break_addr+2] == [memhi] && [break_addr] = 0 then assume ;that the device driver's initialization has an error and wanted to ;abort the device driver. In this case, this routine will set carry ;and return to the caller. ;J.K. 6/26/87 If MultDeviceFlag <> 0, then do not perform the check. ;This is to allow the multiple character device driver which uses ;the same ending address segment with the offset value 0 for each ;of the drives. PUSH AX MOV AX,WORD PTR [BREAK_ADDR+2] ;REMOVE THE INIT CODE cmp MultDeviceFlag, 0 ;AN001; jne Set_Break_Continue ;AN001;Do not check it. cmp ax, [MEMHI] jne Set_Break_Continue ;if not same, then O.K. cmp word ptr [BREAK_ADDR],0 je Yes_Break_failed ;[Break_addr+2]=[MEMHI] & [Break_addr]=0 Set_Break_Continue: MOV [MEMHI],AX MOV AX,WORD PTR [BREAK_ADDR] MOV [MEMLO],AX POP AX ; NOTE FALL THROUGH or [SetDevMarkFlag], SETBRKDONE ;AN005; Signal the successful Set_break ; ; Round the values in MEMLO and MEMHI to paragraph boundary. ; Perform bounds check. ; ROUND: PUSH AX MOV AX,[MEMLO] invoke ParaRound ; para round up ADD [MEMHI],AX MOV [MEMLO],0 mov ax,memhi ; ax = new memhi CMP AX,[ALLOCLIM] ; if new memhi >= alloclim, error JAE MEM_ERR test cs:[SetDevMarkFlag], FOR_DEVMARK ;AN005; jz Skip_Set_DEVMARKSIZE ;AN005; push es ;AN005; push si ;AN005; mov si, cs:[DevMark_Addr] ;AN005; mov es, si ;AN005; sub ax, si ;AN005; dec ax ;AN005; mov es:[DEVMARK_SIZE], ax ;AN005; Paragraph and cs:[SetDevMarkFlag], NOT_FOR_DEVMARK ;AN005; pop si ;AN005; pop es ;AN005; Skip_Set_DEVMARKSIZE: ;AN005; POP AX clc ;clear carry return MEM_ERR: MOV DX,OFFSET BADMEM PUSH CS POP DS CALL PRINT JMP STALL CALLDEV:MOV DS,WORD PTR CS:[ENTRY_POINT+2] ADD BX,WORD PTR CS:[ENTRY_POINT] ;Do a little relocation MOV AX,DS:[BX] PUSH WORD PTR CS:[ENTRY_POINT] MOV WORD PTR CS:[ENTRY_POINT],AX MOV BX,OFFSET PACKET CALL [ENTRY_POINT] POP WORD PTR CS:[ENTRY_POINT] return BADNUM: MOV sepchr,0 XOR AX,AX ; Set Zero flag, and AX = 0 pop bx ; J.K. stc ; AND carry set return ToDigit: SUB AL,'0' JB NotDig CMP AL,9 JA NotDig CLC return NotDig: STC return ; GetNum parses a decimal number. ; Returns it in AX, sets zero flag if AX = 0 (MAY BE considered an ; error), if number is BAD carry is set, zero is set, AX=0. GETNUM: push bx ; J.K. XOR BX,BX ; running count is zero B2: CALL ToDigit ; do we have a digit JC BadNum ; no, bomb XCHG AX,BX ; put total in AX PUSH BX ; save digit MOV BX,10 ; base of arithmetic MUL BX ; shift by one decimal di... POP BX ; get back digit ADD AL,BL ; get total ADC AH,0 ; make that 16 bits JC BADNUM ; too big a number XCHG AX,BX ; stash total invoke GETCHR ;GET NEXT DIGIT JC B1 ; no more characters cmp al, ' ' ;J.K. 5/23/86 space? jz B15 ;J.K. 5/23/86 then end of digits cmp al, ',' ;J.K. 5/23/86 ',' is a seperator!!! jz B15 ;J.K. 5/23/86 then end of digits. cmp al, TAB ;J.K. 5/23/86 TAB jz B15 ;J.K. CMP AL,SepChr ; allow 0 or special separators JZ b15 cmp al,SWTCHR ; See if another switch follows JZ b15 cmp al,LF ; Line-feed? jz b15 cmp al,CR ; Carriage return? jz b15 OR AL,AL ; end of line separator? JNZ B2 ; no, try as a valid char... b15: INC COUNT ; one more character to s... DEC CHRPTR ; back up over separator B1: MOV AX,BX ; get proper count OR AX,AX ; Clears carry, sets Zero accordingly pop bx return SKIP_DELIM proc near ;J.K. ;Skip the delimeters pointed by CHRPTR. AL will contain the first non delimeter ;character encountered and CHRPTR will point to the next character. ;This rouitne will assume the second "," found as a non delimiter character. So ;in case if the string is " , , ", this routine will stop at the second ",". At ;this time, Zero flag is set. ;If COUNT is exhausted, then carry will be set. Skip_delim_char: call getchr jc Skip_delim_exit cmp al, ',' ;the first comma? je Skip_delim_next call delim ;check the charater in AL. jz Skip_delim_char jmp short Skip_delim_exit ;found a non delim char Skip_delim_next: call getchr jc Skip_delim_exit cmp al, ',' ;the second comma? je Skip_delim_exit ;done call delim jz Skip_delim_next Skip_delim_exit: return SKIP_DELIM endp ;J.K. 5/26/86 ***************************************************************** SetDOSCountryInfo proc near ;Input: ES:DI -> pointer to DOS_COUNTRY_CDPG_INFO ; DS:0 -> buffer. ; SI = 0 ; AX = country id ; DX = code page id. (If 0, then use ccSysCodePage as a default.) ; BX = file handle ; This routine can handle maxium 72 COUNTRY_DATA entries. ;Output: DOS_country_cdpg_info set. ; Carry set if any file read failure or wrong information in the file. ; Carry set and CX = -1 if cannot find the matching COUNTRY_id, CODEPAGE ; _id in the file. push di push ax push dx xor cx,cx xor dx,dx mov ax, 512 ;read 512 bytes call ReadInControlBuffer ;Read the file header jc SetDOSData_fail push es push si push cs pop es mov di, offset COUNTRY_FILE_SIGNATURE mov cx, 8 ;length of the signature repz cmpsb pop si pop es jnz SetDOSData_fail ;signature mismatch add si, 18 ;SI -> county info type cmp byte ptr ds:[si], 1 ;Only accept type 1 (Currently only 1 header type) jne SetDOSData_fail ;cannot proceed. error return inc si ;SI -> file offset mov dx, word ptr ds:[si] ;Get the INFO file offset. mov cx, word ptr ds:[si+2] mov ax, 1024 ;read 1024 bytes. call ReadInControlBuffer ;Read INFO jc SetDOSData_fail mov cx, word ptr ds:[si] ;get the # of country, codepage combination entries cmp cx, 72 ;cannot handle more than 72 entries. ja SetDOSData_fail inc si inc si ;SI -> entry information packet pop dx ;restore code page id pop ax ;restore country id pop di SetDOSCntry_find: ;Search for desired country_id,codepage_id. cmp ax, word ptr ds:[si+2] ;compare country_id jne SetDOSCntry_next cmp dx, 0 ;No user specified code page ? je SetDOSCntry_any_codepage;then no need to match code page id. cmp dx, word ptr ds:[si+4] ;compare code page id je SetDOSCntry_got_it SetDOSCntry_next: add si, word ptr ds:[si] ;next entry inc si inc si ;take a word for size of entry itself loop SetDOSCntry_find mov cx, -1 ;signals that bad country id entered. SetDOSCntry_fail: stc ret SetDOSData_fail: pop si pop cx pop di jmp short SetDOSCntry_fail SetDOSCntry_any_CodePage: ;use the code_page_id of the country_id found. mov dx, word ptr ds:[si+4] SetDOSCntry_got_it: ;found the matching entry mov cs:CntryCodePage_Id, dx ;save code page ID for this country. mov dx, word ptr ds:[si+10] ;get the file offset of country data mov cx, word ptr ds:[si+12] mov ax, 512 ;read 512 bytes call ReadInControlBuffer jc SetDOSCntry_fail mov cx, word ptr ds:[si] ;get the number of entries to handle. inc si inc si ;SI -> first entry SetDOSCntry_data: push di ;ES:DI -> DOS_COUNTRY_CDPG_INFO push cx ;save # of entry left push si ;si -> current entry in Control buffer mov al, byte ptr ds:[si+2] ;get data entry id call GetCountryDestination ;get the address of destination in ES:DI jc SetDOSCntry_data_next ;No matching data entry id in DOS mov dx, word ptr ds:[si+4] ;get offset of data mov cx, word ptr ds:[si+6] mov ax, 4200h stc int 21h ;move pointer jc SetDOSData_fail mov dx, 512 ;start of data buffer ; mov cx, word ptr es:[di] ;length of the corresponding data in DOS. ; add cx, 10 ;Signature + A word for the length itself mov cx, 20 ;read 20 bytes only. We only need to mov ah, 3fh ;look at the length of the data in the file. stc int 21h ;read the country.sys data jc SetDOSData_fail ;read failure cmp ax, cx jne SetDOSData_fail mov dx, word ptr ds:[si+4] ;AN008;get offset of data again. mov cx, word ptr ds:[si+6] ;AN008; mov ax, 4200h ;AN008; stc ;AN008; int 21h ;AN008;move pointer back again jc SetDOSData_fail ;AN008; push si ;AN008; mov si, (512+8) ;AN008;get length of the data from the file mov cx, word ptr ds:[si] ;AN008; pop si ;AN008; mov dx, 512 ;AN008;start of data buffer add cx, 10 ;AN008;Signature + A word for the length itself mov ah, 3fh ;AN008;Read the data from the file. stc ;AN008; int 21h ;AN008; jc SetDOSData_fail ;AN008; cmp ax, cx ;AN008; jne SetDOSData_fail ;AN008; mov al, byte ptr ds:[si+2] ;save Data id for future use. mov si, (512+8) ;SI-> data buffer + id tag field mov cx, word ptr ds:[si] ;get the length of the file inc cx ;Take care of a word for lenght of tab inc cx ;itself. cmp cx, (2048 - 512 - 8) ;Fit into the buffer? ja SetDOSData_fail cmp al, SetCountryInfo ;is the data for SetCountryInfo table? jne SetDOSCntry_Mov ;no, don't worry push word ptr es:[di+ccMono_Ptr-ccCountryInfoLen] ;AN009;Cannot destroy ccMono_ptr address. Save them. push word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2] ;AN009;At this time DI -> ccCountryInfoLen push di ;save DI push ax mov ax,cs:CntryCodePage_Id ;Do not use the Code Page info in Country_Info mov ds:[si+4], ax ;Use the saved one for this !!!! pop ax SetDOSCntry_Mov: rep movsb ;copy the table into DOS cmp al, SetCountryInfo ;was the ccMono_ptr saved? jne SetDOSCntry_data_next pop di ;restore DI pop word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2] ;AN009;restore pop word ptr es:[di+ccMono_Ptr-ccCountryInfoLen] ;AN009; SetDOSCntry_data_next: pop si ;restore control buffer pointer pop cx ;restore # of entries left pop di ;restore pointer to DSO_COUNTRY_CDPG add si, word ptr ds:[si] ;try to get the next entry inc si inc si ;take a word of entry length itself ; loop SetDOSCntry_data dec cx ;AN008; cmp cx,0 ;AN008; je SetDOSCntry_OK ;AN008; jmp SetDOSCntry_data ;AN008; SetDOSCntry_OK: ;AN008; ret SetDOSCountryInfo endp ; GetCountryDestination proc near ;Get the destination address in the DOS country info table. ;Input: AL - Data ID ; ES:DI -> DOS_COUNTRY_CDPG_INFO ;On return: ; ES:DI -> Destination address of the matching data id ; carry set if no matching data id found in DOS. push cx add di, ccNumber_of_entries ;skip the reserved area, syscodepage etc. mov cx, word ptr es:[di] ;get the number of entries inc di inc di ;SI -> the first start entry id GetCntryDest: cmp byte ptr es:[di], al je GetCntryDest_OK cmp byte ptr es:[di], SetCountryInfo ;was it SetCountryInfo entry? je GetCntryDest_1 add di, 5 ;next data id jmp short GetCntryDest_loop GetCntryDest_1: add di, NEW_COUNTRY_SIZE + 3 ;next data id GetCntryDest_loop: loop GetCntryDest stc jmp short GetCntryDest_exit GetCntryDest_OK: cmp al, SetCountryInfo ;select country info? jne GetCntryDest_OK1 inc di ;now DI -> ccCountryInfoLen jmp short GetCntryDest_exit GetCntryDest_OK1: les di, dword ptr es:[di+1] ;get the destination in ES:DI GetCntryDest_Exit: pop cx ret GetCountryDestination endp ; ReadInControlBuffer proc near ;Move file pointer to CX:DX ;Read AX bytes into the control buffer. (Should be less than 2 Kb) ;SI will be set to 0 hence DS:SI points to the control buffer. ;Entry: CX,DX offset from the start of the file where the read/write pointer ; be moved. ; AX - # of bytes to read ; BX - file handle ; DS - buffer seg. ;Return: The control data information is read into DS:0 - DS:0200. ; CX,DX value destroyed. ; Carry set if error in Reading file. ; push ax ;# of bytes to read mov ax, 4200h stc int 21h ;move pointer pop cx ;# of bytes to read jc RICB_exit xor dx,dx ;ds:dx -> control buffer xor si,si mov ah,3fh ;read into the buffer stc int 21h ;should be less than 1024 bytes. RICB_exit: ret ReadInControlBuffer endp ; SET_COUNTRY_PATH proc near ;In: DS - SYSINITSEG, ES - CONFBOT, SI -> start of the asciiz path string ; DOSINFO_EXT, CNTRY_DRV, CNTRY_ROOT, CNTRY_PATH ; Assumes current directory is the ROOT directory. ;Out: DS:DI -> full path (CNTRY_DRV). ; Set the CNTRY_DRV string from the COUNTRY=,,path command. ; DS, ES, SI value saved. push si push ds ;switch ds, es push es pop ds pop es ;now DS -> CONFBOT, ES -> SYSINITSEG call chk_drive_letter ;current DS:[SI] is a drive letter? jc SCP_Default_drv ;no, use current default drive. mov al, byte ptr DS:[SI] inc si inc si ;SI -> next char after ":" jmp short SCP_SetDrv SCP_Default_drv: mov ah, 19h int 21h add al, "A" ;convert it to a character. SCP_SetDrv: mov cs:CNTRY_DRV, al ;set the drive letter. mov di, offset CNTRY_PATH mov al, byte ptr DS:[SI] cmp al, "\" je SCP_Root_Dir cmp al, cs:SWTCHR ;let's accept "/" as an directory delim je SCP_Root_Dir jmp short SCP_Path SCP_Root_Dir: dec di ;DI -> CNTRY_ROOT SCP_Path: call MOVE_ASCIIZ ;copy it mov di, offset CNTRY_DRV SCPath_Exit: push ds ;switch ds, es push es pop ds pop es ;DS, ES value restored pop si RET SET_COUNTRY_PATH endp ; CHK_DRIVE_LETTER proc near ;Check if DS:[SI] is a drive letter followed by ":". ;Assume that every alpha charater is already converted to UPPER CASE. ;Carry set if not. ; push ax cmp byte ptr ds:[si], "A" jb CDLetter_NO cmp byte ptr ds:[si], "Z" ja CDLetter_NO cmp byte ptr ds:[si+1], ":" jne CDLetter_NO jmp short CDLetter_exit CDLetter_NO: stc CDLetter_exit: pop ax ret CHK_DRIVE_LETTER endp ; MOVE_ASCIIZ proc near ;In: DS:SI -> source ES:DI -> target ;Out: copy the string until 0. ;Assumes there exists a 0. MASCIIZ_loop: movsb cmp byte ptr DS:[SI-1], 0 ;Was it 0? jne MASCIIZ_loop ret MOVE_ASCIIZ endp ; ; DS:DX POINTS TO STRING TO OUTPUT (ASCIZ) ; ; PRINTS ; ; ; BADFIL: PUSH CS POP ES MOV SI,DX BADLOAD: MOV DX,OFFSET BADLD_PRE ;WANT TO PRINT CONFIG ERROR ; MOV BX,OFFSET BADLD_POST mov bx, offset CRLFM ;AN006; PRNERR: PUSH CS POP DS call Print PRN1: MOV DL,ES:[SI] OR DL,DL JZ PRN2 MOV AH,STD_CON_OUTPUT INT 21H INC SI JMP PRN1 PRN2: MOV DX,BX call Print cmp DoNotShowNum, 1 ;AN000; suppress line number when handling COMMAND.COM je Prnexit call Error_Line PRNEXIT: return PRINT: MOV AH,STD_CON_STRING_OUTPUT INT 21H return IF NOEXEC ; ; LOAD NON EXE FILE CALLED [DS:DX] AT MEMORY LOCATION ES:BX ; LDFIL: PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DS PUSH BX XOR AX,AX ;OPEN THE FILE MOV AH,OPEN STC ;IN CASE OF INT 24 INT 21H POP DX ;Clean stack in case jump JC LDRET PUSH DX MOV BX,AX ;Handle in BX XOR CX,CX XOR DX,DX MOV AX,(LSEEK SHL 8) OR 2 STC ;IN CASE OF INT 24 INT 21H ; Get file size in DX:AX JC LDCLSP OR DX,DX JNZ LDERRP ; File >64K POP DX PUSH DX MOV CX,ES ; CX:DX is xaddr ADD DX,AX ; Add file size to Xaddr JNC DOSIZE ADD CX,1000H ; ripple carry DOSIZE: mov ax,dx call ParaRound mov dx,ax ADD CX,DX CMP CX,[ALLOCLIM] JB OKLD JMP MEM_ERR OKLD: XOR CX,CX XOR DX,DX MOV AX,LSEEK SHL 8 ;Reset pointer to beginning of file STC ;IN CASE OF INT 24 INT 21H JC LDCLSP POP DX PUSH ES ;READ THE FILE IN POP DS ;Trans addr is DS:DX MOV CX,0FF00H ; .COM files arn't any bigger than ; 64k-100H MOV AH,READ STC ;IN CASE OF INT 24 INT 21H JC LDCLS MOV SI,DX ;CHECK FOR EXE FILE CMP WORD PTR [SI],"ZM" CLC ; Assume OK JNZ LDCLS ; Only know how to do .COM files STC JMP SHORT LDCLS LDERRP: STC LDCLSP: POP DX ;Clean stack LDCLS: PUSHF MOV AH,CLOSE ;CLOSE THE FILE STC INT 21H POPF LDRET: POP DS POP SI POP DX POP CX POP BX POP AX return ENDIF ; ; OPEN DEVICE POINTED TO BY DX, AL HAS ACCESS CODE ; IF UNABLE TO OPEN DO A DEVICE OPEN NULL DEVICE INSTEAD ; OPEN_DEV: CALL OPEN_FILE JNC OPEN_DEV3 OPEN_DEV1: MOV DX,OFFSET NULDEV CALL OPEN_FILE return OPEN_DEV3: MOV BX,AX ; Handle from open to BX XOR AX,AX ; GET DEVICE INFO MOV AH,IOCTL INT 21H TEST DL,10000000B retnz MOV AH,CLOSE INT 21H JMP OPEN_DEV1 OPEN_FILE: MOV AH,OPEN STC INT 21H return ;J.K. TEST INT24. Return back to DOS with the fake user response of "FAIL" INT24: mov al, 3 ;AN000; Fail the system call iret ;AN000; Return back to DOS. ;INT24: ADD SP,6 ;RESTORE MACHINE STATE ; POP AX ; POP BX ; POP CX ; POP DX ; POP SI ; POP DI ; POP BP ; POP DS ; POP ES ; PUSH AX ; MOV AH,GET_DEFAULT_DRIVE ;INITIALIZE DOS ; INT 21H ; POP AX ; IRET ;BACK TO USER IF ALTVECT BOOTMES DB 13,10,"MS-DOS version " DB MAJOR_VERSION + "0" DB "." DB (MINOR_VERSION / 10) + "0" DB (MINOR_VERSION MOD 10) + "0" DB 13,10 DB "Copyright 1981,88 Microsoft Corp.",13,10,"$" ENDIF include copyrigh.inc ;P1821; Copyright statement NULDEV DB "NUL",0 CONDEV DB "CON",0 AUXDEV DB "AUX",0 PRNDEV DB "PRN",0 CONFIG DB "\CONFIG.SYS",0 CNTRY_DRV DB "A:" CNTRY_ROOT DB "\" CNTRY_PATH DB "COUNTRY.SYS",0 DB 52 DUP (0) COUNTRY_FILE_SIGNATURE db 0FFh,'COUNTRY' CntryCodePage_Id DW ? COMMND DB "\COMMAND.COM",0 DB 51 dup (0) PathString db 64 dup (0) ;AN014; LShare db "SHARE.EXE",0,"/NC",0Dh,0Ah ;AN014;AN015;To be used by Load/exec. ;/NC parm will disable file sharing check. COMTAB LABEL BYTE ;;;; DB 8,"AVAILDEV",'A' ; NO LONGER SUPPORTED DB 7,"BUFFERS", 'B' DB 5,"BREAK", 'C' DB 6,"DEVICE", 'D' DB 5,"FILES", 'F' DB 4,"FCBS", 'X' DB 9,"LASTDRIVE",'L' db 10,"MULTITRACK", 'M' ;AN002; DB 8,"DRIVPARM", 'P' ; RS for DOS 3.2 IF STACKSW DB 6,"STACKS", 'K' ; BAS for DOS 3.2 ENDIF DB 7,"COUNTRY", 'Q' DB 5,"SHELL", 'S' db 7,"INSTALL", 'I' ;AN000; db 3,"IFS", 'J' ;AN000; db 4,"CPSW", 'W' ;AN000; ;;;; DB 8,"SWITCHAR",'W' ; NO LONGER SUPPORTED db 7,"COMMENT", 'Y' ;AN000; db 3,"REM", '0' ;AN004; db 8,"SWITCHES", '1' ;AN013; DB 0 public DeviceParameters DeviceParameters a_DeviceParameters <0,DEV_3INCH720KB,0,80> hlim dw 2 slim dw 9 public drive drive db ? public switches Switches dw 0 ; ; The following are the recommended BPBs for the media that we know of so ; far. ; 48 tpi diskettes BPB48T DW 512 DB 2 DW 1 DB 2 DW 112 DW 2*9*40 DB 0FDH DW 2 DW 9 DW 2 DD 0 DD 0 ; 96tpi diskettes BPB96T DW 512 DB 1 DW 1 DB 2 DW 224 DW 2*15*80 DB 0F9H DW 7 DW 15 DW 2 DD 0 DD 0 ; 3 1/2 inch diskette BPB BPB35 DW 512 DB 2 DW 1 DB 2 DW 70h DW 2*9*80 DB 0F9H DW 3 DW 9 DW 2 DD 0 DD 0 BPB35H DW 0200H DB 01H DW 0001H DB 02H DW 0E0h DW 0B40H DB 0F0H DW 0009H DW 0012H DW 0002H DD 0 DD 0 BPBTable dw BPB48T ; 48tpi drives dw BPB96T ; 96tpi drives dw BPB35 ; 3.5" drives ; The following are not supported, so default to 3.5" media layout dw BPB35 ; Not used - 8" drives dw BPB35 ; Not Used - 8" drives dw BPB35 ; Not Used - hard files dw BPB35 ; Not Used - tape drives dw BPB35H ; 3-1/2" 1.44MB drive switchlist db 8,"FHSTDICN" ; Preserve the positions of N and C. ; The following depend on the positions of the various letters in SwitchList switchnum equ 11111000B ; which switches require number flagec35 equ 00000100B ; electrically compatible 3.5 inch disk drive flagdrive equ 00001000B flagcyln equ 00010000B flagseclim equ 00100000B flagheads equ 01000000B flagff equ 10000000B SWTCHR EQU "/" ; switch follows this character SYSINITSEG ENDS END