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

1610 lines
32 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
; the following depends on the positions of the various letters in switchlist
switchnum equ 11111000b ; which switches require number
include syscall.inc
include doscntry.inc
include devsym.inc
include ioctl.inc
include devmark.inc ; needed
stacksw equ true ;include switchable hardware stacks
if ibmjapver
noexec equ true
else
noexec equ false
endif
sysinitseg segment public
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 dosinfo:dword
extrn memory_size:word,fcbs:byte,keep:byte
extrn default_drive:byte,confbot:word,alloclim:word
extrn buffers:word,zero:byte,sepchr:byte
extrn files:byte
extrn count:word,chrptr:word
extrn bufptr:byte,memlo:word,prmblk:byte,memhi:word
extrn ldoff:word,area:word,packet:byte,unitcount:byte,
extrn break_addr:dword,bpb_addr:dword,drivenumber:byte
extrn com_level:byte, cmmt:byte, cmmt1:byte, cmmt2:byte
extrn cmd_indicator:byte
extrn donotshownum:byte
extrn multdeviceflag:byte
extrn devmark_addr:word
extrn setdevmarkflag:byte
extrn org_count:word
extrn pararound:near
extrn getchr:near
extrn stall:near
extrn error_line:near
extrn DevEntry:dword
insert_blank db 0 ; M051: indicates that blank has been
; M051: inserted
public int24,open_dev,organize,mem_err,newline,calldev,badload
public prndev,auxdev,config,commnd,condev,getnum,badfil,prnerr
public round,delim,print
public parseline,
public setdoscountryinfo,set_country_path,move_asciiz
public cntry_drv,cntry_root,cntry_path
public delim
public pathstring
public MseDev ; NTVDM internal mouse driver
;
;----------------------------------------------------------------------------
;
; procedure : parseline
;
; entry point is parseline. al contains the first character in command line.
;
;----------------------------------------------------------------------------
;
parseline proc near
; don't get character first time
push ds
push cs
pop ds
assume ds:sysinitseg
nextswtch:
cmp al,cr ; carriage return?
jz done_line
cmp al,lf ; linefeed?
jz put_back ; put it back and done
; anything less or equal to a space is ignored.
cmp al,' ' ; space?
jbe get_next ; skip over space
cmp al,'/'
jz getparm
stc ; mark error invalid-character-in-input
jmp short exitpl
getparm:
call check_switch
mov word ptr switches,bx ; save switches read so far
jc swterr
get_next:
call getchr
jc done_line
jmp nextswtch
swterr:
jmp short exitpl ; exit if error
done_line:
test word ptr switches,flagdrive ; see if drive specified
jnz okay
stc ; mark error no-drive-specified
jmp short exitpl
okay:
; mov ax,word ptr switches
; and ax,0003h ; get flag bits for changeline and non-rem
; mov word ptr deviceparameters.dp_deviceattributes,ax
; mov word ptr deviceparameters.dp_tracktableentries, 0
; clc ; everything is fine
; call setdeviceparameters
exitpl:
pop ds
ret
put_back:
inc count ; one more char to scan
dec chrptr ; back up over linefeed
jmp short done_line
parseline endp
;
;----------------------------------------------------------------------------
;
; procedure : check_switch
;
; processes a switch in the input. it ensures that the switch is valid, and
; gets the number, if any required, following the switch. the switch and the
; number *must* be separated by a colon. carry is set if there is any kind of
; error.
;
;----------------------------------------------------------------------------
;
check_switch proc near
call getchr
jc err_check
and al,0dfh ; convert it to upper case
cmp al,'A'
jb err_check
cmp al,'Z'
ja err_check
push es
push cs
pop es
mov cl,byte ptr switchlist ; get number of valid switches
mov ch,0
mov di,1+offset switchlist ; point to string of valid switches
repne scasb
pop es
jnz err_check
mov ax,1
shl ax,cl ; set bit to indicate switch
mov bx,word ptr switches ; get switches so far
or bx,ax ; save this with other switches
mov cx,ax
test ax, switchnum ; test against switches that require number to follow
jz done_swtch
call getchr
jc err_swtch
cmp al,':'
jnz err_swtch
call getchr
push bx ; preserve switches
mov byte ptr cs:sepchr,' ' ; allow space separators
call getnum
mov byte ptr cs:sepchr,0
pop bx ; restore switches
; because getnum does not consider carriage-return or line-feed as ok, we do
; not check for carry set here. if there is an error, it will be detected
; further on (hopefully).
call process_num
done_swtch:
clc
ret
err_swtch:
xor bx,cx ; remove this switch from the records
err_check:
stc
ret
check_switch endp
;
;----------------------------------------------------------------------------
;
; procedure : process_num
;
; this routine takes the switch just input, and the number following (if any),
; and sets the value in the appropriate variable. if the number input is zero
; then it does nothing - it assumes the default value that is present in the
; variable at the beginning. zero is ok for form factor and drive, however.
;
;----------------------------------------------------------------------------
;
process_num proc near
test word ptr switches,cx ; if this switch has been done before,
jnz done_ret ; ignore this one.
test cx,flagdrive
jz try_f
mov byte ptr drive,al
jmp short done_ret
try_f:
test cx,flagff
jz try_t
; ensure that we do not get bogus form factors that are not supported
; mov byte ptr deviceparameters.dp_devicetype,al
jmp short done_ret
try_t:
or ax,ax
jz done_ret ; if number entered was 0, assume default value
test cx,flagcyln
jz try_s
; mov word ptr deviceparameters.dp_cylinders,ax
jmp short done_ret
try_s:
test cx,flagseclim
jz try_h
mov word ptr slim,ax
jmp short done_ret
; must be for number of heads
try_h:
mov word ptr hlim,ax
done_ret:
clc
ret
process_num endp
;
;----------------------------------------------------------------------------
;
; procedure : organize
;
;----------------------------------------------------------------------------
;
assume ds:nothing, es:nothing
organize proc near
mov cx,[count]
jcxz nochar1
call mapcase
xor si,si
mov di,si
xor ax,ax
mov com_level, 0
;org1: call get ;skip leading control characters
; cmp al,' '
; jb org1
org1:
call skip_comment
jz end_commd_line ; found a comment string and skipped.
call get2 ; not a comment string. then get a char.
cmp al, lf
je end_commd_line ; starts with a blank line.
cmp al, ' '
jbe org1 ; skip leading control characters
jmp short findit
end_commd_line:
stosb ; store line feed char in buffer for the linecount.
mov com_level, 0 ; reset the command level.
jmp org1
nochar1:
stc
ret
findit:
push cx
push si
push di
mov bp,si
dec bp
mov si,offset comtab ;prepare to search command table
mov ch,0
findcom:
mov di,bp
mov cl,[si]
inc si
jcxz nocom
repe cmpsb
lahf
add si,cx ;bump to next position without affecting flags
sahf
lodsb ;get indicator letter
jnz findcom
cmp byte ptr es:[di], cr ;the next char might be cr,lf
je gotcom0 ; such as in "rem",cr,lf case.
cmp byte ptr es:[di], lf
je gotcom0
push ax
mov al, byte ptr es:[di] ;now the next char. should be a delim.
call delim
pop ax
jnz findcom
gotcom0:
pop di
pop si
pop cx
jmp short gotcom
nocom:
pop di
pop si
pop cx
mov al,'Z'
stosb ; save indicator char.
skip_line:
call get2
cmp al, lf ; skip this bad command line
jne skip_line
jmp end_commd_line ; handle next command line
gotcom: stosb ;save indicator char in buffer
mov cmd_indicator, al ; save it for the future use.
org2: call get2 ;skip the commad name until delimiter
cmp al, lf
je org21
cmp al, cr
je org21
call delim
jnz org2
jmp short org3
org21: ;if cr or lf then
dec si ; undo si, cx register
inc cx ; and continue
org3:
cmp cmd_indicator, 'Y' ; comment= command?
je get_cmt_token
cmp cmd_indicator, 'I' ; install= command?
je org_file
cmp cmd_indicator, 'D' ; device= command?
je org_file
cmp cmd_indicator, 'S' ; shell= is a special one!!!
je org_file
cmp cmd_indicator, '1' ; switches= command?
je org_switch
jmp org4
org_switch:
call skip_comment
jz end_commd_line_brdg
call get2
call org_delim
jz org_switch
stosb
jmp org5
org_file: ; get the filename and put 0 at end,
call skip_comment
jz org_put_zero
call get2 ; not a comment
call delim
jz org_file ; skip the possible delimeters
stosb ; copy the first non delim char found in buffer
org_copy_file:
call skip_comment ; comment char in the filename?
jz org_put_zero ; then stop copying filename at that point
call get2
cmp al, '/' ; a switch char? (device=filename/xxx)
je end_file_slash ; this will be the special case.
stosb ; save the char. in buffer
call delim
jz end_copy_file
cmp al, ' '
ja org_copy_file ; keep copying
jmp short end_copy_file ; otherwise, assume end of the filename.
get_cmt_token: ; get the token. just max. 2 char.
call get2
cmp al, ' ' ; skip white spaces or "=" char.
je get_cmt_token ; (we are allowing the other special
cmp al, tab ; charaters can used for comment id.
je get_cmt_token ; character.)
cmp al, '=' ; = is special in this case.
je get_cmt_token
cmp al, cr
je get_cmt_end ; cannot accept the carridge return
cmp al, lf
je get_cmt_end
mov cmmt1, al ; store it
mov cmmt, 1 ; 1 char. so far.
call get2
cmp al, ' '
je get_cmt_end
cmp al, tab
je get_cmt_end
cmp al, cr
je get_cmt_end
cmp al, lf
je end_commd_line_brdg
mov cmmt2, al
inc cmmt
get_cmt_end:
call get2
cmp al, lf
jne get_cmt_end ; skip it.
end_commd_line_brdg: jmp end_commd_line ; else jmp to end_commd_line
org_put_zero: ; make the filename in front of
mov byte ptr es:[di], 0 ; the comment string to be an asciiz.
inc di
jmp end_commd_line ; (maybe null if device=/*)
end_file_slash: ; al = "/" option char.
mov byte ptr es:[di],0 ; make a filename an asciiz
inc di ; and
stosb ; store "/" after that.
jmp short org5 ; continue with the rest of the line
end_copy_file:
mov byte ptr es:[di-1], 0 ; make it an asciiz and handle the next char.
cmp al, lf
je end_commd_line_brdg
jmp short org5
org4: ; org4 skips all delimiters after the command name except for '/'
call skip_comment
jz end_commd_line_brdg
call get2
call org_delim ; skip delimiters except '/' (mrw 4/88)
jz org4
jmp short org51
org5: ; rest of the line
call skip_comment ; comment?
jz end_commd_line_brdg
call get2 ; not a comment.
org51:
stosb ; copy the character
cmp al, '"' ; a quote ?
je at_quote
cmp al, ' '
ja org5
; M051 - Start
cmp cmd_indicator, 'U' ; Q: is this devicehigh
jne not_dh ; N:
cmp al, lf ; Q: is this line feed
je org_dhlf ; Y: stuff a blank before the lf
cmp al, cr ; Q: is this a cr
jne org5 ; N:
mov byte ptr es:[di-1], ' ' ; overwrite cr with blank
stosb ; put cr after blank
inc [insert_blank] ; indicate that blank has been
; inserted
jmp org5
not_dh: ; M051 - End
cmp al, lf ; line feed?
je org1_brdg ; handles the next command line.
jmp org5 ; handles next char in this line.
org_dhlf: ; M051 - Start
cmp [insert_blank], 1 ; Q:has a blank already been inserted
je org1_brdg ; Y:
mov byte ptr es:[di-1], ' ' ; overwrite lf with blank
stosb ; put lf after blank
; M051 - End
org1_brdg:
mov [insert_blank], 0 ; M051: clear blank indicator for
; M051: devicehigh
jmp org1
at_quote:
cmp com_level, 0
je up_level
mov com_level, 0 ; reset it.
jmp org5
up_level:
inc com_level ; set it.
jmp org5
organize endp
;
;----------------------------------------------------------------------------
;
; procedure : get2
;
;----------------------------------------------------------------------------
;
get2 proc near
jcxz noget
mov al,es:[si]
inc si
dec cx
od_ret:
ret
noget:
pop cx
mov count,di
mov org_count, di
xor si,si
mov chrptr,si
ng_ret:
ret
get2 endp
;
;----------------------------------------------------------------------------
;
; procedure : skip_comment
;
;skip the commented string until lf, if current es:si-> a comment string.
;in) es:si-> sting
; cx -> length.
;out) zero flag not set if not found a comment string.
; zero flag set if found a comment string and skipped it. al will contain
; the line feed charater at this moment when return.
; ax register destroyed.
; if found, si, cx register adjusted accordingly.
;
;----------------------------------------------------------------------------
;
skip_comment proc near
jcxz noget ; get out of the organize routine.
cmp com_level, 0 ; only check it if parameter level is 0.
jne no_commt ; (not inside quotations)
cmp cmmt, 1
jb no_commt
mov al, es:[si]
cmp cmmt1, al
jne no_commt
cmp cmmt, 2
jne skip_cmmt
mov al, es:[si+1]
cmp cmmt2, al
jne no_commt
skip_cmmt:
jcxz noget ; get out of organize routine.
mov al, es:[si]
inc si
dec cx
cmp al, lf ; line feed?
jne skip_cmmt
no_commt:
ret
skip_comment endp
;
;----------------------------------------------------------------------------
;
; procedure : delim
;
;----------------------------------------------------------------------------
;
delim proc near
cmp al,'/' ; ibm will assume "/" as an delimeter.
jz delim_ret
cmp al, 0 ; special case for sysinit!!!
jz delim_ret
org_delim: ; used by organize routine except for getting
cmp al,' ' ;the filename.
jz delim_ret
cmp al,9
jz delim_ret
cmp al,'='
jz delim_ret
cmp al,','
jz delim_ret
cmp al,';'
delim_ret:
ret
delim endp
;
;----------------------------------------------------------------------------
;
; procedure : newline
;
; newline returns with first character of next line
;
;----------------------------------------------------------------------------
;
newline proc near
call getchr ;skip non-control characters
jc nl_ret
cmp al,lf ;look for line feed
jnz newline
call getchr
nl_ret:
ret
newline endp
;
;----------------------------------------------------------------------------
;
; procedure : mapcase
;
;----------------------------------------------------------------------------
;
mapcase proc near
push cx
push si
push ds
push es
pop ds
xor si,si
convloop:
lodsb
ifdef DBCS
call testkanj
jz normconv ; if this is not lead byte
mov ah,al
lodsb ; get tail byte
cmp ax,DB_SPACE
jnz @f ; if this is not dbcs space
mov word ptr [si-2],' ' ; set 2 single space
@@:
dec cx
jcxz convdone ;just ignore 1/2 kanji error
jmp short noconv
;fall through, know al is not in 'a'-'z' range
normconv:
endif
cmp al,'a'
jb noconv
cmp al,'z'
ja noconv
sub al,20h
mov [si-1],al
noconv:
loop convloop
convdone:
pop ds
pop si
pop cx
ret
ifdef DBCS
public testkanj
testkanj:
push si
push ds
push ax
mov ax,6300h ; get dos dbcs vector
int 21h
pop ax
bdbcs_do:
cmp ds:word ptr [si],0 ; end of lead byte info?
jz bdbcs_notfound ; jump if so
cmp al,ds:[si] ; less than first byte character?
jb bdbcs_next ; jump if not
cmp al,ds:[si+1] ; grater than first byte character?
ja bdbcs_next
bdbcs_found:
push ax
xor ax,ax
inc ax ; reset zero flag
pop ax
bdbcs_exit:
pop ds
pop si
ret
bdbcs_notfound:
push ax
xor ax,ax ; set zero flag
pop ax
jmp short bdbcs_exit
bdbcs_next:
add si,2 ; points next lead byte table
jmp short bdbcs_do
endif ; DBCS
mapcase endp
;
;----------------------------------------------------------------------------
;
; procedure : round
;
; round the values in memlo and memhi to paragraph boundary.
; perform bounds check.
;
;----------------------------------------------------------------------------
;
round proc near
push ax
mov ax,[memlo]
call pararound ; para round up
add [memhi],ax
mov [memlo],0
mov ax,memhi ; ax = new memhi
cmp ax,[alloclim] ; if new memhi >= alloclim, error
jae mem_err
test cs:[setdevmarkflag], for_devmark
jz skip_set_devmarksize
push es
push si
mov si, cs:[devmark_addr]
mov es, si
sub ax, si
dec ax
mov es:[devmark_size], ax ; paragraph
and cs:[setdevmarkflag], not_for_devmark
pop si
pop es
skip_set_devmarksize:
pop ax
clc ;clear carry
ret
mem_err:
mov dx,offset badmem
push cs
pop ds
call print
jmp stall
round endp
;
;----------------------------------------------------------------------------
;
; procedure : calldev
;
;----------------------------------------------------------------------------
;
calldev proc near
mov ds,word ptr cs:[DevEntry+2]
add bx,word ptr cs:[DevEntry] ;do a little relocation
mov ax,ds:[bx]
push word ptr cs:[DevEntry]
mov word ptr cs:[DevEntry],ax
mov bx,offset packet
call [DevEntry]
pop word ptr cs:[DevEntry]
ret
calldev endp
;
;----------------------------------------------------------------------------
;
; procedure : todigit
;
;----------------------------------------------------------------------------
;
todigit proc near
sub al,'0'
jb notdig
cmp al,9
ja notdig
clc
ret
notdig:
stc
ret
todigit endp
;
;----------------------------------------------------------------------------
;
; procedure : getnum
;
; getnum parses a decimal number.
; returns it in ax, sets zero flag if ax = 0 (may be considered an
; error), if number is bad carry is set, zero is set, ax=0.
;
;----------------------------------------------------------------------------
;
getnum proc near
push bx
xor bx,bx ; running count is zero
b2:
call todigit ; do we have a digit
jc badnum ; no, bomb
xchg ax,bx ; put total in ax
push bx ; save digit
mov bx,10 ; base of arithmetic
mul bx ; shift by one decimal di...
pop bx ; get back digit
add al,bl ; get total
adc ah,0 ; make that 16 bits
jc badnum ; too big a number
xchg ax,bx ; stash total
call getchr ;get next digit
jc b1 ; no more characters
cmp al, ' ' ; space?
jz b15 ; then end of digits
cmp al, ',' ; ',' is a seperator!!!
jz b15 ; then end of digits.
cmp al, tab ; tab
jz b15
cmp al,sepchr ; allow 0 or special separators
jz b15
cmp al,'/' ; see if another switch follows
nop ; cas - remnant of old bad code
nop
jz b15
cmp al,lf ; line-feed?
jz b15
cmp al,cr ; carriage return?
jz b15
or al,al ; end of line separator?
jnz b2 ; no, try as a valid char...
b15:
inc count ; one more character to s...
dec chrptr ; back up over separator
b1:
mov ax,bx ; get proper count
or ax,ax ; clears carry, sets zero accordingly
pop bx
ret
badnum:
mov sepchr,0
xor ax,ax ; set zero flag, and ax = 0
pop bx
stc ; and carry set
ret
getnum endp
;*****************************************************************
setdoscountryinfo proc near
;input: es:di -> pointer to dos_country_cdpg_info
; ds:0 -> buffer.
; si = 0
; ax = country id
; dx = code page id. (if 0, then use ccsyscodepage as a default.)
; bx = file handle
; this routine can handle maxium 438 country_data entries.
;
;output: dos_country_cdpg_info set.
; carry set if any file read failure or wrong information in the file.
; carry set and cx = -1 if cannot find the matching country_id, codepage
; _id in the file.
push di
push ax
push dx
xor cx,cx
xor dx,dx
mov ax,512 ;read 512 bytes
call readincontrolbuffer ;read the file header
jc setdosdata_fail
push es
push si
push cs
pop es
mov di,offset country_file_signature
mov cx,8 ;length of the signature
repz cmpsb
pop si
pop es
jnz setdosdata_fail ;signature mismatch
add si,18 ;si -> county info type
cmp byte ptr ds:[si],1 ;only accept type 1 (currently only 1 header type)
jne setdosdata_fail ;cannot proceed. error return
inc si ;si -> file offset
mov dx,word ptr ds:[si] ;get the info file offset.
mov cx,word ptr ds:[si+2]
mov ax,6144 ;read 6144 bytes.
call readincontrolbuffer ;read info
jc setdosdata_fail
mov cx, word ptr ds:[si] ;get the # of country, codepage combination entries
cmp cx, 438 ;cannot handle more than 438 entries.
;
ja setdosdata_fail
inc si
inc si ;si -> entry information packet
pop dx ;restore code page id
pop ax ;restore country id
pop di
setdoscntry_find: ;search for desired country_id,codepage_id.
cmp ax, word ptr ds:[si+2] ;compare country_id
jne setdoscntry_next
cmp dx, 0 ;no user specified code page ?
je setdoscntry_any_codepage;then no need to match code page id.
cmp dx, word ptr ds:[si+4] ;compare code page id
je setdoscntry_got_it
setdoscntry_next:
add si, word ptr ds:[si] ;next entry
inc si
inc si ;take a word for size of entry itself
loop setdoscntry_find
mov cx, -1 ;signals that bad country id entered.
setdoscntry_fail:
stc
ret
setdosdata_fail:
pop si
pop cx
pop di
jmp short setdoscntry_fail
setdoscntry_any_codepage: ;use the code_page_id of the country_id found.
mov dx, word ptr ds:[si+4]
setdoscntry_got_it: ;found the matching entry
mov cs:cntrycodepage_id, dx ;save code page id for this country.
mov dx, word ptr ds:[si+10] ;get the file offset of country data
mov cx, word ptr ds:[si+12]
mov ax, 512 ;read 512 bytes
call readincontrolbuffer
jc setdoscntry_fail
mov cx, word ptr ds:[si] ;get the number of entries to handle.
inc si
inc si ;si -> first entry
setdoscntry_data:
push di ;es:di -> dos_country_cdpg_info
push cx ;save # of entry left
push si ;si -> current entry in control buffer
mov al, byte ptr ds:[si+2] ;get data entry id
call getcountrydestination ;get the address of destination in es:di
jc setdoscntry_data_next ;no matching data entry id in dos
mov dx, word ptr ds:[si+4] ;get offset of data
mov cx, word ptr ds:[si+6]
mov ax,4200h
stc
int 21h ;move pointer
jc setdosdata_fail
mov dx,512 ;start of data buffer
mov cx,20 ;read 20 bytes only. we only need to
mov ah,3fh ;look at the length of the data in the file.
stc
int 21h ;read the country.sys data
jc setdosdata_fail ;read failure
cmp ax,cx
jne setdosdata_fail
mov dx,word ptr ds:[si+4] ;get offset of data again.
mov cx,word ptr ds:[si+6]
mov ax,4200h
stc
int 21h ;move pointer back again
jc setdosdata_fail
push si
mov si,(512+8) ;get length of the data from the file
mov cx,word ptr ds:[si]
pop si
mov dx,512 ;start of data buffer
add cx,10 ;signature + a word for the length itself
mov ah,3fh ;read the data from the file.
stc
int 21h
jc setdosdata_fail
cmp ax, cx
jne setdosdata_fail
mov al,byte ptr ds:[si+2] ;save data id for future use.
mov si,(512+8) ;si-> data buffer + id tag field
mov cx,word ptr ds:[si] ;get the length of the file
inc cx ;take care of a word for lenght of tab
inc cx ;itself.
cmp cx,(2048 - 512 - 8) ;fit into the buffer?
ja setdosdata_fail
if bugfix
call setdbcs_before_copy
endif
cmp al, setcountryinfo ;is the data for setcountryinfo table?
jne setdoscntry_mov ;no, don't worry
push word ptr es:[di+ccmono_ptr-cccountryinfolen] ;cannot destroy ccmono_ptr address. save them.
push word ptr es:[di+ccmono_ptr-cccountryinfolen+2] ;at this time di -> cccountryinfolen
push di ;save di
push ax
mov ax,cs:cntrycodepage_id ;do not use the code page info in country_info
mov ds:[si+4], ax ;use the saved one for this !!!!
pop ax
setdoscntry_mov:
rep movsb ;copy the table into dos
cmp al, setcountryinfo ;was the ccmono_ptr saved?
jne setdoscntry_data_next
pop di ;restore di
pop word ptr es:[di+ccmono_ptr-cccountryinfolen+2] ;restore
pop word ptr es:[di+ccmono_ptr-cccountryinfolen]
setdoscntry_data_next:
pop si ;restore control buffer pointer
pop cx ;restore # of entries left
pop di ;restore pointer to dso_country_cdpg
add si, word ptr ds:[si] ;try to get the next entry
inc si
inc si ;take a word of entry length itself
dec cx
cmp cx,0
je setdoscntry_ok
jmp setdoscntry_data
setdoscntry_ok:
ret
setdoscountryinfo endp
if bugfix
setdbcs_before_copy proc near
cmp al,setdbcs ; dbcs vector set?
jnz @f ; jump if not
cmp word ptr es:[di], 0 ; zero byte data block?
jz @f ; jump if so
push di
push ax
push cx
mov cx,es:[di] ; load block length
add di,2 ; points actual data
xor al,al ; fill bytes
rep stosb ; clear data block
pop cx
pop ax
pop di
@@:
ret
setdbcs_before_copy endp
endif
getcountrydestination proc near
;get the destination address in the dos country info table.
;input: al - data id
; es:di -> dos_country_cdpg_info
;on return:
; es:di -> destination address of the matching data id
; carry set if no matching data id found in dos.
push cx
add di,ccnumber_of_entries ;skip the reserved area, syscodepage etc.
mov cx,word ptr es:[di] ;get the number of entries
inc di
inc di ;si -> the first start entry id
getcntrydest:
cmp byte ptr es:[di],al
je getcntrydest_ok
cmp byte ptr es:[di],setcountryinfo ;was it setcountryinfo entry?
je getcntrydest_1
add di,5 ;next data id
jmp short getcntrydest_loop
getcntrydest_1:
add di,new_country_size + 3 ;next data id
getcntrydest_loop:
loop getcntrydest
stc
jmp short getcntrydest_exit
getcntrydest_ok:
cmp al,setcountryinfo ;select country info?
jne getcntrydest_ok1
inc di ;now di -> cccountryinfolen
jmp short getcntrydest_exit
getcntrydest_ok1:
les di,dword ptr es:[di+1] ;get the destination in es:di
getcntrydest_exit:
pop cx
ret
getcountrydestination endp
readincontrolbuffer proc near
;move file pointer to cx:dx
;read ax bytes into the control buffer. (should be less than 2 kb)
;si will be set to 0 hence ds:si points to the control buffer.
;entry: cx,dx offset from the start of the file where the read/write pointer
; be moved.
; ax - # of bytes to read
; bx - file handle
; ds - buffer seg.
;return: the control data information is read into ds:0 - ds:0200.
; cx,dx value destroyed.
; carry set if error in reading file.
push ax ;# of bytes to read
mov ax, 4200h
stc
int 21h ;move pointer
pop cx ;# of bytes to read
jc ricb_exit
xor dx,dx ;ds:dx -> control buffer
xor si,si
mov ah,3fh ;read into the buffer
stc
int 21h ;should be less than 1024 bytes.
ricb_exit:
ret
readincontrolbuffer endp
set_country_path proc near
;in: ds - sysinitseg, es - confbot, si -> start of the asciiz path string
; dosinfo_ext, cntry_drv, cntry_root, cntry_path
; assumes current directory is the root directory.
;out: ds:di -> full path (cntry_drv).
; set the cntry_drv string from the country=,,path command.
; ds, es, si value saved.
push si
push ds ;switch ds, es
push es
pop ds
pop es ;now ds -> confbot, es -> sysinitseg
call chk_drive_letter ;current ds:[si] is a drive letter?
jc scp_default_drv ;no, use current default drive.
mov al, byte ptr ds:[si]
inc si
inc si ;si -> next char after ":"
jmp short scp_setdrv
scp_default_drv:
mov ah, 19h
int 21h
add al, "A" ;convert it to a character.
scp_setdrv:
mov cs:cntry_drv, al ;set the drive letter.
mov di, offset cntry_path
mov al, byte ptr ds:[si]
cmp al, "\"
je scp_root_dir
cmp al,"/" ;let's accept "/" as an directory delim
je scp_root_dir
jmp short scp_path
scp_root_dir:
dec di ;di -> cntry_root
scp_path:
call move_asciiz ;copy it
mov di, offset cntry_drv
scpath_exit:
push ds ;switch ds, es
push es
pop ds
pop es ;ds, es value restored
pop si
ret
set_country_path endp
chk_drive_letter proc near
;check if ds:[si] is a drive letter followed by ":".
;assume that every alpha charater is already converted to upper case.
;carry set if not.
push ax
cmp byte ptr ds:[si], "A"
jb cdletter_no
cmp byte ptr ds:[si], "Z"
ja cdletter_no
cmp byte ptr ds:[si+1], ":"
jne cdletter_no
jmp short cdletter_exit
cdletter_no:
stc
cdletter_exit:
pop ax
ret
chk_drive_letter endp
move_asciiz proc near
;in: ds:si -> source es:di -> target
;out: copy the string until 0.
;assumes there exists a 0.
masciiz_loop:
movsb
cmp byte ptr ds:[si-1],0 ;was it 0?
jne masciiz_loop
ret
move_asciiz endp
;
; ds:dx points to string to output (asciz)
;
; prints <badld_pre> <string> <badld_post>
badfil:
push cs
pop es
mov si,dx
badload:
mov dx,offset badld_pre ;want to print config error
mov bx, offset crlfm
prnerr:
push cs
pop ds
call print
prn1:
mov dl,es:[si]
or dl,dl
jz prn2
mov ah,std_con_output
int 21h
inc si
jmp prn1
prn2:
mov dx,bx
call print
cmp donotshownum,1 ; suppress line number when handling command.com
je prnexit
call error_line
prnexit:
ret
print:
cmp cs:bEchoConfig, 0 ; NTVDM skip print call, Jonle
je prnexit
mov ah,std_con_string_output
int 21h
ret
if noexec
; load non exe file called [ds:dx] at memory location es:bx
ldfil:
push ax
push bx
push cx
push dx
push si
push ds
push bx
xor ax,ax ;open the file
mov ah,open
stc ;in case of int 24
int 21h
pop dx ;clean stack in case jump
jc ldret
push dx
mov bx,ax ;handle in bx
xor cx,cx
xor dx,dx
mov ax,(lseek shl 8) or 2
stc ;in case of int 24
int 21h ; get file size in dx:ax
jc ldclsp
or dx,dx
jnz lderrp ; file >64k
pop dx
push dx
mov cx,es ; cx:dx is xaddr
add dx,ax ; add file size to xaddr
jnc dosize
add cx,1000h ; ripple carry
dosize:
mov ax,dx
call pararound
mov dx,ax
add cx,dx
cmp cx,[alloclim]
jb okld
jmp mem_err
okld:
xor cx,cx
xor dx,dx
mov ax,lseek shl 8 ;reset pointer to beginning of file
stc ;in case of int 24
int 21h
jc ldclsp
pop dx
push es ;read the file in
pop ds ;trans addr is ds:dx
mov cx,0ff00h ; .com files arn't any bigger than
; 64k-100h
mov ah,read
stc ;in case of int 24
int 21h
jc ldcls
mov si,dx ;check for exe file
cmp word ptr [si],"ZM"
clc ; assume ok
jnz ldcls ; only know how to do .com files
stc
jmp short ldcls
lderrp:
stc
ldclsp:
pop dx ;clean stack
ldcls:
pushf
mov ah,close ;close the file
stc
int 21h
popf
ldret: pop ds
pop si
pop dx
pop cx
pop bx
pop ax
ret
endif
;
; open device pointed to by dx, al has access code
; if unable to open do a device open null device instead
;
open_dev:
call open_file
jnc open_dev3
open_dev1:
mov dx,offset nuldev
call open_file
of_ret:
ret
open_dev3:
mov bx,ax ; handle from open to bx
xor ax,ax ; get device info
mov ah,ioctl
int 21h
test dl,10000000b
jnz of_ret
mov ah,close
int 21h
jmp open_dev1
open_file:
mov ah,open
stc
int 21h
ret
; test int24. return back to dos with the fake user response of "fail"
int24:
mov al, 3 ; fail the system call
iret ; return back to dos.
include copyrigh.inc ; copyright statement
nuldev db "NUL",0
condev db "CON",0
auxdev db "AUX",0
prndev db "PRN",0
MseDev db "MOUSE",0 ; NTVDM for internal spc mouse
; NTVDM we use a temp file for config.sys 23-Nov-1992 Jonle
; config db "C:\CONFIG.SYS",0
config db 64 dup (0)
cntry_drv db "A:"
cntry_root db "\"
cntry_path db "COUNTRY.SYS",0
db 52 dup (0)
country_file_signature db 0ffh,'COUNTRY'
cntrycodepage_id dw ?
commnd db "\COMMAND.COM",0
db 51 dup (0)
pathstring db 64 dup (0)
comtab label byte
; cmd len command cmd code
; ------- ------- --------
;
db 7, "BUFFERS", 'B'
db 5, "BREAK", 'C'
db 6, "DEVICE", 'D'
db 10, "DEVICEHIGH", 'U'
db 5, "FILES", 'F'
db 4, "FCBS", 'X'
db 9, "LASTDRIVE", 'L'
db 10, "MULTITRACK", 'M'
db 8, "DRIVPARM", 'P'
if stacksw
db 6, "STACKS", 'K'
endif
db 7, "COUNTRY", 'Q'
db 5, "SHELL", 'S'
db 7, "INSTALL", 'I'
db 7, "COMMENT", 'Y'
db 3, "REM", '0'
db 8, "SWITCHES", '1'
db 3, "DOS", 'H'
db 10, "ECHOCONFIG", 'E' ; NTVDM 14-Aug-1992 Jonle
db 11, "NTCMDPROMPT", 'T' ; NTVDM 06-May-1993 sudeepb
db 7, "DOSONLY", 'O' ; NTVDM 06-May-1993 sudeepb
db 0
hlim dw 2
slim dw 9
public bEchoConfig ; NTVDM - 14-Aug-1992 Jonle
bEchoConfig db 0
public drive
drive db ?
public switches
switches dw 0
switchlist db 8,"FHSTDICN" ; preserve the positions of n and c.
; the following depend on the positions of the various letters in switchlist
;switchnum equ 11111000b ; which switches require number
flagec35 equ 00000100b ; electrically compatible 3.5 inch disk drive
flagdrive equ 00001000b
flagcyln equ 00010000b
flagseclim equ 00100000b
flagheads equ 01000000b
flagff equ 10000000b
sysinitseg ends
end