windows-nt/Source/XPSP1/NT/base/mvdm/softpc.new/bios/sysconf.asm

3973 lines
90 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
page ,160
title bios system initialization
;
;----------------------------------------------------------------------------
;
; Modification history
;
; 26-Feb-1991 sudeepb Ported for NT DOSEm
;----------------------------------------------------------------------------
include version.inc ; set version build flags
include biosseg.inc ; establish bios segment structure
lf equ 10
cr equ 13
tab equ 9
have_install_cmd equ 00000001b ; config.sys has install= commands
has_installed equ 00000010b ; sysinit_base installed.
default_filenum = 8
break macro ; dummy empty macro
endm
include sysvar.inc
include pdb.inc ; M020
include syscall.inc
include doscntry.inc
include devsym.inc
include devmark.inc
include umb.inc
include dossym.inc
include dossvc.inc
include cmdsvc.inc
include softpc.inc
stacksw equ true ;include switchable hardware stacks
if ibmjapver
noexec equ true
else
noexec equ false
endif
; external variable defined in ibmbio module for multi-track
multrk_on equ 10000000b ;user spcified mutitrack=on,or system turns
; it on after handling config.sys file as a
; default value,if multrk_flag = multrk_off1.
multrk_off1 equ 00000000b ;initial value. no "multitrack=" command entered.
multrk_off2 equ 00000001b ;user specified multitrack=off.
Bios_Data segment
extrn multrk_flag:word
extrn keyrd_func:byte
extrn keysts_func:byte
Bios_Data ends
; end of multi-track definition.
sysinitseg segment
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 badstack:byte,badcountrycom:byte
extrn badcountry:byte,insufmemory:byte
extrn condev:byte,auxdev:byte,prndev:byte,commnd:byte,config:byte
extrn cntry_drv:byte,cntry_root:byte,cntry_path:byte
extrn memory_size:word
extrn buffers:word
extrn files:byte,num_cds:byte
extrn dosinfo:dword
extrn fcbs:byte,keep:byte
extrn confbot:word,alloclim:word,command_line:byte
extrn zero:byte,sepchr:byte
extrn count:word,chrptr:word,cntryfilehandle:word
extrn memlo:word,memhi:word,prmblk:word,ldoff:word
extrn packet:byte,unitcount:byte,break_addr:dword
extrn bpb_addr:dword,drivenumber:byte,sysi_country:dword
extrn config_size:word
extrn install_flag:word
extrn badorder:byte
extrn errorcmd:byte
extrn linecount:word
extrn showcount:byte
extrn buffer_linenum:word
extrn h_buffers:word
extrn badparm:byte
extrn configmsgflag:word
extrn org_count:word
extrn multi_pass_id:byte
extrn mem_err:near,setdoscountryinfo:near
extrn pararound:near,tempcds:near
extrn set_country_path:near,move_asciiz:near,delim:near
extrn badfil:near,round:near
extrn do_install_exec:near
extrn setdevmark:near
extrn print:near,organize:near,newline:near
extrn parseline:near
extrn badload:near,calldev:near,prnerr:near
extrn runhigh:byte
extrn IsXMSLoaded:near
extrn TryToMovDOSHi:near
ifdef DBCS
extrn testkanj:near
endif
extrn bEchoConfig:byte ; NTVDM flag off\on echo of cfg processing
if stacksw
; internal stack parameters
entrysize equ 8
mincount equ 8
defaultcount equ 9
maxcount equ 64
minsize equ 32
defaultsize equ 128
maxsize equ 512
DOS_FLAG_OFFSET equ 86h
extrn stack_count:word
extrn stack_size:word
extrn stack_addr:dword
endif
public doconf
public getchr
public multi_pass
public AllocUMB
public AllocUMBLow ; NTVDM
public multdeviceflag
multdeviceflag db 0
public devmark_addr
devmark_addr dw ? ;segment address for devmark.
public setdevmarkflag
setdevmarkflag db 0 ;flag used for devmark
ems_stub_installed db 0
IFDEF DONT_LOAD_OS2_DD ; M045
Os2ChkBuf DD 0 ; Tmp read buffer
ENDIF ; M045
badparm_ptr label dword
badparm_off dw 0
badparm_seg dw 0
;******************************************************************************
;take care of config.sys file.
;system parser data and code.
;******************************************************************************
;*******************************************************************
; parser options set for msbio sysconf module
;*******************************************************************
;
;**** default assemble swiches definition **************************
ifndef farsw
farsw equ 0 ; near call expected
endif
ifndef datesw
datesw equ 0 ; check date format
endif
ifndef timesw
timesw equ 0 ; check time format
endif
ifndef filesw
filesw equ 1 ; check file specification
endif
ifndef capsw
capsw equ 0 ; perform caps if specified
endif
ifndef cmpxsw
cmpxsw equ 0 ; check complex list
endif
ifndef numsw
numsw equ 1 ; check numeric value
endif
ifndef keysw
keysw equ 0 ; support keywords
endif
ifndef swsw
swsw equ 1 ; support switches
endif
ifndef val1sw
val1sw equ 1 ; support value definition 1
endif
ifndef val2sw
val2sw equ 0 ; support value definition 2
endif
ifndef val3sw
val3sw equ 1 ; support value definition 3
endif
ifndef drvsw
drvsw equ 1 ; support drive only format
endif
ifndef qussw
qussw equ 0 ; support quoted string format
endif
include parse.asm ;together with psdata.inc
;control block definitions for parser.
;---------------------------------------------------
; buffer = [n | n,m] {/e}
p_parms struc
dw ?
db 1 ; an extra delimiter list
db 1 ; length is 1
db ';' ; delimiter
p_parms ends
p_pos struc
dw ? ; numeric value??
dw ? ; function
dw ? ; result value buffer
; note: by defining result_val before this structure, we could remove
; the "result_val" from every structure invocation
dw ? ; value list
db 0 ; no switches/keywords
p_pos ends
p_range struc
db 1 ; range definition
db 1 ; 1 definition of range
db 1 ; item tag for this range
dd ? ; numeric min
dd ? ; numeric max
p_range ends
buf_parms p_parms <buf_parmsx>
buf_parmsx dw 201h,buf_pos1,buf_pos2 ; min 1, max 2 positionals
db 1 ; one switch
dw sw_x_ctrl
db 0 ; no keywords
buf_pos1 p_pos <8000h,0,result_val,buf_range_1> ; numeric
buf_range_1 p_range <,,,1,99> ; M050
buf_pos2 p_pos <8001h,0,result_val,buf_range_2> ; optional num.
buf_range_2 p_range <,,,0,8>
sw_x_ctrl p_pos <0,0,result_val,noval,1> ; followed by one switch
switch_x db '/X',0 ; M016
p_buffers dw 0 ; local variables
p_h_buffers dw 0
p_buffer_slash_x db 0
;common definitions ------------
noval db 0
result_val label byte
db ? ; type returned
db ? ; item tag returned
dw ? ; es:offset of the switch defined
rv_byte label byte
rv_dword dd ? ; value if number,or seg:offset to string.
;-------------------------------
; break = [ on | off ]
brk_parms p_parms <brk_parmsx>
brk_parmsx dw 101h,brk_pos ; min,max = 1 positional
db 0 ; no switches
db 0 ; no keywords
brk_pos p_pos <2000h,0,result_val,on_off_string> ; simple string
on_off_string label byte
db 3 ; signals that there is a string choice
db 0 ; no range definition
db 0 ; no numeric values choice
db 2 ; 2 strings for choice
db 1 ; the 1st string tag
dw on_string
db 2 ; the 2nd string tag
dw off_string
on_string db "ON",0
off_string db "OFF",0
p_ctrl_break db 0 ; local variable
;--------------------------------
; country = n {m {path}}
; or
; country = n,,path
cntry_parms p_parms <cntry_parmsx>
cntry_parmsx dw 301h,cntry_pos1,cntry_pos2,cntry_pos3 ; min 1, max 3 pos.
db 0 ; no switches
db 0 ; no keywords
cntry_pos1 p_pos <8000h,0,result_val,cc_range> ; numeric value
cc_range p_range <,,,1,999>
cntry_pos2 p_pos <8001h,0,result_val,cc_range> ; optional num.
cntry_pos3 p_pos <201h,0,result_val,noval> ; optional filespec
p_cntry_code dw 0 ; local variable
p_code_page dw 0 ; local variable
;--------------------------------
; files = n
files_parms p_parms <files_parmsx>
files_parmsx dw 101h,files_pos ; min,max 1 positional
db 0 ; no switches
db 0 ; no keywords
files_pos p_pos <8000h,0,result_val,files_range,0> ; numeric value
files_range p_range <,,,8,255>
p_files db 0 ; local variable
;-------------------------------
; fcbs = n,m
fcbs_parms p_parms <fcbs_parmsx>
fcbs_parmsx dw 201h,fcbs_pos_1,fcbs_pos_2 ; min,max = 2 positional
db 0 ; no switches
db 0 ; no keywords
fcbs_pos_1 p_pos <8000h,0,result_val,fcbs_range> ; numeric value
fcbs_range p_range <,,,1,255>
fcbs_pos_2 p_pos <8000h,0,result_val,fcbs_keep_range> ; numeric value
fcbs_keep_range p_range <,,,0,255>
p_fcbs db 0 ; local variable
p_keep db 0 ; local variable
;-------------------------------
; lastdrive = x
ldrv_parms p_parms <ldrv_parmsx>
ldrv_parmsx dw 101h,ldrv_pos ; min,max = 1 positional
db 0 ; no switches
db 0 ; no keywords
ldrv_pos p_pos <110h,10h,result_val,noval> ; drive only, ignore colon
; remove colon at end
p_ldrv db 0 ; local variable
;-------------------------------
; stacks = n,m
stks_parms p_parms <stks_parmsx>
stks_parmsx dw 202h,stks_pos_1,stks_pos_2 ; min,max = 2 positionals
db 0 ; no switches
db 0 ; no keywords
stks_pos_1 p_pos <8000h,0,result_val,stks_range> ; numeric value
stks_range p_range <,,,0,64>
stks_pos_2 p_pos <8000h,0,result_val,stk_size_range> ; numeric value
stk_size_range p_range <,,,0,512>
p_stack_count dw 0 ; local variable
p_stack_size dw 0 ; local variable
;-------------------------------
; multitrack = [ on | off ]
mtrk_parms p_parms <mtrk_parmsx>
mtrk_parmsx dw 101h,mtrk_pos ; min,max = 1 positional
db 0 ; no switches
db 0 ; no keywords
mtrk_pos p_pos <2000h,0,result_val,on_off_string> ; simple string
p_mtrk db 0 ; local variable
;-------------------------------
; switches=/k
swit_parms p_parms <swit_parmsx>
swit_parmsx dw 0 ; no positionals
db 3 ; 2 switches for now. M059 M063
dw swit_k_ctrl ; /k control
dw swit_t_ctrl ; /t control M059
dw swit_w_ctrl ; /w control M063
db 0 ; no keywords
swit_k_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows
swit_k db '/K',0
swit_t_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows M059
swit_t db '/T',0 ; M059
swit_w_ctrl p_pos <0,0,result_val,noval,1> ; switch string follows M063
swit_w db '/W',0 ; M063
p_swit_k db 0 ; local variable
p_swit_t db 0 ; local variable M059
p_swit_w db 0 ; local variable M063
;-------------------------------
; DOS = [ high | low ]
dos_parms p_parms <dos_parmsx>
dos_parmsx db 1 ; min parameters
db 2 ; max parameters
dw dos_pos ;
dw dos_pos ;
db 0 ; no switches
db 0 ; no keywords
dos_pos p_pos <2000h,0,result_val,dos_strings> ; simple string
p_pos <2000h,0,result_val,dos_strings> ; simple string
dos_strings label byte
db 3 ; signals that there is a string choice
db 0 ; no range definition
db 0 ; no numeric values choice
db 4 ; 4 strings for choice
db 1 ; the 1st string tag
dw hi_string
db 2 ; the 2nd string tag
dw lo_string
db 3
dw umb_string
db 4
dw noumb_string
hi_string db "HIGH",0
lo_string db "LOW",0
umb_string db "UMB",0
noumb_string db "NOUMB",0
p_dos_hi db 0 ; local variable
; BUGBUG : I dont know whether PARSER uses
; this variable or not
;******************************************************************************
public DevEntry
DevSize dw ? ; size of the device driver being loaded(paras)
DevLoadAddr dw ? ; Mem addr where the device driver is 2 b loaded
DevLoadEnd dw ? ; MaxAddr to which device can be loaded
DevEntry dd ? ; Entry point to the device driver
DevBrkAddr dd ? ; Break address of the device driver
;
DevUMB db 0 ; byte indicating whether to load DDs in UMBs
DevUMBAddr dw 0 ; cuurent UMB used fro loading devices (paras)
DevUMBSize dw 0 ; Size of the current UMB being used (paras)
DevUMBFree dw 0 ; Start of free are in the current UMB (paras)
;
DevXMSAddr dd ?
;
DevExecAddr dw ? ; Device load address parameter to Exec call
DevExecReloc dw ? ; Device load relocation factor
;
DeviceHi db 0 ; Flag indicating whther the current device
; is being loaded into UMB
DevSizeOption dw ? ; SIZE= option
;
Int12Lied db 0 ; did we trap int 12 ?
OldInt12Mem dw ? ; value in 40:13h (int 12 ram)
ThreeComName db 'PROTMAN$' ; 3Com Device name
;
FirstUMBLinked db 0
DevDOSData dw ? ; segment of DOS Data
DevCmdLine dd ? ; Current Command line
DevSavedDelim db ? ; The delimiter which was replaced with null
; to use the file name in the command line
;
;----------------------------------------------------------------------------
;
; procedure : doconf
;
; Config file is parsed intitially with this routine. For the
; Subsequent passes 'multi_pass' entry is used .
;
;----------------------------------------------------------------------------
;
doconf proc near
push cs
pop ds
assume ds:sysinitseg
mov ax,(char_oper shl 8) ;get switch character
int 21h
mov [command_line+1],dl ; set in default command line
mov dx,offset config ;now pointing to file description
mov ax,open shl 8 ;open file "config.sys"
stc ;in case of int 24
int 21h ;function request
jnc noprob ; brif opened okay
mov multi_pass_id,11 ; set it to unreasonable number
ret
noprob: ;get file size (note < 64k!!)
mov bx,ax
xor cx,cx
xor dx,dx
mov ax,(lseek shl 8) or 2
int 21h
mov [count],ax
xor dx,dx
mov ax,lseek shl 8 ;reset pointer to beginning of file
int 21h
mov dx,[confbot] ;use current confbot value
mov ax,[count]
mov [config_size],ax ;save the size of config.sys file.
call pararound
sub dx,ax
sub dx,11h ;room for header
mov [confbot],dx ; config starts here. new conbot value.
call tempcds ; finally get cds to "safe" location
assume ds:nothing,es:nothing
mov dx,[confbot]
mov ds,dx
mov es,dx
xor dx,dx
mov cx,[count]
mov ah,read
stc ;in case of int 24
int 21h ;function request
pushf
; find the eof mark in the file. if present,then trim length.
push ax
push di
push cx
mov al,1ah ; eof mark
mov di,dx ; point ro buffer
jcxz puteol ; no chars
repnz scasb ; find end
jnz puteol ; none found and count exahusted
; we found a 1a. back up
dec di ; backup past 1a
; just for the halibut,stick in an extra eol
puteol:
mov al,cr
stosb
mov al,lf
stosb
sub di,dx ; difference moved
mov count,di ; new count
pop cx
pop di
pop ax
push cs
pop ds
assume ds:sysinitseg
push ax
mov ah,close
int 21h
pop ax
popf
jc conferr ;if not we've got a problem
cmp cx,ax
jz getcom ;couldn't read the file
conferr:
mov dx,offset config ;want to print config error
call badfil
endconv:
ret
;
;----------------------------------------------------------------------------
;
; entry : multi_pass
;
; called to execute device=,install= commands
;
;----------------------------------------------------------------------------
;
multi_pass:
push cs
pop ds
cmp multi_pass_id,10
jae endconv ; do nothing. just return.
push confbot
pop es ; es -> confbot
mov si,org_count
mov count,si ; set count
xor si,si
mov chrptr,si ; reset chrptr,linecount
mov linecount,si
call getchr
jmp short conflp
getcom:
call organize ;organize the file
call getchr
conflp: jc endconv
;*** call reset_dos_version ; still need to reset version even ibmdos handles this through
;*** ; function 4bh call,since ibmdos does not know when load/overlay call finishes.
inc linecount ; increase linecount.
mov multdeviceflag,0 ; reset multdeviceflag.
mov setdevmarkflag,0 ; reset setdevmarkflag.
cmp al,lf ; linefeed?
je blank_line ; then ignore this line.
mov ah,al
call getchr
jnc tryi
cmp multi_pass_id,2
jae endconv ;do not show badop again for multi_pass.
jmp badop
coff: push cs
pop ds
call newline
jmp conflp
blank_line:
call getchr
jmp conflp
coff_p:
push cs
pop ds
;to handle install= commands,we are going to use multi-pass.
;the first pass handles the other commands and only set install_flag when
;it finds any install command. the second pass will only handle the
;install= command.
;------------------------------------------------------------------------------
;install command
;------------------------------------------------------------------------------
tryi:
cmp multi_pass_id,0 ; the initial pass for DOS=HI
je multi_try_doshi
cmp multi_pass_id,2 ; the second pass was for ifs=
je coff ; now it is NOPs
; This pass can be made use of if
; we want do some config.sys process
; after device drivers are loaded
; and before install= commands
; are processed
cmp multi_pass_id,3 ; the third pass for install= ?
je multi_try_i
cmp ah, 'H'
je coff
cmp ah, 'E'
je coff
cmp ah,'I' ; install= command?
jne tryb ; the first pass is for normal operation.
or install_flag,have_install_cmd ; set the flag
jmp coff ; and handles the next command
multi_try_i:
cmp ah,'I' ; install= command?
jne multi_pass_filter ; no. ignore this.
call do_install_exec ;install it.
jmp coff ;to handle next install= command.
multi_pass_filter:
cmp ah,'Y' ; comment?
je multi_pass_adjust
cmp ah,'Z' ; bad command?
je multi_pass_adjust
cmp ah,'0' ; rem?
jne coff ; ignore the rest of the commands.
multi_pass_adjust: ; these commands need to
dec chrptr ; adjust chrptr,count
inc count ; for newline proc.
multi_pass_coff:
jmp coff ; to handle next install= commands.
;----------------------------------------------------------------------------
; DOS=HIGH/LOW command
;
; EchoConfig command turns on con echo for config processing
; NTVDM 14-Aug-1992 Jonle
;----------------------------------------------------------------------------
;
multi_try_doshi:
cmp ah, 'H'
je it_is_h
cmp ah, 'E'
jne multi_pass_filter
mov cs:bEchoConfig, ah ; init console
CMDSVC SVC_CMDINITCONSOLE
jmp coff
it_is_h: ; M003 - removed initing DevUMB
; & runhigh
mov di,offset dos_parms
xor cx,cx
mov dx,cx
h_do_parse:
call sysinit_parse
jnc h_parse_ok ; parse error
h_badparm:
call badparm_p ; show message and end the serach loop.
jmp short h_end
h_parse_ok:
cmp ax,$p_rc_eol ; end of line?
jz h_end ; then end the $endloop
call ProcDOS
jmp short h_do_parse
h_end:
jmp coff
;------------------------------------------------------------------------------
; buffer command
;------------------------------------------------------------------------------
;*******************************************************************************
; *
; function: parse the parameters of buffers= command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; buffers set *
; buffer_slash_x flag set if /x option chosen. *
; h_buffers set if secondary buffer cache specified. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di points to buf_parms; /*parse control definition*/ *
; set dx,cx to 0; *
; reset buffer_slash_x; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; if (result_val.$p_synonym_ptr == slash_e) then /*not a switch *
; buffer_slash_x = 1 *
; else if (cx == 1) then /* first positional */ *
; buffers = result_val.$p_picked_val; *
; else h_buffers = result_val.$p_picked_val; *
; else {show error message;error exit} *
; }; *
; if (buffer_slash_x is off & buffers > 99) then show_error; *
; }; *
; *
;*******************************************************************************
tryb:
cmp ah,'B'
jnz tryc
; NTVDM - buffers command is ignored
; 15-Aug-1992 Jonle
jmp coff
if 0
mov p_buffer_slash_x,0
mov di,offset buf_parms
xor cx,cx
mov dx,cx
do7:
call sysinit_parse
jnc if7 ; parse error,
call badparm_p ; and show messages and end the search loop.
jmp short sr7
if7:
cmp ax,$p_rc_eol ; end of line?
jz en7 ; then jmp to $endloop for semantic check
cmp result_val.$p_synonym_ptr,offset switch_x
jnz if11
; mov p_buffer_slash_x,1 ; set the flag M016
jmp short en11
if11:
mov ax,word ptr result_val.$p_picked_val
cmp cx,1
jnz if13
mov p_buffers,ax
jmp short en11
if13:
mov p_h_buffers,ax
en11:
jmp do7
en7:
cmp p_buffers,99
jbe if18
; cmp p_buffer_slash_x,0 ; M016
; jnz if18
call badparm_p
mov p_h_buffers,0
jmp short sr7
if18:
mov ax,p_buffers ; we don't have any problem.
mov buffers,ax ; now,let's set it really.
mov ax,p_h_buffers
mov h_buffers,ax
; mov al,p_buffer_slash_x ; M016
; mov buffer_slash_x,al
mov ax,linecount
mov buffer_linenum,ax ; save the line number for the future use.
sr7:
jmp coff
endif
;------------------------------------------------------------------------------
; break command
;------------------------------------------------------------------------------
;****************************************************************************
; *
; function: parse the parameters of break = command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; turn the control-c check on or off. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di to brk_parms; *
; set dx,cx to 0; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; if (result_val.$p_item_tag == 1) then /*on */ *
; set p_ctrl_break,on; *
; else /*off */ *
; set p_ctrl_break,off; *
; else {show message;error_exit}; *
; }; *
; if (no error) then *
; dos function call to set ctrl_break check according to *
; }; *
; *
;****************************************************************************
tryc:
cmp ah,'C'
jnz trym
mov di,offset brk_parms
xor cx,cx
mov dx,cx
do22:
call sysinit_parse
jnc if22 ; parse error
call badparm_p ; show message and end the serach loop.
jmp short sr22
if22:
cmp ax,$p_rc_eol ; end of line?
jz en22 ; then end the $endloop
cmp result_val.$p_item_tag,1
jnz if26
mov p_ctrl_break,1 ; turn it on
jmp short en26
if26:
mov p_ctrl_break,0 ; turn it off
en26:
jmp short do22 ; we actually set the ctrl break
en22:
mov ah,set_ctrl_c_trapping ; if we don't have any parse error.
mov al,1
mov dl,p_ctrl_break
int 21h
sr22:
jmp coff
;------------------------------------------------------------------------------
; multitrack command
;------------------------------------------------------------------------------
;******************************************************************************
; *
; function: parse the parameters of multitrack= command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; turn multrk_flag on or off. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di to brk_parms; *
; set dx,cx to 0; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; if (result_val.$p_item_tag == 1) then /*on */ *
; set p_mtrk,on; *
; else /*off */ *
; set p_mtrk,off; *
; else {show message;error_exit}; *
; }; *
; if (no error) then *
; dos function call to set multrk_flag according to p_mtrk. *
; *
; }; *
; *
;******************************************************************************
trym:
cmp ah,'M'
jnz tryu
mov di,offset mtrk_parms
xor cx,cx
mov dx,cx
do31:
call sysinit_parse
jnc if31 ; parse error
call badparm_p ; show message and end the serach loop.
jmp short sr31
if31:
cmp ax,$p_rc_eol ; end of line?
jz en31 ; then end the $endloop
cmp result_val.$p_item_tag,1
jnz if35
mov p_mtrk,1 ; turn it on temporarily.
jmp short en35
if35:
mov p_mtrk,0 ; turn it off temporarily.
en35:
jmp short do31 ; we actually set the multrk_flag here
en31:
push ds
mov ax,Bios_Data
mov ds,ax
assume ds:Bios_Data
cmp p_mtrk,0
jnz if39
mov multrk_flag,multrk_off2 ; 0001h
jmp short en39
if39:
mov multrk_flag,multrk_on ; 8000h
en39:
pop ds
assume ds:sysinitseg
sr31:
jmp coff
;
;-----------------------------------------------------------------------------
; devicehigh command
;-----------------------------------------------------------------------------
;
assume ds:nothing
tryu:
cmp ah, 'U'
jne tryd
mov badparm_off, si ; stash it there in case of an error
mov badparm_seg, es
call ParseSize ; process the size= option
jnc @f
call badparm_p
jmp coff
@@:
push si
push es
@@:
mov al, es:[si]
cmp al, cr
je @f
cmp al, lf
je @f
call delim
jz @f
inc si
jmp @b
@@:
mov DevSavedDelim, al ; Save the delimiter before replacing
; it with null
mov byte ptr es:[si], 0
pop es
pop si
mov DeviceHi, 0
cmp DevUMB, 0 ; do we support UMBs
je LoadDevice ; no, we don't
mov DeviceHi, 1
jmp short LoadDevice
;
;------------------------------------------------------------------------------
; device command
;------------------------------------------------------------------------------
assume ds:nothing
tryd:
cmp ah,'D'
jz gotd
jmp tryq
gotd:
mov DeviceHi, 0 ; not to be loaded in UMB ;M007
mov DevSizeOption, 0
mov DevSavedDelim, ' ' ; In case of DEVICE= the null has to
; be replaced with a ' '
LoadDevice:
mov bx,cs ;device= or devicehigh= command.
mov ds,bx
mov word ptr [bpb_addr],si ; pass the command line to the dvice
mov word ptr [bpb_addr+2],es
mov word ptr DevCmdLine, si ; save it for ourself
mov word ptr DevCmdLine+2, es
call round
call SizeDevice
jc BadFile
call InitDevLoad
mov ax, DevLoadAddr
add ax, DevSize
jc NoMem
cmp DevLoadEnd, ax
jae LoadDev
NoMem:
jmp mem_err
BadFile:
cmp byte ptr es:[si], cr
jne @f
jmp badop
@@:
call badload
jmp coff
LoadDev:
push es
pop ds
assume ds:nothing
mov dx,si ;ds:dx points to file name
if noexec
les bx,dword ptr cs:[memlo]
call ldfil ;load in the device driver
else
call ExecDev ; load device driver using exec call
endif
badldreset:
push ds
pop es ;es:si back to config.sys
push cs
pop ds ;ds back to sysinit
jc BadFile
goodld:
push es
push si ; ???
call RemoveNull
push es
push si
push cs
pop es
;NTVDM: block device drivers are not supported.
; Putup user warning popup for unsupported device driver
; 29-Sep-1992 Jonle
;
push ds
push si
lds si, DevEntry ; peek the header attribute
test word ptr ds:[si.sdevatt],devtyp ; IS block device driver?
pop si
pop ds
jnz got_device_com_cont ; no!
pop si ;clear the stack
pop es
mov ax, NOSUPPORT_DRIVER
BOP BOP_NOSUPPORT
jmp short erase_dev_do
got_device_com_cont:
call LieInt12Mem
call UpdatePDB ; update the PSP:2 value M020
cmp cs:multdeviceflag, 0 ; Pass limit only for the 1st device
; driver in the file ; M027
jne skip_pass_limit ; ; M027
mov word ptr break_addr, 0 ; pass the limit to the DD
mov bx, DevLoadEnd
mov word ptr break_addr+2, bx
skip_pass_limit: ; M027
mov bx,sdevstrat
call calldev ; calldev (sdevstrat);
mov bx,sdevint
call calldev ; calldev (sdevint);
call TrueInt12Mem
mov ax, word ptr break_addr ; move break addr from the req packet
mov word ptr DevBrkAddr, ax
mov ax, word ptr break_addr+2
mov word ptr DevBrkAddr+2, ax
assume ds:nothing
cmp DevUMB, 0
jz @f
call AllocUMB
@@:
;
;------ If we are waiting to be moved into hma lets try it now !!!
;
cmp runhigh, 0ffh
jne @f
call TryToMovDOSHi ; move DOS into HMA if reqd
@@:
pop si
pop ds
mov byte ptr [si],0 ; *p = 0;
push cs
pop ds
jmp short was_device_com
erase_dev_do: ; modified to show message "error in config.sys..."
pop si
pop es
push cs
pop ds
; test [setdevmarkflag],setbrkdone ;if already set_break is done,
; jnz skip1_resetmemhi ; then do not
; dec [memhi] ;adjust memhi by a paragrah of devmark.
skip1_resetmemhi:
cmp configmsgflag,0
je no_error_line_msg
call error_line ; no "error in config.sys" msg for device driver. dcr d493
mov configmsgflag,0 ;set the default value again.
no_error_line_msg:
jmp coff
;
;----------------------------------------------------------------------------
;
was_device_com:
mov ax,word ptr [DevBrkAddr+2]
cmp ax,DevLoadEnd
jbe breakok
pop si
pop es
jmp BadFile
breakok:
lds si,DevEntry ;ds:si points to header
les di,cs:[dosinfo] ;es:di point to dos info
mov ax,ds:[si.sdevatt] ;ax Dev attributes
;
;------ lets deal with character devices,
; NTVDM: removed check for block drivers, jonle
;
ischardev:
or cs:[setdevmarkflag],for_devmark
call DevSetBreak ; go ahead and alloc mem for device
jc erase_dev_do ;device driver's init routine failed.
test ax,iscin ;is it a console in?
jz tryclk
mov word ptr es:[di.sysi_con],si
mov word ptr es:[di.sysi_con+2],ds
tryclk: test ax,isclock ;is it a clock device?
jz linkit
mov word ptr es:[di+sysi_clock],si
mov word ptr es:[di+sysi_clock+2],ds
linkit:
mov cx,word ptr es:[di.sysi_dev] ;dx:cx = head of list
mov dx,word ptr es:[di.sysi_dev+2]
mov word ptr es:[di.sysi_dev],si ;set head of list in dos
mov word ptr es:[di.sysi_dev+2],ds
mov ax,ds:[si] ;get pointer to next device
mov word ptr cs:[DevEntry],ax ;and save it
mov word ptr ds:[si],cx ;link in the driver
mov word ptr ds:[si+2],dx
enddev:
pop si
pop es
inc ax ;ax = ffff (no more devs if yes)?
jz coffj3
inc cs:multdeviceflag ; possibly multiple device driver.
call DevBreak ; M009
jmp goodld ; otherwise pretend we loaded it in
coffj3: mov cs:multdeviceflag,0 ; reset the flag
call DevBreak
jmp coff
bad_bpb_size_sector:
pop si
pop es
mov dx,offset badsiz_pre
mov bx,offset crlfm
call prnerr
; test [setdevmarkflag],setbrkdone ;if already set_break is done,
; jnz skip2_resetmemhi ; then do not
; dec [memhi] ;adjust memhi by a paragrah of devmark.
skip2_resetmemhi:
jmp coff
;------------------------------------------------------------------------------
; country command
; the syntax is:
; country=country id {,codepage {,path}}
; country=country id {,,path} :default codepage id in dos
;------------------------------------------------------------------------------
tryq:
cmp ah,'Q'
jz tryq_cont
jmp tryf
tryq_cont:
mov cntry_drv,0 ; reset the drive,path to default value.
mov p_code_page,0
mov di,offset cntry_parms
xor cx,cx
mov dx,cx
do52:
call sysinit_parse
jnc if52 ; parse error,check error code and
call cntry_error ; show message and end the search loop.
mov p_cntry_code,-1 ; signals that parse error.
jmp short sr52
if52:
cmp ax,$p_rc_eol ; end of line?
jz sr52 ; then end the search loop
cmp result_val.$p_type,$p_number ; numeric?
jnz if56
mov ax,word ptr result_val.$p_picked_val
cmp cx,1
jnz if57
mov p_cntry_code,ax
jmp short en57
if57:
mov p_code_page,ax
en57:
jmp short en56 ; path entered
if56:
push ds
push es
push si
push di
push cs
pop es
lds si,rv_dword ; move the path to known place.
mov di,offset cntry_drv
call move_asciiz
pop di
pop si
pop es
pop ds
en56:
jmp do52
sr52:
cmp p_cntry_code,-1 ; had a parse error?
jne tryq_open
jmp coff
tryqbad: ;"invalid country code or code page"
stc
mov dx,offset badcountry
jmp tryqchkerr
tryq_open:
cmp cntry_drv,0
je tryq_def
mov dx,offset cntry_drv
jmp short tryq_openit
tryq_def:
mov dx,offset cntry_root
tryq_openit:
mov ax,3d00h ;open a file
stc
int 21h
jc tryqfilebad ;open failure
mov cs:cntryfilehandle,ax ;save file handle
mov bx,ax
mov ax,cs:p_cntry_code
mov dx,cs:p_code_page ; now,ax=country id,bx=filehandle
mov cx,cs:[memhi]
add cx,384 ; need 6k buffer to handle country.sys
; M023
cmp cx,cs:[alloclim]
ja tryqmemory ;cannot allocate the buffer for country.sys
mov si,offset cntry_drv ;ds:si -> cntry_drv
cmp byte ptr [si],0 ;default path?
jne tryq_set_for_dos
inc si
inc si ;ds:si -> cntry_root
tryq_set_for_dos:
les di,cs:sysi_country ;es:di -> country info tab in dos
push di ;save di
add di,ccpath_countrysys
call move_asciiz ;set the path to country.sys in dos.
pop di ;es:di -> country info tab again.
mov cx,cs:[memhi]
mov ds,cx
xor si,si ;ds:si -> 2k buffer to be used.
call setdoscountryinfo ;now do the job!!!
jnc tryqchkerr ;read error or could not find country,code page combination
cmp cx,-1 ;could not find matching country_id,code page?
je tryqbad ;then "invalid country code or code page"
tryqfilebad:
push cs
pop es
cmp cs:cntry_drv,0 ;is the default file used?
je tryqdefbad
mov si,offset cntry_drv
jmp short tryqbadload
tryqdefbad: ;default file has been used.
mov si,offset cntry_root ;es:si -> \country.sys in sysinit_seg
tryqbadload:
call badload ;ds will be restored to sysinit_seg
mov cx,cs:[confbot]
mov es,cx ;restore es -> confbot.
jmp short coffj4
tryqmemory:
mov dx,offset insufmemory
tryqchkerr:
mov cx,cs:[confbot]
mov es,cx ;restore es -> confbot seg
push cs
pop ds ;retore ds to sysinit_seg
jnc coffj4 ;if no error,then exit
call print ;else show error message
call error_line
coffj4:
mov bx,cntryfilehandle
mov ah,3eh
int 21h ;close a file. don't care even if it fails.
jmp coff
cntry_error proc near
;function: show "invalid country code or code page" messages,or
; "error in country command" depending on the error code
; in ax returned by sysparse;
;in: ax - error code
; ds - sysinitseg
; es - confbot
;out: show message. dx destroyed.
cmp ax,$p_out_of_range
jnz if64
mov dx,offset badcountry ;"invalid country code or code page"
jmp short en64
if64:
mov dx,offset badcountrycom ;"error in contry command"
en64:
call print
call error_line
ret
cntry_error endp
;------------------------------------------------------------------------------
; files command
;------------------------------------------------------------------------------
;*******************************************************************************
; function: parse the parameters of files= command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; variable files set. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di points to files_parms; *
; set dx,cx to 0; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; files = result_val.$p_picked_val *
; else *
; error exit; *
; }; *
; }; *
; *
;*******************************************************************************
tryf:
cmp ah,'F'
jnz tryl
mov di,offset files_parms
xor cx,cx
mov dx,cx
do67:
call sysinit_parse
jnc if67 ; parse error
call badparm_p ; and show messages and end the search loop.
jmp short sr67
if67:
cmp ax,$p_rc_eol ; end of line?
jz en67 ; then end the $endloop
mov al,byte ptr result_val.$p_picked_val
mov p_files,al ; save it temporarily
jmp short do67
en67:
mov al,p_files
SVC SVC_DEMWOWFILES ; For WOW VDM Set the file= to max.
mov files,al ; no error. really set the value now.
sr67:
jmp coff
;------------------------------------------------------------------------------
; lastdrive command
;------------------------------------------------------------------------------
;*******************************************************************************
; function: parse the parameters of lastdrive= command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; set the variable num_cds. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di points to ldrv_parms; *
; set dx,cx to 0; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; set num_cds to the returned value; *
; else /*error exit*/ *
; error exit; *
; }; *
; }; *
; *
;*******************************************************************************
tryl:
cmp ah,'L'
jnz tryp
jmp coff
;NTVDM Ignore the lastdrive command. Dos will figure this from the host OS.
; 17-Aug-1992 Jonle
if 0
mov di,offset ldrv_parms
xor cx,cx
mov dx,cx
do73:
call sysinit_parse
jnc if73 ; parse error
call badparm_p ; and show messages and end the search loop.
jmp short sr73
if73:
cmp ax,$p_rc_eol ; end of line?
jz en73 ; then end the $endloop
mov al,rv_byte ; pick up the drive number
mov p_ldrv,al ; save it temporarily
jmp do73
en73:
mov al,p_ldrv
mov num_cds,al ; no error. really set the value now.
sr73:
jmp coff
endif
;--------------------------------------------------------------------------
; setting drive parameters
;--------------------------------------------------------------------------
tryp:
cmp ah,'P'
jnz tryk
jmp coff
; sudeepb 04-Mar-1991 : Ignoring DRIVEPARM command
; call parseline
; jc trypbad
;
; call setparms
; call diddleback
; jc trypbad
; jmp coff
;trypbad:jmp badop
;--------------------------------------------------------------------------
; setting internal stack parameters
; stacks=m,n where
; m is the number of stacks (range 8 to 64,default 9)
; n is the stack size (range 32 to 512 bytes,default 128)
; j.k. 5/5/86: stacks=0,0 implies no stack installation.
; any combinations that are not within the specified limits will
; result in "unrecognized command" error.
;--------------------------------------------------------------------------
;****************************************************************************
; *
; function: parse the parameters of stacks= command. *
; the minimum value for "number of stacks" and "stack size" is *
; 8 and 32 each. in the definition of sysparse value list,they *
; are set to 0. this is for accepting the exceptional case of *
; stacks=0,0 case (,which means do not install the stack.) *
; so,after sysparse is done,we have to check if the entered *
; values (stack_count,stack_size) are within the actual range, *
; (or if "0,0" pair has been entered.) *
; input : *
; es:si -> parameters in command line. *
; output: *
; set the variables stack_count,stack_size. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di points to stks_parms; *
; set dx,cx to 0; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; { if (cx == 1) then /* first positional = stack count */ *
; p_stack_count = result_val.$p_picked_val; *
; if (cx == 2) then /* second positional = stack size */ *
; p_stack_size = result_val.$p_picked_val; *
; } *
; else /*error exit*/ *
; error exit; *
; }; *
; here check p_stack_count,p_stack_size if it meets the condition; *
; if o.k.,then set stack_count,stack_size; *
; else error_exit; *
; }; *
;****************************************************************************
tryk:
cmp ah,'K'
je do_tryk
jmp trys
if stacksw
do_tryk:
mov di,offset stks_parms
xor cx,cx
mov dx,cx
do79:
call sysinit_parse
jnc if79 ; parse error
mov dx,offset badstack ; "invalid stack parameter"
call print ; and show messages and end the search loop.
call error_line
jmp sr79
if79:
cmp ax,$p_rc_eol ; end of line?
jz en79 ; then end the $endloop
mov ax,word ptr result_val.$p_picked_val
cmp cx,1
jnz if83
mov p_stack_count,ax
jmp short en83
if83:
mov p_stack_size,ax
en83:
jmp do79
en79:
cmp p_stack_count,0
jz if87
cmp p_stack_count,mincount
jb ll88
cmp p_stack_size,minsize
jnb if88
ll88:
mov p_stack_count,-1 ; invalid
if88:
jmp short en87
if87:
cmp p_stack_size,0
jz en87
mov p_stack_count,-1 ; invalid
en87:
cmp p_stack_count,-1 ; invalid?
jnz if94
mov stack_count,defaultcount ;reset to default value.
mov stack_size,defaultsize
mov word ptr stack_addr,0
mov dx,offset badstack
call print
call error_line
jmp short sr79
if94:
mov ax,p_stack_count
mov stack_count,ax
mov ax,p_stack_size
mov stack_size,ax
mov word ptr stack_addr,-1 ; stacks= been accepted.
sr79:
jmp coff
endif
;------------------------------------------------------------------------
; shell command
;------------------------------------------------------------------------
trys:
cmp ah,'S'
jnz tryx
mov [command_line+1],0
mov di,offset commnd + 1
mov [di-1],al
storeshell:
call getchr
or al,al
jz getshparms
cmp al," "
jb endsh
mov [di],al
inc di
jmp storeshell
endsh:
mov byte ptr [di],0
; push di
; mov di,offset commnd
; SVC SVC_SETSHELLNAME
; pop di
call getchr
cmp al,lf
jnz conv
call getchr
conv: jmp conflp
getshparms:
mov byte ptr [di],0
mov di,offset command_line+1
parmloop:
call getchr
cmp al," "
jb endsh
mov [di],al
inc di
jmp parmloop
;------------------------------------------------------------------------
; fcbs command
;------------------------------------------------------------------------
;************************************************************************
; function: parse the parameters of fcbs= command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; set the variables fcbs,keep. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di points to fcbs_parms; *
; set dx,cx to 0; *
; while (end of command line) *
; { sysparse; *
; if (no error) then *
; { if (cx == 1) then /* first positional = fcbs */ *
; fcbs = result_val.$p_picked_val; *
; if (cx == 2) then /* second positional = keep */ *
; keep = result_val.$p_picked_val; *
; } *
; else /*error exit*/ *
; error exit; *
; }; *
; }; *
;************************************************************************
tryx:
cmp ah,'X'
jnz tryy
mov di,offset fcbs_parms
xor cx,cx
mov dx,cx
do98:
call sysinit_parse
jnc if98 ; parse error
call badparm_p ; and show messages and end the search loop.
jmp short sr98
if98:
cmp ax,$p_rc_eol ; end of line?
jz en98 ; then end the $endloop
mov al,byte ptr result_val.$p_picked_val
cmp cx,1 ; the first positional?
jnz if102
mov p_fcbs,al
jmp short en102
if102:
mov p_keep,al
en102:
jmp do98
en98:
mov al,p_fcbs ; M017
mov fcbs,al ; M017
mov keep,0 ; M017
sr98:
jmp coff
;-------------------------------------------------------------------------
; comment= do nothing. just decrese chrptr,and increase count for correct
; line number
;-------------------------------------------------------------------------
tryy:
cmp ah,'Y'
jne try0
donothing:
dec chrptr
inc count
jmp coff
;------------------------------------------------------------------------
; rem command
;------------------------------------------------------------------------
try0: ;do nothing with this line.
cmp ah,'0'
je donothing
;-----------------------------------------------------------------------
; switches command
;-----------------------------------------------------------------------
;****************************************************************************
; *
; function: parse the option switches specified. *
; note - this command is intended for the future use also. when we need to *
; to set system data flag,use this command. *
; *
; input : *
; es:si -> parameters in command line. *
; output: *
; p_swit_k set if /k option chosen. *
; *
; subroutines to be called: *
; sysinit_parse *
; logic: *
; { *
; set di points to swit_parms; /*parse control definition*/ *
; set dx,cx to 0; *
; while (end of command line) *
; { sysinit_parse; *
; if (no error) then *
; if (result_val.$p_synonym_ptr == swit_k) then *
; p_swit_k = 1 *
; endif *
; else {show error message;error exit} *
; }; *
; }; *
; *
;****************************************************************************
cmp ah,'1' ;switches= command entered?
je do_try1
jmp tryt
do_try1:
mov di,offset swit_parms
xor cx,cx
mov dx,cx
do110:
call sysinit_parse
jnc if110 ; parse error
call badparm_p ; and show messages and end the search loop.
jmp short sr110
if110:
cmp ax,$p_rc_eol ; end of line?
jz en110 ; then jmp to $endloop for semantic check
cmp result_val.$p_synonym_ptr,offset swit_k
jnz if115 ; ;M059
mov p_swit_k,1 ; set the flag
jmp do110
if115: ;M059
cmp result_val.$p_synonym_ptr, offset swit_t ;M059
jne if116 ;M059 M063
mov p_swit_t, 1 ;M059
jmp do110 ;M059
if116:
cmp result_val.$p_synonym_ptr, offset swit_w ;M063
jne do110 ;M063
mov p_swit_w, 1 ;M063
jmp do110 ;M063
en110:
cmp p_swit_k,1 ;if /k entered,
push ds
mov ax,Bios_Data
mov ds,ax
assume ds:Bios_Data
jnz if117
mov keyrd_func,0 ;use the conventional keyboard functions
mov keysts_func,1
if117:
; mov al, p_swit_t ;M059
; mov t_switch, al ;M059
cmp p_swit_w, 0 ;M063
je skip_dos_flag ;M063
push es
push bx
mov ah, GET_IN_VARS ;M063
int 21h ;M063
or byte ptr es:[DOS_FLAG_OFFSET], SUPPRESS_WINA20 ;M063
pop bx
pop es
skip_dos_flag: ;M063
pop ds
assume ds:sysinitseg
sr110:
jmp coff
;------------------------------------------------------------------------
; NTCMDPROMPT command. This command forces SCS functionality to use
; cmd.exe prompt rather than command.com's prompt on shelling out
; and on finding a TSR.
;------------------------------------------------------------------------
tryt:
cmp ah,'T'
je tryt_5
jmp short tryo
tryt_5:
push si
push bp
xor ax,ax
mov bp,ax
mov si,ax
mov al,4
mov ah,setdpb
int 21h
pop bp
pop si
jmp coff
;------------------------------------------------------------------------
; DOSONLY command. This command forces only DOS binaries to run from
; command.com prompt. non_dos binaries will putup the stub message
; of unable to run it under DOS.
;------------------------------------------------------------------------
tryo:
cmp ah,'O'
je tryo_5
jmp short tryz
tryo_5:
push si
push bp
xor ax,ax
mov bp,ax
mov si,ax
mov al,6
mov ah,setdpb
int 21h
pop bp
pop si
jmp coff
;------------------------------------------------------------------------
; bogus command
;------------------------------------------------------------------------
tryz:
cmp ah,0ffh
je tryff
dec chrptr
inc count
jmp short badop
;------------------------------------------------------------------------
; null command
;------------------------------------------------------------------------
tryff: ;skip this command.
jmp donothing
doconf endp
;------------------------------------------------------------------------------
sysinit_parse proc
;set up registers for sysparse
;in) es:si -> command line in confbot
; di -> offset of the parse control defintion.
;
;out) calls sysparse.
; carry will set if parse error.
; *** the caller should check the eol condition by looking at ax
; *** after each call.
; *** if no parameters are found,then ax will contain a error code.
; *** if the caller needs to look at the synomym@ of the result,
; *** the caller should use cs:@ instead of es:@.
; cx register should be set to 0 at the first time the caller calls this
; procedure.
; ax - exit code
; bl - terminated delimeter code
; cx - new positional ordinal
; si - set to pase scanned operand
; dx - selected result buffer
push es ;save es,ds
push ds
push es
pop ds ;now ds:si -> command line
push cs
pop es ;now es:di -> control definition
mov cs:badparm_seg,ds ;save the pointer to the parm
mov cs:badparm_off,si ; we are about to parse for badparm msg.
mov dx,0
call sysparse
cmp ax,$p_no_error ;no error
;**cas note: when zero true after cmp, carry clear
jz ll4
cmp ax,$p_rc_eol ;or the end of line?
jnz if4
ll4:
clc
jmp short en4
if4:
stc
en4:
pop ds
pop es
ret
sysinit_parse endp
;
;----------------------------------------------------------------------------
;
; procedure : badop_p
;
; same thing as badop,but will make sure to set ds register back
; to sysinitseg and return back to the caller.
;
;----------------------------------------------------------------------------
;
badop_p proc near
push cs
pop ds ;set ds to configsys seg.
mov dx,offset badopm
call print
call error_line
ret
badop_p endp
;
;----------------------------------------------------------------------------
;
; label : badop
;
;----------------------------------------------------------------------------
;
badop: mov dx,offset badopm ;want to print command error "unrecognized command..."
call print
call error_line ;show "error in config.sys ..." .
jmp coff
;
;----------------------------------------------------------------------------
;
; procedure : badparm_p
;
; show "bad command or parameters - xxxxxx"
; in badparm_seg,badparm_off -> xxxxx
;
;----------------------------------------------------------------------------
;
badparm_p proc near
push ds
push dx
push si
push cs
pop ds
mov dx,offset badparm
call print ;"bad command or parameters - "
lds si,badparm_ptr
; print "xxxx" until cr.
do1:
mov dl,byte ptr [si] ; get next character
cmp dl,cr ; is a carriage return?
jz en1 ; exit loop if so
mov ah,std_con_output ; function 2
int 21h ; display character
inc si ; next character
jmp do1
en1:
push cs
pop ds
mov dx,offset crlfm
call print
call error_line
pop si
pop dx
pop ds
badparmp_ret:
ret
badparm_p endp
;
;----------------------------------------------------------------------------
;
; procedure : getchr
;
;----------------------------------------------------------------------------
;
getchr proc near
push cx
mov cx,count
jcxz nochar
mov si,chrptr
mov al,es:[si]
dec count
inc chrptr
clc
get_ret:
pop cx
ret
nochar: stc
jmp short get_ret
getchr endp
;
;----------------------------------------------------------------------------
;
; procedure : incorrect_order
;
; show "incorrect order in config.sys ..." message.
;
;----------------------------------------------------------------------------
;
incorrect_order proc near
mov dx,offset badorder
call print
call showlinenum
ret
incorrect_order endp
;
;----------------------------------------------------------------------------
;
; procedure : error_line
;
; show "error in config.sys ..." message.
;
;----------------------------------------------------------------------------
;
public error_line
error_line proc near
push cs
pop ds
mov dx,offset errorcmd
call print
call showlinenum
ret
error_line endp
;
;----------------------------------------------------------------------------
;
; procedure : showlinenum
;
; convert the binary linecount to decimal ascii string in showcount
;and display showcount at the current curser position.
;in.) linecount
;
;out) the number is printed.
;
;----------------------------------------------------------------------------
;
showlinenum proc near
push es
push ds
push di
push cs
pop es ; es=cs
push cs
pop ds
mov di,offset showcount+4 ; di -> the least significant decimal field.
mov cx,10 ; decimal devide factor
mov ax,cs:linecount
sln_loop:
cmp ax,10 ; < 10?
jb sln_last
xor dx,dx
div cx
or dl,30h ; add "0" (= 30h) to make it an ascii.
mov [di],dl
dec di
jmp sln_loop
sln_last:
or al,30h
mov [di],al
mov dx,di
call print ; show it.
pop di
pop ds
pop es
ret
showlinenum endp
comment ^
set_devmark proc near
;***************************************************************************
; function: set a paragraph of informations infront of a device file or *
; an ifs file to be loaded for mem command. *
; the structure is: *
; devmark_id byte "d" for device,"i" for ifs *
; devmark_size size in para for the device loaded *
; devmark_filename 11 bytes. filename *
; *
; input : *
; [memhi] = address to set up devmark. *
; [memlo] = 0 *
; es:si -> pointer to [drive][path]filename,0 *
; [ifs_flag] = is_ifs bit set if ifs= command. *
; *
; output: devmark_id,devmark_filename set *
; cs:[devmark_addr] set. *
; ax,cx register destroyed. *
;***************************************************************************
push ds
push si
push es
push di
mov di,cs:[memhi]
mov ds,di
assume ds:nothing
mov [devmark_addr],di ; save the devmark address for the future.
mov ds:[devmark_id],devmark_device ; 'd'
inc di
mov ds:[devmark_seg],di
xor al,al
push si
pop di ; now es:si = es:di = [path]filename,0
mov cx,128 ; maximum 128 char
repnz scasb ; find 0
dec di ; now es:di-> 0
sdvmk_backward: ; find the pointer to the start of the filename.
mov al,byte ptr es:[di] ; we do this by check es:di backward until
cmp al,'\' ; di = si or di -> '\' or di -> ':'.
je sdvmk_gotfile
cmp al,':'
je sdvmk_gotfile
cmp di,si
je sdvmk_fileptr
dec di
jmp sdvmk_backward
sdvmk_gotfile:
inc di
sdvmk_fileptr: ; now es:di -> start of file name
push di ; cas - holy sh*t!!! CODE!
pop si ; save di to si.
push ds ; switch es,ds
push es
pop ds
pop es ; now,ds:si -> start of filename
mov di,devmark_filename
push di
mov al,' '
mov cx,8
rep stosb ; clean up memory.
pop di
mov cx,8 ; max 8 char. only
sdvmk_loop:
lodsb
cmp al,'.'
je sdvmk_done
cmp al,0
je sdvmk_done
stosb
loop sdvmk_loop
sdvmk_done:
pop di
pop es
pop si
pop ds
ret
set_devmark endp
^
; =========================================================================
;reset_dos_version proc near
;
;;function: issue ax=122fh,dx=0,int 2fh to restore the dos version.
;
; push ax
; push dx
; mov ax,122fh
; mov dx,0
; int 2fh
; pop dx
; pop ax
; ret
;reset_dos_version endp
;
;
; =========================================================================
IFDEF DONT_LOAD_OS2_DD ; M045
EXE_SIG EQU 5a4dh ; .EXE file signature
OS2_SIG EQU 454eh ; OS2 .EXE file signature
SIGNATURE_LEN EQU 2 ; Lenght of .EXE signature in bytes
SIZE_DWORD EQU 4
SEG_SIG_OFFSET EQU 18h ; Offset of segmented .EXE signature
SEG_EXE_SIG EQU 40h ; Signature of a segmented .EXE file
SEG_HEADER_PTR EQU 3ch ; Offsets of ptr to segmented header
; =========================================================================
; CheckForOS2 PROC
;
; Examines an open file to see if it is really an OS2 executable file.
;
; REGISTERS: AX - Open file handle
; RETURNS: Carry - Carry set if file is an OS2 executable or error.
; DESTROYS: NOTHING
; NOTE: The file ptr is assumed to be set to start of file
; on entry and is not reset to begining of the file
; on exit.
;
; Strategy: If word value at 00h == 454eh file is OS2
; else if word value at 00h == 5a4dh and
; (word value at 18h == 40h and the dword ptr at 3ch
; points to word value of 454eh) file is OS2.
;
; =========================================================================
CheckForOS2 PROC NEAR
push AX
push BX
push CX
push DX
push DS
push BP
push CS ; BUGBUG
pop DS ; NOT ROM DOS COMPATIBLE
mov BX,AX ; Put open file handle in BX
mov BP,offset DS:Os2ChkBuf ; Save buff offset for latter
; First we need to read in the first 2 bytes of the file
; to see if it's an OS2 .EXE file and if not see if
; it is a DOS .EXE file.
mov AX,(read shl 8) ; AH = DOS read function
mov CX,SIGNATURE_LEN ; CX = size of word value
mov DX,BP ; DS:DX --> tmp buffer
int 21h
jc OS2ChkExit ; Return carry on error
dec AX ; Check number of byte read
dec AX
jnz NotOs2 ; Must be at end of file
mov AX, WORD PTR DS:Os2ChkBuf
cmp AX, OS2_SIG ; Check for 454eh
je IsOS2 ; Return is OS2 if match
cmp AX, EXE_SIG ; Now see if it's a DOS .EXE
jne NotOS2 ; If no match can't be OS2
; Here we know the file has a valid DOS .EXE signature so
; now we need to see if it's a segmented .EXE file by looking
; for the segmented .EXE signature at file offset 18h
mov AX,(lseek shl 8) ; AX = Seek from begining
xor CX,CX
mov DX,SEG_SIG_OFFSET ; CX:DX = offset of segmented
int 21h ; Seek to offset 18h
jc OS2ChkExit ; Return carry on error
mov AX,read shl 8 ; AX = Read file
mov CX,SIGNATURE_LEN ; CX = size of word value
mov DX,BP ; Restore buffer offset
int 21h ; DS:DX -> buffer
jc OS2ChkExit ; Return carry on error
dec AX ; Check number of byte read
dec AX
jnz NotOs2 ; Must be at end of file
cmp WORD PTR DS:Os2ChkBuf,SEG_EXE_SIG ; Chk for segmented .EXE file
jne NotOS2 ; Can't be OS2 if no match
; Here we know we have a segmented .EXE file so we have
; to get the offset of the start of the segmented header
; from offset 3ch in the file.
mov AX,(lseek shl 8) ; AX = Seek from begining
xor CX,CX
mov DX,SEG_HEADER_PTR ; CX:DX = offset of head ptr
int 21h ; Seek to offset 3ch
jc OS2ChkExit ; Return carry on error
mov AX,(read shl 8) ; AX = Read file
mov CX,SIZE_DWORD ; CX = size of dword (4 bytes)
mov DX,BP ; Restore buffer offset
int 21h ; Read in 4 byte offset
jc OS2ChkExit ; Return carry on error
cmp AX,SIZE_DWORD ; Check number of byte read
jne NotOs2 ; Must be at end of file
; At this point OS2ChkBuf has a 4 byte offset into the file
; to the start of a segmented .EXE header so we need to read
; the 2 bytes at this location to see if they are 454eh
mov DX,WORD PTR DS:Os2ChkBuf
mov CX,WORD PTR DS:Os2ChkBuf[2] ; CX:DX = offset of new header
mov AX,(lseek shl 8) ; AX = Seek from begining
int 21h ; Seek to offset 3ch
jc OS2ChkExit ; Return carry on error
mov AX,(read shl 8) ; AX = Read file
mov CX,SIGNATURE_LEN ; CX = size of word (2 bytes)
mov DX,BP ; DS:DX --> Os2ChkBuf
int 21h ; Read in 4 byte offset
jc OS2ChkExit ; Return carry on error
dec AX ; Check number of byte read
dec AX
jnz NotOs2 ; Must be at end of file
; We have the segmented .EXE header in OS2ChkBuf so all
; we have left to do is see if it's a .EXE signature.
cmp WORD PTR DS:OS2ChkBuf,OS2_SIG ; Check for 454eh
jne NotOs2 ; Not OS2 if it doesn't match
IsOs2:
stc ; Signal error or OS2 .EXE
jmp SHORT OS2ChkExit
NotOs2:
clc ; Signal no err and not OS2
OS2ChkExit:
pop BP
pop DS
pop DX
pop CX
pop BX
pop AX
ret
CheckForOS2 ENDP
ENDIF ; M045
;
;----------------------------------------------------------------------------
;
; procedure : ProcDOS
;
; Process the result of DOS= parsing
;
; result_val.$p_item_tag = 1 for DOS=HIGH
; = 2 for DOS=LOW
; = 3 for DOS=UMB
; = 4 for DOS=NOUMB
;----------------------------------------------------------------------------
;
ProcDOS proc near
assume ds:nothing, es:nothing
xor ah, ah
mov al, result_val.$p_item_tag
dec ax
jz pd_hi
dec ax
jz pd_lo
dec ax
jz pd_umb
mov DevUMB, 0
ret
pd_umb:
mov DevUMB, 0ffh
ret
pd_lo:
mov runhigh, 0
ret
pd_hi:
mov runhigh, 0ffh
ret
ProcDOS endp
;
;----------------------------------------------------------------------------
;
; procedure : LieInt12Mem
;
; Input : DevEntry points to Device Start address (offset == 0)
; alloclim set to the limit of low memory.
;
; Output : none
;
; Changes the ROM BIOS variable which stores the total low memory
; If a 3com device driver (any character device with name 'PROTMAN$')
; is being loaded alloclim is converted into Ks and stored in 40:13h
; Else if a device driver being loaded into UMB the DevLoadEnd is
; converted into Ks and stored in 40:13h
;
;----------------------------------------------------------------------------
;
LieInt12Mem proc near
assume ds:nothing, es:nothing
mov ax, alloclim ; lie INT 12 as alloclim
; assuming that it is 3Com
call IsIt3Com? ; Is it 3Com driver?
je lim_set ; yes, lie to him differently
cmp DeviceHi, 0 ; Is the DD being loaded in UMB
je limx ; no, don't lie
mov ax, DevLoadEnd ; lie INT 12 as end of UMB
lim_set:
call SetInt12Mem
limx:
ret
LieInt12Mem endp
;
;----------------------------------------------------------------------------
;
; procedure : SetInt12Mem
;
; Input : AX = Memory size to be set (in paras)
; Output : none
;
; Sets the variable 40:13 to the memory size passed in AX
; It saves the old value in 40:13 in OldInt12Mem,
; It also sets a flag Int12Lied to 0ffh, which is checked before
; restoring the value of 40:13
;
;----------------------------------------------------------------------------
;
SetInt12Mem proc near
assume ds:nothing, es:nothing
push ds
mov bx, 40h
mov ds, bx ; ROM BIOS Data Segment
mov bx, word ptr ds:[13h] ; INT 12 memory variable
mov OldInt12Mem, bx ; save it
mov cl, 6
shr ax, cl ; convert paras into Ks
mov word ptr ds:[13h], ax ; Lie
mov Int12Lied, 0ffh ; mark that we are lying
pop ds
ret
SetInt12Mem endp
;
;----------------------------------------------------------------------------
;
; procedure : TrueInt12Mem
;
; Input : Int12Lied = 0 if we are not lying currently
; = 0ffh if we are lying
; OldInt12Mem = Saved value of 40:13h
;
; Output : none
;
; Resets the INT 12 Memory variable if we were lying about int 12
; and resets the flag which indicates that we were lying
;
;----------------------------------------------------------------------------
;
TrueInt12Mem proc near
assume ds:nothing, es:nothing
cmp Int12Lied, 0 ; were we lying so far?
mov Int12Lied, 0 ; reset it anyway
je timx ; no, we weren't
push ds
mov ax, 40h
mov ds, ax
mov ax, OldInt12Mem
mov word ptr ds:[13h], ax ; restore INT 12 memory
pop ds
timx:
ret
TrueInt12Mem endp
;
;----------------------------------------------------------------------------
;
; procedure : IsIt3Com?
;
; Input : DevEntry = Seg:0 of device driver
; Output : Zero flag set if device name is 'PROTMAN$'
; else Zero flag is reset
;
;----------------------------------------------------------------------------
;
IsIt3Com? proc near
assume ds:nothing, es:nothing, ss:nothing
push ds
push es
push si
lds si, DevEntry ; ptr to device header
add si, sdevname ; ptr device name
push cs
pop es
mov di, offset ThreeComName
mov cx, 8 ; name length
rep cmpsb
pop si
pop es
pop ds
ret
IsIt3Com? endp
;M020 : BEGIN
;
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
UpdatePDB proc near
assume ds:nothing
push ds
mov ah, 62h
int 21h
mov ds, bx
mov bx, alloclim
mov ds:[PDB_Block_Len], bx
pop ds
ret
UpdatePDB endp
;
; M020 : END
;
;----------------------------------------------------------------------------
;
; procedure : InitDevLoad
;
; Input : DeviceHi = 0 indicates load DD in low memory
; = 1 indicates load in UMB
; DevSize = Size of the device driver file in paras
;
; Output : none
;
; Initializes DevLoadAddr, DevLoadEnd & DevEntry.
; Also sets up a header for the Device driver entry for mem utility
;
;----------------------------------------------------------------------------
;
InitDevLoad proc near
assume ds:nothing, es:nothing
cmp DeviceHi, 0 ; Are we loading in UMB
je InitForLo ; no, init for lo mem
call SpaceInUMB? ; Do we have space left in the
; current UMB ?
jnc InitForHi ; yes, we have
call ShrinkUMB ; shrink the current UMB in use
call GetUMBForDev ; else try to allocate new UMB
jc InitForLo ; we didn't succeed, so load
; in low memory
InitForHi:
mov ax, DevUMBFree ; get Para addr of free mem
mov dx, DevUMBAddr ; UMB start addr
add dx, DevUMBSize ; DX = UMB End addr
jmp short idl1
InitForLo:
mov DeviceHi, 0 ; in case we failed to load
; into UMB indicate that we
; are loading low
mov ax, memhi ; AX = start of Low memory
mov dx, alloclim ; DX = End of Low memory
idl1:
call DevSetMark ; setup a sub-arena for DD
mov DevLoadAddr, ax ; init the Device load address
mov DevLoadEnd, dx ; init the limit of the block
mov word ptr DevEntry, 0 ; init Entry point to DD
mov word ptr DevEntry+2, ax
ret
InitDevLoad endp
;------------------------------------------------------------------
; NTVDM 08-Dec-1992 Jonle
;
; AllocUMBLow- Allocates a chunk from memory from UMB area
; or from low memory area in case UMB memory
; is unavailable.
;
; The arena is marked as
;
; Input: es:di addr of arena name to copy
; cx size to allocate
;
; Output: es:di points to memory allocated
;
;------------------------------------------------------------------
AllocUMBLow proc near
assume ds:nothing, es:nothing
mov ax, cx ; convert size to paras
add ax, 18 ; extra for dummy dev header for mem.exe
call pararound
mov DevSize, ax
mov word ptr [bpb_addr], di ; fake cmd line for dev name
mov word ptr [bpb_addr+2], es
mov al, DevUMB ; we want UMB
mov DeviceHi, al
call InitDevLoad
mov ax, word ptr DevEntry+2 ; mark arena for mem.exe
dec ax
mov es, ax
mov byte ptr es:[devmark_id], devmark_spc
inc ax ; mark final size
add ax, DevSize
mov word ptr DevBrkAddr+2,ax
mov word ptr DevBrkAddr, 0
call DevBreak
mov di, word ptr DevEntry ; es:di -> deventry
mov ax, word ptr DevEntry+2
mov es, ax
AllocUMBLow endp
;
;----------------------------------------------------------------------------
;
; procedure : SpaceInUMB?
;
; Input : DevUMBAddr, DevUMBSize, DevUMBFree & DevSize
; Output : Carry set if no space in UMB
; Carry clear if Space is available for the device in
; current UMB
;
;----------------------------------------------------------------------------
;
SpaceInUMB? proc near
assume ds:nothing, es:nothing
mov ax, DevUMBSize
add ax, DevUMBAddr ; End of UMB
sub ax, DevUMBFree ; - Free = Remaining space
or ax, ax ; Nospace ?
jnz @f
stc
ret
@@:
dec ax ; space for sub-arena
cmp ax, DevSize ; do we have space ?
ret
SpaceInUMB? endp
;
;----------------------------------------------------------------------------
;
; procedure : GetUMBForDev
;
; Input : DevSize
; Output : Carry set if couldn't allocate a UMB to fit the
; the device.
; If success carry clear
;
; Allocates the biggest UMB for loading devices and updates
; DevUMBSize, DevUMBAddr & DevUMBFree if it succeeded in allocating
; UMB.
;
; This routine relies on the fact that all of the low memory
; is allocated, and any DOS alloc calls should return memory
; from the UMB pool.
;
;----------------------------------------------------------------------------
;
GetUMBForDev proc near
assume ds:nothing, es:nothing
if 0
;;
mov bx, 0ffffh
mov ax, 4800h
int 21h
or bx, bx
jz gufd_err
dec bx
cmp DevSize, bx
ja gufd_err
inc bx
mov ax, 4800h
int 21h
jc gufd_err
push ds
dec ax
mov ds, ax
mov word ptr ds:[arena_owner], 8
mov word ptr ds:[arena_name], 'DS'
inc ax
pop ds
mov DevUMBSize, bx ; update the UMB Variables
mov DevUMBAddr, ax
mov DevUMBFree, ax
clc ; mark no error
ret
gufd_err:
xor ax, ax
mov DevUMBSize, ax ; erase the previous values
mov DevUMBAddr, ax
mov DevUMBFree, ax
stc
ret
else
;; we changed the allocation strategy to best-fit for NT. This is because
;; we want to reserve bigger blocks for loadhigh command. In most case,
;; device drivers are smaller than TSR(ran from loadhigh). This change give
;; us a better chance to load the big tsr like DOSX.EXE to UMB and
;; give applications more free conventional memory.
;; The following implementation seems slow because every time we need an
;; UMB, we go through the chain. This is done because each request has
;; different size - We can grab all UMBs from the very beginning and put
;; them in a list, but we have to maintain the list. -williamh
push cx
push dx
push es
xor cx, cx ;; allocated count = 0
mov dx, DevSize
inc dx ;; minimum size in paras
;; bios needs its sub-arena
search_for_best_block:
mov bx, 0ffffh ;; get largest block size
mov ah, 48h ;; so far
int 21h
cmp bx, dx ;; will this satisfy ours?
jb allocate_the_block ;; no, break
mov ah, 48h ;; allocate this block
int 21h
jc allocate_the_block ;; failed, use the previous one
inc cx ;; we have one more allocated
push bx ;; save the size
push ax ;; save the address
jmp short search_for_best_block
allocate_the_block:
;; the block saved on the top of the stack is the best fit one
;; grab it if there is one
jcxz gufd_err ;; no block found, error
pop ax ;; get the address
pop DevUMBSize ;; and size
mov DevUMBAddr, ax
mov DevUMBFree, ax
dec ax
push ds
mov ds, ax
mov word ptr ds:[arena_owner], 8
mov word ptr ds:[arena_name], 'DS'
pop ds
dec cx
;; now free those unnecessary blocks
jcxz allocate_done
free_allocated_blocks:
pop es ;; get the address
add sp, 2 ;; discard the size
mov ah, 49h ;; free it
int 21h
loop free_allocated_blocks
allocate_done:
clc ; mark no error
jmp short GetUMBForDevExit
gufd_err:
xor ax, ax
mov DevUMBSize, ax ; erase the previous values
mov DevUMBAddr, ax
mov DevUMBFree, ax
stc
GetUMBForDevExit:
pop es
pop dx
pop cx
ret
endif
GetUMBForDev endp
;
;----------------------------------------------------------------------------
;
; procedure : DevSetMark
;
; Input : AX - Free segment were device is going to be loaded
; Output : AX - Segment at which device can be loaded (AX=AX+1)
;
; Creates a sub-arena for the device driver
; puts 'D' marker in the sub-arena
; Put the owner of the sub-arena as (AX+1)
; Copies the file name into sub-arena name field
;
; Size field of the sub-arena will be set only at succesful
; completion of Device load.
;
;----------------------------------------------------------------------------
;
DevSetMark proc near
assume ds:nothing, es:nothing
push es
push di
push ds
push si
mov es, ax
mov byte ptr es:[devmark_id], devmark_device ; 'D'
inc ax
mov word ptr es:[devmark_seg], ax
;
;-------------- Copy file name
;
push ax ; save load addr
lds si, bpb_addr ; command line is still there
;M004 - BEGIN
mov di, si
cld
dsm_again:
lodsb
cmp al, ':'
jne isit_slash
mov di, si
jmp dsm_again
isit_slash:
cmp al, '\'
jne isit_null
mov di, si
jmp dsm_again
isit_null:
ifdef DBCS
call testkanj
jz @f ; if this is not lead byte
lodsb ; get tail byte
@@:
endif
or al, al
jnz dsm_again
mov si, di
;M004 - END
mov di, devmark_filename
mov cx, 8 ; maximum 8 characters
dsm_next_char:
lodsb
or al, al
jz blankout
cmp al, '.'
jz blankout
stosb
loop dsm_next_char
blankout:
jcxz dsm_exit
mov al, ' '
rep stosb ; blank out the rest
dsm_exit:
pop ax ; restore load addr
pop si
pop ds
pop di
pop es
ret
DevSetMark endp
;
;----------------------------------------------------------------------------
;
; procedure : SizeDevice
;
; Input : ES:SI - points to device file to be sized
;
; Output : Carry set if file cannot be opened or if it is an OS2EXE file
;
; Calculates the size of the device file in paras and stores it
; in DevSize
;
;----------------------------------------------------------------------------
;
SizeDevice proc near
assume ds:nothing, es:nothing
push es
pop ds
mov dx, si ; ds:dx -> file name
mov ax, 3d00h ; open
int 21h
jc sd_err ; open failed
IFDEF DONT_LOAD_OS2_DD ; M045
call CheckForOS2 ; is it a OS2 EXE file ?
jc sd_close ; yeah, we dont load them
ENDIF ; M045
mov bx, ax ; BX - file handle
mov ax, 4202h ; seek
xor cx, cx
mov dx, cx ; to end of file
int 21h
jc sd_close ; did seek fail (impossible)
add ax, 15 ; para convert
adc dx, 0
test dx, 0fff0h ; size > 0ffff paras ?
jz @f ; no
mov DevSize, 0ffffh ; invalid device size
; assuming that we fail later
jmp short sd_close
@@:
mov cl, 4 ; conver it to paras
shr ax, cl
mov cl, 12
shl dx, cl
or ax, dx ;
cmp ax, DevSizeOption
ja @f
mov ax, DevSizeOption
@@:
mov DevSize, ax ; save file size
clc
sd_close:
pushf ; let close not spoil our
; carry flag
mov ax, 3e00h ; close
int 21h ; we are not checking for err
popf
sd_err:
ret
SizeDevice endp
;
;----------------------------------------------------------------------------
;
; procedure : ExecDev
;
; Input : ds:dx -> device to be executed
; DevLoadAddr - contains where device has to be loaded
;
; Output : Carry if error
; Carry clear if no error
;
; Loads a device driver using the 4b03h function call
;
;----------------------------------------------------------------------------
;
ExecDev proc near
assume ds:nothing, es:nothing
mov bx, DevLoadAddr
mov DevExecAddr, bx ; Load the parameter block
; block for exec with
; Load address
mov DevExecReloc, bx
mov bx,cs
mov es,bx
mov bx,offset DevExecAddr ;es:bx points to parameters
mov al,3
mov ah,exec
int 21h ;load in the device driver
ret
ExecDev endp
;
;----------------------------------------------------------------------------
;
; procedure : RemoveNull
;
; Input : ES:SI points to a null terminated string
;
; Output : none
;
; Replaces the null at the end of a string with blank
;
;----------------------------------------------------------------------------
;
RemoveNull proc near
assume ds:nothing, es:nothing
rn_next:
mov bl, es:[si]
or bl, bl ; null ?
jz rn_gotnull
inc si ; advance the pointer
jmp rn_next
rn_gotnull:
mov bl, DevSavedDelim
mov byte ptr es:[si], bl ; replace null with blank
ret
RemoveNull endp
;
;----------------------------------------------------------------------------
;
; procedure : RoundBreakAddr
;
; Input : DevBrkAddr
; Output : DevBrkAddr
;
; Rounds DevBrkAddr to a para address so that it is of the form xxxx:0
;
;----------------------------------------------------------------------------
;
RoundBreakAddr proc near
assume ds:nothing, es:nothing
mov ax, word ptr DevBrkAddr
call pararound
add word ptr DevBrkAddr+2, ax
mov word ptr DevBrkAddr, 0
mov ax, DevLoadEnd
cmp word ptr DevBrkAddr+2, ax
jbe rba_ok
jmp mem_err
rba_ok:
ret
RoundBreakAddr endp
;
;----------------------------------------------------------------------------
;
; procedure : DevSetBreak
;
; Input : DevBrkAddr
; Output : Carry set if Device returned Init failed
; Else carry clear
;
;----------------------------------------------------------------------------
;
DevSetBreak proc near
assume ds:nothing, es:nothing
push ax
mov ax,word ptr [DevBrkAddr+2] ;remove the init code
cmp multdeviceflag, 0
jne set_break_continue ;do not check it.
cmp ax, DevLoadAddr
jne set_break_continue ;if not same, then o.k.
cmp word ptr [DevBrkAddr],0
je break_failed ;[DevBrkAddr+2]=[memhi] & [DevBrkAddr]=0
set_break_continue:
call RoundBreakAddr
pop ax
clc
ret
break_failed:
pop ax
stc
ret
DevSetBreak endp
;
;----------------------------------------------------------------------------
;
; procedure : DevBreak
;
; Input : DevLoadAddr & DevBrkAddr
; Output : none
;
; Marks a succesful install of a device driver
; Sets device size field in sub-arena &
; Updates Free ptr in UMB or adjusts memhi
;
;----------------------------------------------------------------------------
;
DevBreak proc near
assume ds:nothing, es:nothing
push ds
mov ax, DevLoadAddr
mov bx, word ptr [DevBrkAddr+2]
dec ax ; seg of sub-arena
mov ds, ax
inc ax ; Back to Device segment
sub ax, bx
neg ax ; size of device in paras
mov ds:[devmark_size], ax ; store it in sub-arena
cmp DeviceHi, 0
je db_lo
mov DevUMBFree, bx ; update Free ptr in UMB
jmp short db_exit
db_lo:
mov memhi, bx
mov memlo, 0
db_exit:
pop ds
ret
DevBreak endp
;
;----------------------------------------------------------------------------
;
; procedure : ParseSize
;
; Parses the command line for SIZE= command
;
; ES:SI = command line to parsed
;
; returns ptr to command line after SIZE= option in ES:SI
; updates the DevSizeOption variable with value supplied
; in SIZE=option
; Returns carry if the SIZE option was invalid
;
;----------------------------------------------------------------------------
;
ParseSize proc near
assume ds:nothing, es:nothing
mov DevSizeOption, 0 ; init the value
mov word ptr DevCmdLine, si
mov word ptr DevCmdLine+2, es
call SkipDelim
cmp word ptr es:[si], 'IS'
jne ps_no_size
cmp word ptr es:[si+2], 'EZ'
jne ps_no_size
mov al, es:[si+4]
call delim
jne ps_no_size
add si, 5
call GetHexNum
jc ps_err
mov DevSizeOption, ax
call SkipDelim
ps_no_size:
clc
ret
ps_err:
stc
ret
ParseSize endp
;
;----------------------------------------------------------------------------
;
; procedure : SkipDelim
;
; Skips delimiters in the string pointed to by ES:SI
; Returns ptr to first non-delimiter character in ES:SI
;
;----------------------------------------------------------------------------
;
SkipDelim proc near
assume ds:nothing, es:nothing
sd_next_char:
mov al, es:[si]
call delim
jnz sd_ret
inc si
jmp sd_next_char
sd_ret:
ret
SkipDelim endp
;
;----------------------------------------------------------------------------
;
; procedure : GetHexNum
;
; Converts an ascii string terminated by a delimiter into binary.
; Assumes that the ES:SI points to a Hexadecimal string
;
; Returns in AX the number number of paras equivalent to the
; hex number of bytes specified by the hexadecimal string.
;
; Returns carry in case it encountered a non-hex character or
; if it encountered crlf
;
;----------------------------------------------------------------------------
;
GetHexNum proc near
assume ds:nothing, es:nothing
xor ax, ax
xor dx, dx
ghn_next:
mov bl, es:[si]
cmp bl, cr
je ghn_err
cmp bl, lf
je ghn_err
push ax
mov al, bl
call Delim
pop ax
jz ghn_into_paras
call GetNibble
jc ghn_err
mov cx, 4
ghn_shift1:
shl ax, 1
rcl dx, 1
loop ghn_shift1
or al, bl
inc si
jmp ghn_next
ghn_into_paras:
add ax, 15
adc dx, 0
test dx, 0fff0h
jnz ghn_err
mov cx, 4
ghn_shift2:
clc
rcr dx, 1
rcr ax, 1
loop ghn_shift2
clc
ret
ghn_err:
stc
ret
GetHexNum endp
;
;----------------------------------------------------------------------------
;
; procedure : GetNibble
;
; Convert one nibble (hex digit) in BL into binary
;
; Retruns binary value in BL
;
; Returns carry if BL contains non-hex digit
;
;----------------------------------------------------------------------------
;
GetNibble proc near
cmp bl, '0'
jb gnib_err
cmp bl, '9'
ja is_it_hex
sub bl, '0' ; clc
ret
is_it_hex:
cmp bl, 'A'
jb gnib_err
cmp bl, 'F'
ja gnib_err
sub bl, 'A'- 10 ; clc
ret
gnib_err:
stc
ret
GetNibble endp
;
;
;============================================================================
;============================================================================
;
;----------------------------------------------------------------------------
;
; procedure : AllocUMB
;
; Allocate all UMBs and link it to DOS arena chain
;
;----------------------------------------------------------------------------
;
AllocUMB proc near
call InitAllocUMB ; link in the first UMB
jc au_exit ; quit on error
au_next:
call umb_allocate ; allocate
jc au_coalesce
call umb_insert ; & insert till no UMBs
jmp short au_next
au_coalesce:
call umb_coalesce ; coalesce all UMBs
au_exit:
ret
AllocUMB endp
;
;----------------------------------------------------------------------------
;
; procedure : InitAllocUMB
;
;----------------------------------------------------------------------------
;
InitAllocUMB proc near
call IsXMSLoaded
jnz iau_err ; quit on no XMS driver
mov ah, 52h
int 21h ; get DOS DATA seg
mov DevDOSData, es ; & save it for later
mov ax, 4310h
int 2fh
mov word ptr DevXMSAddr, bx ; get XMS driver address
mov word ptr DevXMSAddr+2, es
cmp FirstUMBLinked, 0 ; have we already linked a UMB?
jne @f ; quit if we already did it
call LinkFirstUMB ; else link the first UMB
jc iau_err
mov FirstUMBLinked, 0ffh ; mark that 1st UMB linked
@@:
clc
ret
iau_err:
stc
ret
InitAllocUMB endp
;-------------------------------------------------------------------------
;
; Procedure Name : umb_allocate
;
; Inputs : DS = data
;
; Outputs : if UMB available
; Allocates the largest available UMB and
; BX = segment of allocated block
; DX = size of allocated block
; NC
; else
; CY
;
; Uses : BX, DX
;
;-------------------------------------------------------------------------
umb_allocate proc near
push ax
mov ah, XMM_REQUEST_UMB
mov dx, 0ffffh ; try to allocate largest
; possible
call dword ptr DevXMSAddr
; dx now contains the size of
; the largest UMB
or dx, dx
jz ua_err
mov ah, XMM_REQUEST_UMB
call dword ptr DevXMSAddr
cmp ax, 1 ; Q: was the reqst successful
jne ua_err ; N: error
clc
ua_done:
pop ax
ret
ua_err:
stc
jmp short ua_done
umb_allocate endp
;---------------------------------------------------------------------------
;
; Procedure Name : umb_insert
;
; Inputs : DOSDATA:UMB_HEAD = start of umb chain
; : BX = seg address of UMB to be linked in
; : DX = size of UMB to be linked in paras
; ; DS = data
;
; Outputs : links the UMB into the arena chain
;
; Uses : AX, CX, ES, DX, BX
;
;---------------------------------------------------------------------------
umb_insert proc near
push ds
mov ds, [DevDOSData]
mov ds, ds:[UMB_ARENA] ; es = UMB_HEAD
mov ax, ds
mov es, ax
ui_next:
cmp ax, bx ; Q: is current block above
; new block
ja ui_insert ; Y: insert it
; Q: is current block the
; last
cmp es:[arena_signature], arena_signature_end
jz ui_append ; Y: append new block to chain
; N: get next block
mov ds, ax ; M005
call get_next ; ax = es = next block
jmp short ui_next
ui_insert:
mov cx, ds ; ds = previous arena
inc cx ; top of previous block
sub cx, bx
neg cx ; cx = size of used block
mov ds:[arena_signature], arena_signature_normal
mov ds:[arena_owner], 8 ; mark as system owned
mov ds:[arena_size], cx
mov word ptr ds:[arena_name], 'CS'
; prepare the arena at start of new block
mov es, bx
mov es:[arena_signature], arena_signature_normal
mov es:[arena_owner], arena_owner_system
; mark as free
sub dx, 2 ; make room for arena at
; start & end of new block
mov es:[arena_size], dx
; prepare arena at end of new block
add bx, dx
inc bx
mov es, bx ; es=arena at top of new block
inc bx ; bx=top of new block
; ax contains arena just above
; this block
sub ax, bx ; ax = size of used block
mov es:[arena_signature], arena_signature_normal
mov es:[arena_owner], 8 ; mark as system owned
mov es:[arena_size], ax
mov word ptr es:[arena_name], 'CS'
jmp short ui_done
ui_append:
; es = arena of last block
add ax, es:[arena_size] ; ax=top of last block-1 para
sub es:[arena_size], 1 ; reflect the space we are
; going to rsrv on top of this
; block for the next arena.
mov es:[arena_signature], arena_signature_normal
mov cx, ax ; cx=top of prev block-1
inc ax
sub ax, bx ; ax=top of prev block -
; seg. address of new block
neg ax
mov es, cx ; ds = arena of unused block
mov es:[arena_signature], arena_signature_normal
mov es:[arena_owner], 8 ; mark as system owned
mov es:[arena_size], ax
mov word ptr es:[arena_name], 'CS'
; prepare the arena at start of new block
mov es, bx
mov es:[arena_signature], arena_signature_end
mov es:[arena_owner], arena_owner_system
; mark as free
dec dx ; make room for arena
mov es:[arena_size], dx
ui_done:
pop ds
ret
umb_insert endp
;
;----------------------------------------------------------------------------
;
;** umb_coalesce - Combine free blocks ahead with current block
;
; Coalesce adds the block following the argument to the argument block,
; iff it's free. Coalesce is usually used to join free blocks, but
; some callers (such as $setblock) use it to join a free block to it's
; preceeding allocated block.
;
; EXIT 'C' clear if OK
; (ds) unchanged, this block updated
; (ax) = address of next block, IFF not at end
; 'C' set if arena trashed
; USES cx, di, ds, es
;
;----------------------------------------------------------------------------
;
umb_coalesce proc near
xor di, di
mov es, [DevDOSData]
mov es, es:[UMB_ARENA] ; es = UMB_HEAD
uc_nextfree:
mov ax, es
mov ds, ax
cmp es:[arena_owner], di ; Q: is current arena free
jz uc_again ; Y: try to coalesce with next block
; N: get next arena
call get_next ; es, ax = next arena
jc uc_done
jmp short uc_nextfree
uc_again:
call get_next ; ES, AX <- next block
jc uc_done
uc_check:
cmp es:[arena_owner],di ; Q: is arena free
jnz uc_nextfree ; N: get next free arena
; Y: coalesce
mov cx,es:[arena_size] ; cx <- next block size
inc cx ; cx <- cx + 1 (for header size)
add ds:[arena_size],cx ; current size <- current size + cx
mov cl,es:[di] ; move up signature
mov ds:[di],cl
jmp short uc_again ; try again
uc_done:
ret
umb_coalesce endp
;
;----------------------------------------------------------------------------
;
;** get_next - Find Next item in Arena
;
; ENTRY dS - pointer to block head
; EXIT AX,ES - pointers to next head
; 'C' set iff arena damaged
;
;----------------------------------------------------------------------------
;
get_next proc near
cmp byte ptr ds:[0], arena_signature_end
je gn_err
mov ax,ds ; ax=current block
add ax,ds:[arena_size] ; ax=ax + current block length
inc ax ; remember that header!
mov es, ax
clc
ret
gn_err:
stc
ret
get_next endp
;
;----------------------------------------------------------------------------
;
; procedure : LinkFirstUMB
;
;----------------------------------------------------------------------------
;
LinkFirstUMB proc near
call umb_allocate
jc lfu_err
; bx = segment of allocated UMB
; dx = size of UMB
int 12h ; ax = size of memory
mov cl, 6
shl ax, cl ; ax = size in paragraphs
mov cx, ax ; cx = size in paras
sub ax, bx ; ax = - size of unused block
neg ax
sub cx, 1 ; cx = first umb_arena
mov es, cx ; es = first umb_arena
mov es:[arena_signature], arena_signature_normal
mov es:[arena_owner], 8 ; mark as system owned
mov es:[arena_size], ax
mov word ptr es:[arena_name], 'CS'
; put in the arena for the first UMB
mov es, bx ; es has first free umb seg
mov es:[arena_signature], arena_signature_end
mov es:[arena_owner], arena_owner_system
; mark as free
dec dx ; make room for arena
mov es:[arena_size], dx
mov es, [DevDOSData]
mov di, UMB_ARENA
mov es:[di], cx ; initialize umb_head in DOS
; data segment with the arena
; just below Top of Mem
; we must now scan the arena chain and update the size of the last
; arena
mov di, DOS_ARENA
mov es, word ptr es:[di] ; es = start arena
xor di, di
scan_next:
cmp byte ptr es:[di], arena_signature_end
jz got_last
mov ax, es
add ax, es:[arena_size]
inc ax
mov es, ax
jmp short scan_next
got_last:
;; -williamh- we reserved the last paragraph for UMB_HEAD already.
;; refer to sysinit1.asm!goinit
;; The following instruction was commentted out for this reason.
;; sub es:[arena_size], 1
;;
mov es:[arena_signature], arena_signature_normal
clc
ret
lfu_err:
stc
ret
LinkFirstUMB endp
;
;----------------------------------------------------------------------------
;
; procedure : ShrinkUMB
;
; Shrinks the current UMB in use, so that the unused portions
; of the UMB is given back to the DOS free mem pool
;
;----------------------------------------------------------------------------
;
public ShrinkUMB
ShrinkUMB proc near
cmp DevUMBAddr, 0
je su_exit
push es
push bx
mov bx, DevUMBFree
sub bx, DevUMBAddr
mov es, DevUMBAddr
mov ax, 4a00h
int 21h
mov ax, es
dec ax
mov es, ax
mov word ptr es:[arena_owner], 8
pop bx
pop es
su_exit:
ret
ShrinkUMB endp
;M002 - BEGIN
;
;----------------------------------------------------------------------------
;
; procedure : UnlinkUMB
;
; Unlinks the UMBs from the DOS arena chain
;
;----------------------------------------------------------------------------
;
public UnlinkUMB
UnlinkUMB proc near
push ds
push es
cmp FirstUMBLinked, 0
je ulu_x ; nothing to unlink
mov es, DevDOSData ; get DOS data seg
mov ds, es:[DOS_ARENA]
mov di, es:[UMB_ARENA]
ulu_next:
call get_next
jc ulu_x
cmp di, ax ; is the next one UMB ?
je ulu_found
mov ds, ax
jmp ulu_next
ulu_found:
mov ds:[arena_signature], 'Z'
ulu_x:
pop es
pop ds
ret
UnlinkUMB endp
;M002 - END
; =========================================================================
;
sysinitseg ends
end