|
|
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 ifdef NEC_98 include dpb.inc endif ;NEC_98 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
ifndef NEC_98 stacksw equ true ;include switchable hardware stacks else ;NEC_98 stacksw equ false ;include switchable hardware stacks endif ;NEC_98
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 ifndef NEC_98 extrn parseline:near else ;NEC_98 extrn deviceparameters:byte extrn diddleback:near,parseline:near,setparms:near endif ;NEC_98 extrn badload:near,calldev:near,prnerr:near
extrn runhigh:byte extrn IsXMSLoaded:near
extrn TryToMovDOSHi:near
ifdef DBCS extrn testkanj:near endif
ifdef JAPAN extrn badblock2:byte,badsiz_pre2:byte,badcountry2:byte,insufmemory2:byte extrn badcountry2:byte,badcountrycom2:byte,badstack2:byte,badopm2:byte extrn badparm2:byte,badorder2:byte,errorcmd2:byte 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
ifdef NEC_98 DOS_FLAG_OFFSET equ 86h endif ;NEC_98 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 ifndef NEC_98 buf_range_1 p_range <,,,1,99> ; M050 else ;NEC_98 ;<patch BIOS50-P18> buf_range_1 p_range <,,,1,62> ; M050 endif ;NEC_98 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 ifndef NEC_98 DevSavedDelim db ? ; The delimiter which was replaced with null else ;NEC_98 DevSavedDelim db 00h ; The delimiter which was replaced with null endif ;NEC_98 ; 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 @@: ifndef NEC_98 mov DevSavedDelim, al ; Save the delimiter before replacing ; it with null else ;NEC_98 db 4 dup (90h) ; 4 bytes of NOPs endif ;NEC_98 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 ifndef NEC_98 mov DevSavedDelim, ' ' ; In case of DEVICE= the null has to ; be replaced with a ' ' else ;NEC_98 mov DevSavedDelim, 00h endif ;NEC_98
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
ifndef NEC_98 mov ax, NOSUPPORT_DRIVER BOP BOP_NOSUPPORT jmp short erase_dev_do endif ;NEC_98
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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badsiz_pre2 @@: endif 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 ifndef NEC_98 ifdef JAPAN pushf call IsDBCSCodePage jz @f mov dx,offset badcountry2 @@: popf endif else ;NEC_98 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badsiz_pre2 @@: endif endif ;NEC_98 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 ifdef JAPAN pushf call IsDBCSCodePage jz @f mov dx,offset insufmemory2 @@: popf endif 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" ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badcountry2 @@: endif jmp short en64
if64: mov dx,offset badcountrycom ;"error in contry command" ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badcountrycom2 @@: endif 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
; sudeepb - 27-Feb-1997 ; if a bad value is found, set it to DOS default i.e. 20. If its WOW VDM ; the BOP will return the right value. mov p_files,20
; call badparm_p ; and show messages and end the search loop. jmp short en67
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: ifndef NEC_98 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" ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badstack2 @@: endif 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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badstack2 @@: endif 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 else ;NEC_98 if stacksw
cmp ah,'K' je do_tryk jmp trys
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" ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badstack2 @@: endif 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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badstack2 @@: endif 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 endif ;NEC_98
;------------------------------------------------------------------------ ; 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: ifndef NEC_98 ; mov al, p_swit_t ;M059 else ;NEC_98 mov al, p_swit_t ;M059 endif ;NEC_98 ; 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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badopm2 @@: endif call print call error_line ret
badop_p endp ; ;---------------------------------------------------------------------------- ; ; label : badop ; ;---------------------------------------------------------------------------- ; badop: mov dx,offset badopm ;want to print command error "unrecognized command..." ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badopm2 @@: endif 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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badparm2 @@: endif 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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset badorder2 @@: endif 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 ifdef JAPAN call IsDBCSCodePage jz @f mov dx,offset errorcmd2 @@: endif 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 ifndef NEC_98 jc lfu_err else ;NEC_98 jnc lfu_next jmp lfu_err lfu_next: endif ;NEC_98
; bx = segment of allocated UMB ; dx = size of UMB
ifndef NEC_98 int 12h ; ax = size of memory else ;NEC_98 xor cx,cx mov es,cx mov al,byte ptr es:[501h] ; BIOS_FLG and ax,07h ; main memory size inc ax mov cl,7 shl ax,cl ; ax= size of memory
test byte ptr es:[501h],08h ; hireso? jz got_mm ; no cmp ax,768 jb got_mm sub ax,64 got_mm: endif ;NEC_98 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 ;; ifdef NEC_98 sub es:[arena_size], 1 endif ;NEC_98 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
; ========================================================================= ;
ifdef JAPAN public IsDBCSCodePage IsDBCSCodePage proc near push ax push bx mov ax,4f01h ; get code page xor bx,bx int 2fh cmp bx,932 pop bx pop ax ret IsDBCSCodePage endp endif
sysinitseg ends end
|