4008 lines
93 KiB
NASM
4008 lines
93 KiB
NASM
page ,160
|
|
title bios system initialization
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; Modification history
|
|
;
|
|
; 26-Feb-1991 sudeepb Ported for NT DOSEm
|
|
;----------------------------------------------------------------------------
|
|
|
|
break macro ; dummy empty macro
|
|
endm
|
|
include version.inc
|
|
include biosseg.inc
|
|
include sysvar.inc
|
|
include curdir.inc
|
|
include pdb.inc
|
|
include exe.inc
|
|
include sf.inc
|
|
include arena.inc
|
|
include syscall.inc
|
|
include devsym.inc
|
|
include ioctl.inc
|
|
include biostruc.inc
|
|
include dossym.inc
|
|
include dosmac.inc
|
|
include mult.inc
|
|
include dossvc.inc
|
|
include dbgsvc.inc
|
|
include cmdsvc.inc
|
|
include xmssvc.inc
|
|
include vint.inc
|
|
|
|
Bios_Code segment
|
|
extrn BCode_start:near
|
|
extrn BCode_end:near
|
|
extrn seg_reinit:far
|
|
|
|
Bios_Code ends
|
|
|
|
include devmark.inc
|
|
include cputype.inc
|
|
|
|
|
|
true equ 0ffffh
|
|
false equ 0
|
|
cr equ 13
|
|
lf equ 10
|
|
tab equ 9
|
|
|
|
;multMULT equ 4ah
|
|
multMULTGETHMAPTR equ 1
|
|
multMULTALLOCHMA equ 2
|
|
|
|
|
|
stacksw equ true ;include switchable hardware stacks
|
|
mycds_size equ 71 ; size of curdir_list. if it is not
|
|
;the same, then will generate compile error.
|
|
|
|
if DEBUG ; BUGBUG - Jeez, remove this!
|
|
dossize equ 0b200h
|
|
else
|
|
dossize equ 0a000h
|
|
endif
|
|
|
|
if ibmjapver
|
|
noexec equ true
|
|
else
|
|
noexec equ false
|
|
endif
|
|
|
|
; if mycds_size <> curdirlen,then force a compilatiaon error.
|
|
|
|
if mycds_size ne curdirlen
|
|
%out !!! sysinit1 compilation failed. different cds size !!!
|
|
.errne mycds_size eq curdirlen
|
|
endif
|
|
|
|
if not ibmjapver
|
|
extrn re_init:far
|
|
endif
|
|
|
|
ifdef TAIWAN
|
|
extrn cdosinit:near
|
|
endif
|
|
|
|
;---------------------------------------
|
|
|
|
Bios_Data segment
|
|
|
|
;equates for main stack and stack initialization program
|
|
|
|
if stacksw
|
|
|
|
extrn NextStack:dword ; Win386 Instance table stuff
|
|
extrn IT_StackLoc:dword ; we have to plug in so that our
|
|
extrn IT_StackSize:word ; stacks can be instanced
|
|
|
|
entrysize equ 8
|
|
|
|
mincount equ 8
|
|
defaultcount equ 9
|
|
maxcount equ 64
|
|
|
|
minsize equ 32
|
|
defaultsize equ 128
|
|
maxsize equ 512
|
|
|
|
allocbyte equ 0
|
|
intlevel equ 1
|
|
savedsp equ 2
|
|
savedss equ 4
|
|
newsp equ 6
|
|
|
|
free equ 0
|
|
allocated equ 1
|
|
overflowed equ 2
|
|
clobbered equ 3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; external variables in ibmbio for int19h handling rouitne.
|
|
|
|
extrn int19sem:byte
|
|
|
|
irp aa,<02,08,09,0a,0b,0c,0d,0e,70,72,73,74,76,77>
|
|
extrn int19old&aa:dword
|
|
endm
|
|
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.
|
|
|
|
extrn multrk_flag:word
|
|
;
|
|
;SR; Win386 present flag
|
|
;
|
|
extrn IsWin386:BYTE
|
|
;
|
|
;SR; Added for SetFocus routine for WIN386 support
|
|
;
|
|
extrn V86_Crit_SetFocus:far
|
|
|
|
extrn xms:dword ; entry point for xms driver
|
|
extrn inHMA:byte ; flag meaning we're running high
|
|
|
|
extrn FreeHMAPtr:word
|
|
extrn MoveDOSIntoHMA:dword
|
|
extrn SysinitPresent:byte
|
|
extrn DemInfoFlag:byte
|
|
extrn spc_mse_int10:dword
|
|
extrn int29Perf:dword
|
|
|
|
extrn outchr:near
|
|
Bios_Data ends
|
|
|
|
; NTVDM 16-Sep-1992 Jonle
|
|
; Softpc Kbd, mouse, emm drivers
|
|
SpcKbdSeg segment
|
|
extrn InstSpcKbd:near
|
|
extrn SpcKbdBeg:byte
|
|
extrn SpcKbdEnd:byte
|
|
extrn int10h_vector:near
|
|
SpcKbdSeg ends
|
|
|
|
SpcMseSeg segment
|
|
extrn InstSpcMse:near
|
|
extrn SpcMseBeg:byte
|
|
extrn SpcMseEnd:byte
|
|
SpcMseSeg ends
|
|
|
|
SpcEmmSeg segment
|
|
extrn InitSpcEmm:near
|
|
extrn SpcEmmBeg:byte
|
|
extrn SpcEmmEnd:byte
|
|
extrn SI_end:byte
|
|
SpcEmmSeg ends
|
|
|
|
|
|
|
|
|
|
sysinitseg segment
|
|
assume cs:sysinitseg, ds:nothing,es:nothing,ss:nothing
|
|
|
|
extrn badcom:byte
|
|
extrn condev:byte
|
|
extrn auxdev:byte
|
|
extrn prndev:byte
|
|
extrn commnd:byte
|
|
extrn devmark_addr:word
|
|
extrn setdevmarkflag:byte
|
|
extrn pathstring:byte
|
|
|
|
extrn print:near
|
|
extrn int24:near
|
|
extrn mem_err:near
|
|
extrn doconf:near
|
|
extrn multi_pass:near
|
|
|
|
extrn badload:near
|
|
extrn error_line:near
|
|
|
|
extrn ShrinkUMB:near
|
|
extrn UnlinkUMB:near ;M002
|
|
extrn AllocUMB:near
|
|
extrn toomanydrivesmsg:byte ; M029
|
|
|
|
|
|
;NTVDM
|
|
extrn MseDev:byte ; internal mouse driver name
|
|
extrn AllocUMBLow:near ; mem alloc for new internal drivers
|
|
extrn bEchoConfig:byte
|
|
extrn config:byte
|
|
|
|
public current_dos_location
|
|
public device_list
|
|
public sysi_country
|
|
public memory_size
|
|
public default_drive
|
|
public buffers
|
|
public files
|
|
public num_cds
|
|
public sysinit
|
|
public cntryfilehandle
|
|
public command_line
|
|
|
|
if stacksw ; internal stack information
|
|
public stack_count
|
|
public stack_size
|
|
public stack_addr
|
|
endif
|
|
|
|
public dosinfo
|
|
public fcbs
|
|
public keep
|
|
public confbot
|
|
public alloclim
|
|
public zero
|
|
public sepchr
|
|
public count
|
|
public chrptr
|
|
public org_count
|
|
public bufptr
|
|
public memlo
|
|
public prmblk
|
|
public memhi
|
|
public ldoff
|
|
public area
|
|
public packet
|
|
public unitcount
|
|
public break_addr
|
|
public bpb_addr
|
|
public drivenumber
|
|
public config_size
|
|
public install_flag
|
|
public com_level
|
|
public cmmt
|
|
public cmmt1
|
|
public cmmt2
|
|
public cmd_indicator
|
|
public linecount
|
|
public showcount
|
|
public buffer_linenum
|
|
public donotshownum
|
|
public h_buffers
|
|
public configmsgflag
|
|
public do_install_exec
|
|
public multi_pass_id
|
|
public temp_bcode_seg
|
|
public seg_reinit_ptr
|
|
|
|
public toomanydrivesflag ; M029
|
|
|
|
sysinit$:
|
|
if stacksw
|
|
.sall
|
|
|
|
; interrupt level 2, 3, 4, 5, 6, 7,(10, 11, 12, 14, 15 - at level)
|
|
; should follow the standard interrupt sharing scheme which has
|
|
; a standard header structure.
|
|
; fyi, the following shows the relations between
|
|
; the interrupt vector and interrupt level.
|
|
; vec(hex) 2 8 9 a b c d e 70 72 73 74 76 77
|
|
; lvl(deci) 9 0 1 2 3 4 5 6 8 10 11 12 14 15
|
|
; msstack module modifies the following interrupt vectors
|
|
; to meet the standard interrupt sharing standard;
|
|
; a, b, c, d, e, 72, 73, 74, 76, 77.
|
|
; also, for interrupt level 7 and 15, the firstflag in a standard header
|
|
; should be initialized to indicat whether this interrupt handler is
|
|
; the first (= 80h) or not. the firstflag entry of int77h's
|
|
; program header is initialized in this module.
|
|
; firstflag is only meaningful for interrupt level 7 and 15.
|
|
;
|
|
|
|
; user specifies the number of stack elements - default = 9
|
|
; minimum = 8
|
|
; maximum = 64
|
|
;
|
|
; intercepts asynchronous hardware interrupts only
|
|
;
|
|
; picks a stack from pool of stacks and switches to it
|
|
;
|
|
; calls the previously saved interrupt vector after pushing flags
|
|
;
|
|
; on return, returns the stack to the stack pool
|
|
;
|
|
|
|
|
|
; this is a modification of stacks:
|
|
; 1. to fix a bug which was causing the program to take up too much space.
|
|
; 2. to dispense stack space from hi-mem first rather than low-mem first.
|
|
; . clobbers the stack that got too big instead of innocent stack
|
|
; . allows system to work if the only stack that got too big was the most
|
|
; deeply nested one
|
|
; 3. disables nmi interrupts while setting the nmi vector.
|
|
; 4. double checks that a nested interrupt didn't get the same stack.
|
|
; 5. intercepts ints 70, 72-77 for pc-ats and other future products
|
|
|
|
even
|
|
dw 0 ; spare field but leave these in order
|
|
stackcount dw 0
|
|
stackat dw 0
|
|
stacksize dw 0
|
|
stacks dw 0
|
|
dw 0
|
|
|
|
firstentry dw stacks
|
|
lastentry dw stacks+(defaultcount*entrysize)-entrysize
|
|
nextentry dw stacks+(defaultcount*entrysize)-entrysize
|
|
|
|
|
|
; these are the individual interrupt handlers
|
|
|
|
assume ds:nothing,es:nothing,ss:nothing
|
|
|
|
public int02
|
|
public old02
|
|
old02 dd 0
|
|
int02 proc far
|
|
|
|
;; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle
|
|
;;
|
|
;; *********************************************************************
|
|
;;
|
|
;; this is special support for the pc convertible / nmi handler
|
|
;;
|
|
;; on the pc convertible, there is a situation where an nmi can be
|
|
;; caused by using the "out" instructions to certain ports. when this
|
|
;; occurs, the pc convertible hardware *guarantees* that **nothing**
|
|
;; can stop the nmi or interfere with getting to the nmi handler. this
|
|
;; includes other type of interrupts (hardware and software), and
|
|
;; also includes other type of nmi's. when any nmi has occured,
|
|
;; no other interrtupt (hardware, software or nmi) can occur until
|
|
;; the software takes specific steps to allow further interrupting.
|
|
;;
|
|
;; for pc convertible, the situation where the nmi is generated by the
|
|
;; "out" to a control port requires "fixing-up" and re-attempting. in
|
|
;; otherwords, it is actually a "restartable exception". in this
|
|
;; case, the software handler must be able to get to the stack in
|
|
;; order to figure out what instruction caused the problem, where
|
|
;; it was "out"ing to and what value it was "out"ing. therefore,
|
|
;; we will not switch stacks in this situation. this situation is
|
|
;; detected by interrogating port 62h, and checking for a bit value
|
|
;; of 80h. if set, *****do not switch stacks*****.
|
|
;;
|
|
;; *********************************************************************
|
|
;
|
|
; push ax
|
|
; push es
|
|
; mov ax,0f000h
|
|
; mov es,ax
|
|
; cmp byte ptr es:[0fffeh],mdl_convert ;check if convertible
|
|
; pop es
|
|
; jne normal02
|
|
;
|
|
; in al,62h
|
|
; test al,80h
|
|
; jz normal02
|
|
;
|
|
;special02:
|
|
; pop ax
|
|
; jmp dword ptr old02
|
|
;
|
|
;normal02:
|
|
; pop ax
|
|
;
|
|
|
|
call do_int_stacks
|
|
dw old02
|
|
|
|
int02 endp
|
|
|
|
public int08
|
|
public old08
|
|
old08 dd 0
|
|
int08 proc far
|
|
call do_int_stacks
|
|
dw old08
|
|
int08 endp
|
|
|
|
public int09
|
|
public old09
|
|
old09 dd 0
|
|
int09 proc far
|
|
|
|
; keyboard interrupt must have a three byte jump, a nop and a zero byte
|
|
; as its first instruction for compatibility reasons
|
|
|
|
ifidn <09>,<09>
|
|
jmp short keyboard_lbl
|
|
nop
|
|
db 0
|
|
keyboard_lbl label near
|
|
endif
|
|
|
|
call do_int_stacks
|
|
dw old09
|
|
int09 endp
|
|
|
|
public int70
|
|
public old70
|
|
old70 dd 0
|
|
int70 proc far
|
|
call do_int_stacks
|
|
dw old70
|
|
int70 endp
|
|
|
|
irp a,<0a,0b,0c,0d,0e,72,73,74,76,77>
|
|
public int&a
|
|
public old&a
|
|
public firstflag&a
|
|
int&a proc far
|
|
jmp short entry_int&a&_stk
|
|
old&a dd 0 ;forward pointer
|
|
dw 424bh ;compatible signature for int. sharing
|
|
firstflag&a db 0 ;the firstly hooked.
|
|
jmp short intret_&a ;reset routine. we don't care this.
|
|
db 7 dup (0) ;reserved for future.
|
|
entry_int&a&_stk:
|
|
call do_int_stacks
|
|
dw old&a
|
|
intret_&a:
|
|
jmp DOIRET
|
|
int&a endp
|
|
endm
|
|
|
|
|
|
DOCLI:
|
|
FCLI
|
|
ret
|
|
DOSTI:
|
|
FSTI
|
|
ret
|
|
DOIRET:
|
|
FIRET
|
|
|
|
|
|
;********************************************************************
|
|
;common routines
|
|
|
|
; do interrupt stack switching. the fake return address holds
|
|
; a pointer to the far-pointer of the actual interrupt
|
|
; service routine
|
|
|
|
do_int_stacks:
|
|
push ax
|
|
push bp
|
|
push es
|
|
mov es, cs:[stacks+2] ; get segment of stacks
|
|
|
|
mov bp,nextentry ; get most likely candidate
|
|
mov al,allocated
|
|
xchg es:byte ptr allocbyte[bp],al ; grab the entry
|
|
cmp al,free ; still avail?
|
|
jne notfree02
|
|
|
|
sub nextentry,entrysize ; set for next interrupt
|
|
|
|
found02:
|
|
mov es:word ptr savedsp[bp],sp ; save sp value
|
|
mov es:word ptr savedss[bp],ss ; save ss also
|
|
|
|
mov ax,bp ; temp save of table offset
|
|
|
|
|
|
mov bp,es:word ptr newsp[bp] ; get new sp value
|
|
cmp es:[bp],ax ; check for offset into table
|
|
jne foundbad02
|
|
|
|
push bp
|
|
mov bp,sp
|
|
mov ax,8[bp] ; get offset of interrupt vector
|
|
pop bp
|
|
|
|
push es ; ss:sp = new stack
|
|
pop ss
|
|
mov sp,bp
|
|
|
|
mov bp,ax ; get pointer to interrupt vector
|
|
mov bp,cs:[bp]
|
|
pushf ; go execute the real interrupt handler
|
|
call cs:dword ptr [bp] ; call the old interrupt vector
|
|
|
|
mov bp,sp ; retrieve the table offset for us
|
|
mov bp,es:[bp] ; but leave it on the stack
|
|
mov ss,es:word ptr savedss[bp] ; get old stack back
|
|
mov sp,es:word ptr savedsp[bp]
|
|
|
|
|
|
mov es:byte ptr allocbyte[bp],free ; free the entry
|
|
mov nextentry,bp ; setup to use next time
|
|
|
|
newerror02:
|
|
pop es
|
|
pop bp ; saved on entry
|
|
pop ax ; saved on entry
|
|
add sp,2 ; lose the fake return address
|
|
|
|
intret_02:
|
|
jmp DOIRET ; done with this interrupt
|
|
|
|
notfree02:
|
|
cmp al,allocated ; error flag
|
|
je findnext02 ; no, continue
|
|
xchg es:byte ptr allocbyte[bp],al ; yes, restore error value
|
|
|
|
findnext02:
|
|
call longpath
|
|
jmp found02
|
|
|
|
foundbad02:
|
|
cmp bp,firstentry
|
|
jc findnext02
|
|
mov bp,ax ; flag this entry
|
|
mov es:byte ptr allocbyte[bp],clobbered
|
|
jmp findnext02 ; keep looking
|
|
longpath:
|
|
mov bp,lastentry ; start with last entry in table
|
|
|
|
lploopp:
|
|
cmp es:byte ptr allocbyte[bp],free ; is entry free?
|
|
jne inuse ; no, try next one
|
|
|
|
mov al,allocated
|
|
xchg es:byte ptr allocbyte[bp],al ; allocate entry
|
|
cmp al,free ; is it still free?
|
|
je found ; yes, go use it
|
|
|
|
cmp al,allocated ; is it other than allocated or free?
|
|
je inuse ; no, check the next one
|
|
|
|
mov es:byte ptr allocbyte[bp],al ; yes, put back the error state
|
|
|
|
inuse:
|
|
cmp bp,firstentry
|
|
je fatal
|
|
sub bp,entrysize
|
|
jmp lploopp
|
|
|
|
found:
|
|
ret
|
|
|
|
fatal proc near
|
|
|
|
; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle
|
|
;
|
|
; push ds
|
|
; mov ax, 0f000h ;look at the model byte
|
|
; mov ds, ax
|
|
; cmp ds:byte ptr [0fffeh], mdl_convert ;convertible?
|
|
; pop ds
|
|
; jne skip_nmis
|
|
;
|
|
; mov al,07h ; disable pc convertible nmis
|
|
; out 72h,al
|
|
;
|
|
;skip_nmis:
|
|
|
|
call DOCLI ; disable and mask
|
|
mov al,0ffh ; all other ints
|
|
out 021h,al
|
|
out 0a1h,al
|
|
|
|
mov si,cs
|
|
mov ds,si
|
|
mov si,offset fatal_msg
|
|
|
|
;SR;
|
|
; We set all foci to this VM to issue the stack failure message
|
|
;
|
|
push ax
|
|
push ds
|
|
mov ax,Bios_Data
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
|
|
test ds:[IsWin386],1
|
|
pop ds
|
|
pop ax
|
|
assume ds:nothing
|
|
jz fatal_loop ;win386 not present, continue
|
|
|
|
call V86_Crit_SetFocus ;set focus to this VM
|
|
;
|
|
;SR; We do not bother about the returned status of this call.
|
|
;
|
|
|
|
fatal_loop:
|
|
lodsb
|
|
cmp al,'$'
|
|
je fatal_done
|
|
|
|
mov bl,7
|
|
mov ah,14
|
|
int 010h ; whoops, this enables ints
|
|
jmp fatal_loop
|
|
|
|
fatal_done:
|
|
jmp fatal_done
|
|
fatal endp
|
|
|
|
include msbio.cl5 ;fatal stack error message
|
|
.xall
|
|
public endstackcode
|
|
endstackcode label byte
|
|
endif
|
|
|
|
sysinit:
|
|
jmp goinit
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
DDHighInfo struc
|
|
ddhigh_CSegPtr dd ? ; pointer to code segment to be relocated
|
|
ddhigh_CSegLen dw ? ; length of code segment to be relocated
|
|
ddhigh_CallBak dd ? ; pointer to the call back routine
|
|
DDHighInfo ends
|
|
|
|
public runhigh
|
|
runhigh db 0h
|
|
|
|
|
|
dosinfo dd 0 ; address of the DOS Sysini Variables
|
|
|
|
dos_temp_location label dword
|
|
dosinit dw 0
|
|
current_dos_location dw 0
|
|
|
|
device_list dd 0
|
|
|
|
sysi_country dd 0 ; pointer to country table in dos
|
|
|
|
dos_segreinit dw 0,0 ; room for dword
|
|
|
|
lo_doscod_size dw 0 ; dos code size when in low mem
|
|
hi_doscod_size dw 0 ; dos code size when in HMA
|
|
|
|
def_php dw 0
|
|
|
|
|
|
; M022--
|
|
; pointer for calling into Bios_Code for re-initializing segment values.
|
|
; call with ax = new segment for Bios_Code. Notice that we'll
|
|
; call it in its temporary home, cuz seg_reinit won't get moved to
|
|
; the new home.
|
|
|
|
seg_reinit_ptr label dword
|
|
|
|
dw offset Bios_Code:seg_reinit
|
|
temp_bcode_seg dw Bios_Code
|
|
|
|
|
|
;variables for stack initialization program.
|
|
|
|
if stacksw
|
|
stack_count dw defaultcount
|
|
stack_size dw defaultsize
|
|
stack_addr dd 0
|
|
endif
|
|
|
|
; various default values
|
|
|
|
memory_size dw 1
|
|
RPLMemTop dw 0
|
|
default_drive db 0 ;initialized by ibminit.
|
|
buffers dw -1 ; initialized during buffer allocation
|
|
h_buffers dw 0 ; # of the heuristic buffers. initially 0.
|
|
singlebuffersize dw ? ; maximum sector size + buffer header
|
|
|
|
files db 8 ; enough files for pipe
|
|
fcbs db 4 ; performance for recycling
|
|
keep db 0 ; keep original set
|
|
num_cds db 1 ; minimum needed is 1, so that initialization does'nt have a problem
|
|
confbot dw ?
|
|
alloclim dw ?
|
|
DirStrng db "A:\",0 ; string for the root directory of a drive
|
|
command_line db 2,0,"P" ;default command.com args
|
|
db 125 dup (0)
|
|
zero db 0
|
|
sepchr db 0
|
|
linecount dw 0 ; line count in config.sys
|
|
showcount db ' ',cr,lf,'$' ; used to convert linecount to ascii.
|
|
buffer_linenum dw 0 ; line count for "buffers=" command if entered.
|
|
|
|
|
|
buf_prev_off dw 0
|
|
|
|
if not noexec
|
|
comexe exec0 <0,command_line,default_drive,zero>
|
|
endif
|
|
|
|
;------------------------------------------------------------------
|
|
; variables for install= command.
|
|
|
|
multi_pass_id db 0 ; parameter passed to multi_pass
|
|
; indicating the pass number
|
|
; 0 - do scan for DOS=HIGH/LOW
|
|
; 1 - load device drivers
|
|
; 2 - was to load IFS
|
|
; now it is unused
|
|
; 3 - do install=
|
|
; >3 - nop
|
|
install_flag dw 0
|
|
|
|
have_install_cmd equ 00000001b ; config.sys has install= commands
|
|
has_installed equ 00000010b ; sysinit_base installed.
|
|
|
|
config_size dw 0 ; size of config.sys file. set by sysconf.asm
|
|
sysinit_base_ptr dd 0 ; pointer to sysinit_base
|
|
sysinit_ptr dd 0 ; returning addr. from sysinit_base
|
|
checksum dw 0 ; used by sum_up
|
|
|
|
ldexec_fcb db 20 dup (' ') ;big enough
|
|
ldexec_line db 0 ;# of parm characters
|
|
ldexec_start db ' '
|
|
ldexec_parm db 80 dup (0)
|
|
|
|
instexe exec0 <0,ldexec_line,ldexec_fcb,ldexec_fcb>
|
|
|
|
;------------------------------------------------------------------
|
|
;variables for comment=
|
|
|
|
com_level db 0 ;level of " " in command line
|
|
cmmt db 0 ;length of comment string token
|
|
cmmt1 db 0 ;token
|
|
cmmt2 db 0 ;token
|
|
cmd_indicator db ?
|
|
donotshownum db 0
|
|
|
|
;------------------------------------------------------------------
|
|
count dw 0
|
|
org_count dw 0
|
|
chrptr dw 0
|
|
cntryfilehandle dw 0
|
|
old_area dw 0
|
|
impossible_owner_size dw 0 ; paragraph
|
|
;------------------------------------------------------------------
|
|
|
|
bucketptr label dword
|
|
bufptr label dword ;leave this stuff in order!
|
|
memlo dw 0
|
|
prmblk label word
|
|
memhi dw 0
|
|
ldoff dw 0
|
|
area dw 0
|
|
|
|
packet db 24 ; was 22
|
|
db 0
|
|
db 0 ;initialize code
|
|
dw 0
|
|
db 8 dup (?)
|
|
|
|
unitcount db 0
|
|
break_addr dd 0
|
|
bpb_addr dd 0
|
|
drivenumber db 0
|
|
configmsgflag dw 0 ; used to control "error in config.sys line #" message
|
|
|
|
toomanydrivesflag db 0 ;>24 fixed disk partitions flag ; M029
|
|
|
|
BCodeSeg dw Bios_Code
|
|
|
|
|
|
|
|
|
|
;SR;
|
|
; This is the communication block between the DOS and the BIOS. It starts at
|
|
;the SysinitPresent flag. Any other data that needs to be communicated
|
|
;to the DOS should be added after SysinitPresent. The pointer to this block
|
|
;is passed to DOS as part of the DOSINIT call.
|
|
;
|
|
|
|
BiosComBlock dd Bios_Data:SysinitPresent
|
|
|
|
tempstack db 80h dup (?)
|
|
|
|
goinit:
|
|
|
|
ifdef JAPAN
|
|
mov ah,50h ; set crt mode
|
|
mov al,0
|
|
mov bx,81 ; for JAPAN
|
|
int 10h
|
|
mov ah,50h ; set keyboard mode
|
|
mov al,0
|
|
mov bx,81 ; for JAPAN
|
|
int 16h
|
|
endif
|
|
cld
|
|
|
|
;; Before we installed spckbd.asm (we hook a lot of vectors there),
|
|
;; we shouldn't invoke any interrupt calls directly to bios(they will
|
|
;; go directly to ROM bios). Since we do know what exactly those ROM
|
|
;; bios(s) do, a safer manner is to issue bop to our 32 bits side.
|
|
;; int 12h ; Get Memory in 1k
|
|
BOP 12h
|
|
mov cl,6
|
|
shl ax,cl ;convert to 16-byte blocks(segment no.)
|
|
mov cx,ax
|
|
dec cx ; one para for an arena at end of mem
|
|
; in case of UMBs
|
|
mov memory_size,cx
|
|
|
|
push cs
|
|
pop ds
|
|
xor si,si
|
|
mov di,si
|
|
mov ax, offset sysinitgrp:SI_end ; need this much room for sysinit
|
|
call off_to_para
|
|
sub cx,ax
|
|
|
|
; we need to leave room for the DOS and for the BIOS
|
|
; code above sysinit in memory
|
|
;
|
|
sub cx,dossize/16 ; leave this much room for DOS
|
|
|
|
mov ax,offset BCode_end
|
|
call off_to_para ; leave this much room for BIOS code
|
|
sub cx,ax
|
|
|
|
mov es,cx ; offset where sysinit will be located
|
|
mov cx,offset sysinitgrp:SI_end
|
|
shr cx,1 ;divide by 2 to get words
|
|
rep movsw ;relocate sysinit
|
|
|
|
push es ; push relocated segment
|
|
mov ax,offset sysin
|
|
push ax ; push relocated entry point
|
|
|
|
retf ; far jump to relocated sysinit
|
|
|
|
|
|
; move the dos to its proper location
|
|
|
|
sysin:
|
|
assume ds:nothing,es:nothing,ss:nothing
|
|
|
|
mov ax, Bios_Data ; point DS to BIOS data
|
|
mov ds, ax
|
|
|
|
assume ds:Bios_Data
|
|
|
|
mov word ptr MoveDOSIntoHMA+2, cs ; set seg of routine to move DOS
|
|
mov SysinitPresent, 1 ; flag that MoveDOSIntoHMA can be called
|
|
|
|
SVC SVC_ISDEBUG
|
|
mov DemInfoFlag, al
|
|
|
|
test al,ISDBG_DEBUGGEE
|
|
je @f
|
|
SAVEREG <bx,dx,es>
|
|
mov bx, cs ; current base of BIOS
|
|
xor cx, cx
|
|
mov dx, current_dos_location; get offset of end of code
|
|
sub dx, bios_data ; add in length of data segment
|
|
REPT 4
|
|
shl dx, 1
|
|
rcl cx, 1
|
|
endm
|
|
|
|
mov ax, SYMOP_LOAD SHL 8 + ID_NTIO
|
|
SVC SVC_DEMSYSTEMSYMBOLOP
|
|
|
|
mov bx, 1 ; bugbug: Hardcoded segment number
|
|
mov ax, ds ; low segment location
|
|
mov es, ax ; relocated segment
|
|
|
|
mov ax, SYMOP_MOVE SHL 8 + ID_NTIO
|
|
SVC SVC_DEMSYSTEMSYMBOLOP
|
|
|
|
RESTOREREG <es,dx,bx>
|
|
@@:
|
|
|
|
; first move the MSDOS.SYS image up to a harmless place
|
|
; on top of our new sysinitseg
|
|
|
|
mov ax,offset sysinitgrp:SI_end ; how big is sysinitseg?
|
|
call off_to_para
|
|
mov cx,cs ; pick a buffer for msdos above us
|
|
add ax,cx
|
|
mov es,ax
|
|
xor si,si
|
|
mov di,si
|
|
|
|
mov ds,[current_dos_location] ; where it is (set by msinit)
|
|
|
|
assume ds:nothing
|
|
|
|
mov cx,dossize/2
|
|
rep movsw
|
|
mov [current_dos_location],es
|
|
|
|
; The DOS code is ORGed at a non-zero value to allow it to be located in
|
|
; HIMEM. Thus, the DOS segment location must be adjusted accordingly.
|
|
|
|
mov ax,ds:word ptr 3 ; get offset of dos
|
|
mov [dosinit],ax ; that's the entry point offset
|
|
call off_to_para ; subtract this much from segment
|
|
sub [current_dos_location],ax
|
|
|
|
|
|
; BIOS code is moved to the top of memory
|
|
; until it is determined whether it will be running in HIMEM or not.
|
|
|
|
|
|
; now put Bios_Code up on top of that. Assume Bios_Code + dossize < 64k
|
|
|
|
mov ax,es
|
|
add ax,dossize/16 ; get paragraph of end of dos
|
|
mov es,ax
|
|
xchg ax,temp_bcode_seg ; swap with original home of Bios_Code
|
|
mov ds,ax ; point to loaded image of Bios_Code
|
|
|
|
assume ds:nothing
|
|
|
|
mov si,offset BCode_start
|
|
mov di,si
|
|
mov cx,offset BCode_end
|
|
sub cx,si
|
|
shr cx,1
|
|
rep movsw ; move Bios_Code into place
|
|
|
|
mov ax,es ; tell it what segment it's in
|
|
call [seg_reinit_ptr] ; far call to seg_reinit in Bios_Code (M022)
|
|
|
|
|
|
; now call dosinit while it's in its temporary home
|
|
|
|
les di,cs:[BiosComBlock] ; ptr to BIOS communication block
|
|
lds si,cs:[device_list] ; set for call to dosinit
|
|
|
|
assume ds:nothing, es:nothing
|
|
|
|
mov dx,cs:[memory_size] ; set for call to dosinit
|
|
|
|
call DOCLI
|
|
mov ax,cs
|
|
mov ss,ax
|
|
align 2 ; assembler wouldn't let me do an "and 0fffeh"
|
|
locstack label byte ; on the mov sp,offset locstack
|
|
mov sp,offset locstack ; set stack
|
|
|
|
call DOSTI
|
|
|
|
|
|
; This call to DOSINIT will relocate the DOS data from its present location
|
|
; at the top of memory, to its final location in low memory just above the
|
|
; BIOS data. It will then build important DOS data structures in low
|
|
; memory following the DOS data. It returns (among many other things) the
|
|
; new starting address of free memory.
|
|
|
|
call [dos_temp_location] ; call dosinit
|
|
;es:di -> sysinitvars_ext
|
|
|
|
mov [def_php],ds ; save pointer to PSP
|
|
mov [hi_doscod_size],ax ; size of doscode (including exepatch)
|
|
mov [lo_doscod_size],cx ; (not including exepatch)
|
|
mov [dos_segreinit],dx ; save offset of segreinit
|
|
|
|
mov ax,word ptr es:[di.sysi_initvars]
|
|
mov word ptr dosinfo,ax
|
|
mov ax,word ptr es:[di.sysi_initvars+2]
|
|
mov word ptr [dosinfo+2],ax ;set the sysvar pointer
|
|
|
|
mov ax,word ptr es:[di.sysi_country_tab]
|
|
mov word ptr [sysi_country],ax
|
|
mov ax,word ptr es:[di.sysi_country_tab+2]
|
|
mov word ptr [sysi_country+2],ax ;set the sysi_country pointer
|
|
|
|
mov es,[current_dos_location] ; give dos its temporary loc.
|
|
mov [dos_segreinit+2],es
|
|
;
|
|
les di,dosinfo ;es:di -> dosinfo
|
|
|
|
clc ;get the extended memory size
|
|
|
|
; execute the get extended memory size subfunction in the bios int 15h
|
|
; if the function reports an error do nothing else store the extended
|
|
; memory size reported at the appropriate location in the dosinfo buffer
|
|
; currently pointed to by es:di. use the offsets specified in the
|
|
; definition of the sysinitvars struct in inc\sysvar.inc
|
|
|
|
mov ah,88h
|
|
;; IBM ps/2 90 int 15(ah = 88h) read a coms byte(0B6h) which we don't support.
|
|
;; it returns 0 on this query.
|
|
;; we issue a bop to 32bits to get the real extended memeory size
|
|
;; int 15h ;check extended memory size
|
|
BOP 15h
|
|
;; jc no_ext_memory
|
|
mov es:[di].sysi_ext_mem,ax ;save extended memory size
|
|
;; or ax, ax
|
|
no_ext_memory:
|
|
mov ax,es:[di.sysi_maxsec] ; get the sector size
|
|
add ax,bufinsiz ; size of buffer header
|
|
mov [singlebuffersize],ax ; total size for a buffer
|
|
|
|
SVC SVC_DEMGETBOOTDRIVE
|
|
mov [default_drive],al
|
|
mov es:[di.sysi_boot_drive],al ; set sysi_boot_drive
|
|
|
|
; determine if 386 system...
|
|
if 1
|
|
get_cpu_type ; macro to determine cpu type
|
|
cmp ax,2 ; is it a 386?
|
|
jne not_386_system ; no: don't mess with flag
|
|
endif
|
|
|
|
mov es:[di.sysi_dwmove],1
|
|
not_386_system:
|
|
mov al,es:[di.sysi_numio]
|
|
mov drivenumber,al ; save start of installable block drvs
|
|
|
|
mov ax,cs
|
|
sub ax,11h ; room for PSP we will copy shortly
|
|
mov cx,[singlebuffersize] ; temporary single buffer area
|
|
shr cx,1
|
|
shr cx,1 ; divide size by 16...
|
|
shr cx,1
|
|
shr cx,1 ; ...to get paragraphs...
|
|
inc cx ; ... and round up
|
|
|
|
; cas note: this unorthodox paragraph rounding scheme wastes a byte if
|
|
; [singlebuffersize] ever happens to be zero mod 16. Could this
|
|
; ever happen? Only if the buffer overhead was zero mod 16, since
|
|
; it is probably safe to assume that the sector size always will be.
|
|
;
|
|
; mohans also found a bug in CONFIG.SYS processing where it replaces
|
|
; EOF's with cr,lf's, without checking for collision with [confbot].
|
|
; perhaps the extra byte this code guarantees is what has kept that
|
|
; other code from ever causing a problem???
|
|
|
|
sub ax,cx
|
|
mov [confbot],ax ; temp "unsafe" location
|
|
; push es ; preserve pointer to DOSINFO data
|
|
; push di
|
|
|
|
; setup and initialize the temporary buffer
|
|
|
|
; les di,es:[di.sysi_buf] ;get the buffer chain entry pointer
|
|
; mov word ptr es:[di.Dirty_Buff_Count],0
|
|
; mov word ptr es:[di.Buff_Queue],0
|
|
; mov word ptr es:[di.Buff_Queue+2],ax
|
|
; mov es,ax
|
|
; xor ax,ax
|
|
; mov di,ax ;es:di -> single buffer
|
|
|
|
; mov es:[di.buf_next],ax ;points to itself
|
|
; mov es:[di.buf_prev],ax ;points to itself
|
|
|
|
; mov word ptr es:[di.buf_id],00ffh ;free buffer,clear flag
|
|
; mov word ptr es:[di.buf_sector],0
|
|
; mov word ptr es:[di.buf_sector+2],0
|
|
|
|
; pop di ; restore pointer to DOSINFO data
|
|
; pop es
|
|
|
|
push cs
|
|
pop ds
|
|
|
|
assume ds:sysinitseg
|
|
|
|
call tempcds ; set up cdss so re_init and sysinit
|
|
; can make disk system calls
|
|
assume ds:nothing ; tempcds trashes ds
|
|
|
|
mov ds,[def_php] ; retreive pointer to PSP returned by DOSINIT
|
|
|
|
if not ibmjapver
|
|
call re_init ; re-call the bios
|
|
endif
|
|
|
|
call DOSTI ; ints ok
|
|
cld ; make sure
|
|
|
|
; dosinit has set up a default "process" (php) at ds:0. we will move it out
|
|
; of the way by putting it just below sysinit at end of memory.
|
|
|
|
mov bx,cs
|
|
sub bx,10h
|
|
mov es,bx
|
|
xor si,si
|
|
mov di,si
|
|
mov cx,80h
|
|
rep movsw
|
|
|
|
mov word ptr es:[pdb_jfn_pointer + 2],es ; relocate
|
|
mov ah,set_current_pdb
|
|
int 21h ; tell dos we moved it
|
|
|
|
push ds ; preserve DS returned by DOSINIT
|
|
push cs
|
|
pop ds ; point DS to sysinitseg
|
|
|
|
assume ds:sysinitseg
|
|
|
|
; set up temp. critical error handler
|
|
mov dx,offset int24 ;set up int 24 handler
|
|
mov ax,(set_interrupt_vector shl 8) or 24h
|
|
int 21h
|
|
|
|
cmp byte ptr [TooManyDrivesFlag],0 ;Q: >24 partitions? M029
|
|
je no_err ; N: continue M029
|
|
mov dx,offset TooManyDrivesMsg ; Y: print error message M029
|
|
call print ; M029
|
|
no_err: ; M029
|
|
|
|
pop ds ; start of free memory
|
|
|
|
assume ds:nothing
|
|
|
|
mov dl,[default_drive]
|
|
or dl,dl
|
|
jz nodrvset ; bios didn't say
|
|
dec dl ; a = 0
|
|
mov ah,set_default_drive
|
|
int 21h ;select the disk
|
|
|
|
nodrvset:
|
|
|
|
;
|
|
; Process the CONFIG.SYS file
|
|
;
|
|
|
|
ProcessConfig:
|
|
|
|
;
|
|
; NTVDM store temp file name for config.sys, 23-Nov-1992 Jonle
|
|
;
|
|
push ds
|
|
push cs
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
mov dx,offset config ; ds:dx points file description
|
|
CMDSVC SVC_GETCONFIGSYS
|
|
pop ds
|
|
assume ds:nothing
|
|
|
|
|
|
ifndef TAIWAN
|
|
|
|
call doconf ;do pre-scan for dos=high/low
|
|
|
|
else ; taiwan
|
|
|
|
call chkoemlocaldrv
|
|
mov cs:oemdriverinst,ax
|
|
call cdosinit
|
|
push es
|
|
push bx
|
|
|
|
pop bx
|
|
pop es
|
|
call maketempvector ;make dummy int service routine
|
|
|
|
call doconf ;do pre-scan for dos=high/low
|
|
|
|
call chklocalexist ;check if local dev drv exist
|
|
;if not found,system halt
|
|
call recovercsiint ;recover csi interrupt vector
|
|
endif ; taiwan
|
|
|
|
|
|
|
|
; Now, we decide what to do with the DOS code.
|
|
; It will either be relocated to low memory, above the DOS data structures,
|
|
; or else it will be located in HiMem, in which case a stub with the DOS
|
|
; code entry points will be located in low memory. Dos_segreinit is used
|
|
; to tell the DOS data where the code has been placed, and to install the
|
|
; low memory stub if necessary. If the DOS is going to go into HiMem, we
|
|
; must first initialize it in its present location and load the installable
|
|
; device drivers. Then, if a HiMem driver has been located, we can actually
|
|
; relocate the DOS code into HiMem.
|
|
;
|
|
|
|
; M025 begin
|
|
|
|
cmp runhigh, 0 ; Did user choose to run low ?
|
|
je dont_install_stub ; yes, don't install dos low mem stub
|
|
;
|
|
;------ user chose to load high
|
|
;
|
|
|
|
|
|
mov es,[current_dos_location] ; give dos its temporary loc.
|
|
|
|
xor ax,ax ; ax = 00 ---> install stub
|
|
call cs:dword ptr [dos_segreinit] ; call dos segreinit
|
|
jmp short do_multi_pass
|
|
|
|
;
|
|
;------ User chose to load dos low
|
|
;
|
|
dont_install_stub:
|
|
|
|
xor bx, bx ; M012
|
|
; don't use int 21 call to alloc mem
|
|
|
|
call MovDOSLo ; move it !
|
|
|
|
|
|
mov ax, 1 ; dont install stub
|
|
mov es, current_dos_location; set_dos_final_position set it up
|
|
call dword ptr dos_segreinit ; inform dos about new seg
|
|
|
|
|
|
do_multi_pass:
|
|
|
|
call AllocFreeMem ; allocate all the free mem
|
|
; & update [memhi] & [area]
|
|
; start of free memory.
|
|
|
|
; M025 end
|
|
|
|
|
|
|
|
; NTVDM
|
|
; Copy softpc keyboard driver resident code to start of free mem
|
|
; Install Softpc IVT hooks
|
|
mov al,devmark_spc
|
|
call setdevmark
|
|
mov es, cs:[devmark_addr]
|
|
mov word ptr es:[arena_name], 'BK'
|
|
mov word ptr es:[arena_name+2], 'D'
|
|
|
|
cld
|
|
mov ax,[memhi]
|
|
push ds
|
|
mov cx,Bios_Data
|
|
mov ds,cx
|
|
assume ds:Bios_Data
|
|
mov word ptr spc_mse_int10,offset int10h_vector
|
|
mov word ptr spc_mse_int10+2,ax
|
|
mov word ptr int29Perf,offset outchr ; sudeepb 03-Nov-1992
|
|
mov word ptr int29Perf+2,ds ; added for int10 performance
|
|
pop ds
|
|
assume ds:nothing
|
|
|
|
mov es,ax ;es dest seg. for SpcKbd
|
|
push es
|
|
push cs
|
|
pop ds ;ds src seg for SpcKbd
|
|
mov si,offset sysinitgrp:SpcKbdBeg
|
|
mov cx,offset sysinitgrp:SpcKbdEnd
|
|
sub cx,si
|
|
xor di,di
|
|
mov [memlo],cx
|
|
or [setdevmarkflag],for_devmark
|
|
call round
|
|
rep movsb
|
|
pop ds
|
|
call sysinitgrp:InstSpcKbd
|
|
|
|
; save value of int09 for int 09 hardware stack disable
|
|
xor ax,ax
|
|
mov ds,ax
|
|
mov si, 09h*4
|
|
lodsw
|
|
mov word ptr cs:old09, ax
|
|
lodsw
|
|
mov word ptr cs:old09+2, ax
|
|
|
|
; save value of int08 for int 08 hardware stack disable
|
|
mov si, 08h*4
|
|
lodsw
|
|
mov word ptr cs:old08, ax
|
|
lodsw
|
|
mov word ptr cs:old08+2, ax
|
|
|
|
|
|
; NTVDM
|
|
; Attempt to init emm memory manager. if we have emm
|
|
; then load internal emm stub device driver.
|
|
;
|
|
; check if emm memory is available
|
|
mov ax, [memhi]
|
|
inc ax ;1 para for arena header
|
|
mov ds, ax ;expected seg for emm drv
|
|
call sysinitgrp:InitSpcEmm
|
|
cmp ax, 0
|
|
jne NoEmmServices
|
|
|
|
; fill in the arena name
|
|
mov al, devmark_device
|
|
call setdevmark
|
|
mov es, cs:[devmark_addr]
|
|
mov word ptr es:[arena_name], 'ME'
|
|
mov word ptr es:[arena_name+2], 'M'
|
|
|
|
; copy in emm stub driver code
|
|
cld
|
|
mov ax,[memhi]
|
|
mov es,ax
|
|
push es ;save for diddling devheader
|
|
push cs
|
|
pop ds
|
|
mov si,offset sysinitgrp:SpcEmmBeg
|
|
mov cx,offset sysinitgrp:SpcEmmEnd
|
|
sub cx,si
|
|
xor di,di
|
|
mov [memlo],cx
|
|
or [setdevmarkflag],for_devmark
|
|
call round
|
|
rep movsb
|
|
|
|
; link in emm stub driver
|
|
; so apps can find emm driver
|
|
pop ds
|
|
xor si, si ;ds:si = device header
|
|
les di, cs:[dosinfo] ;es:di = to dos info
|
|
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 word ptr ds:[si], cx ;link in the driver
|
|
mov word ptr ds:[si+2], dx
|
|
|
|
NoEmmServices:
|
|
|
|
|
|
; Now, process config.sys some more.
|
|
; Load the device drivers and install programs
|
|
inc cs:multi_pass_id ; multi_pass_id = 1
|
|
call multi_pass ; load device drivers
|
|
|
|
|
|
; NTVDM
|
|
; Install Softpc Mouse driver in UMB if can else in LOW memory
|
|
; This must be done after himem.sys is loaded for umb support
|
|
;
|
|
mov cx, offset sysinitgrp:SpcMseEnd
|
|
sub cx, offset sysinitgrp:SpcMseBeg ; cx, size of SpceMse
|
|
mov di, offset MseDev
|
|
push cs
|
|
pop es ; es:di, dest
|
|
push cx ; preserve cx
|
|
call AllocUMBLow
|
|
pop cx
|
|
push es ; save to pass to InstSpcMse
|
|
|
|
mov si, offset sysinitgrp:SpcMseBeg
|
|
push cs
|
|
pop ds ; ds:si, Source of SpcMse code
|
|
rep movsb
|
|
|
|
pop ds
|
|
call sysinitgrp:InstSpcMse
|
|
|
|
|
|
|
|
call ShrinkUMB
|
|
call UnlinkUMB ; unlink all UMBs ;M002
|
|
inc cs:multi_pass_id ; multi_pass_id = 2
|
|
call multi_pass ; was load ifs (now does nothing)
|
|
call endfile ; setup fcbs, files, buffers etc
|
|
|
|
;
|
|
;Reset SysinitPresent flag here. This is needed for the special fix for lying
|
|
;to device drivers. This has been moved up to this point to avoid problems
|
|
;with overlays called from installed programs
|
|
;
|
|
mov ax,Bios_Data
|
|
mov es,ax ; point ES to bios data
|
|
|
|
assume es:Bios_Data
|
|
|
|
mov es:SysinitPresent,0 ; clear SysinitPresent flag
|
|
|
|
test install_flag,have_install_cmd ; are there install commands?
|
|
jz dolast ; no, no need for further processing
|
|
inc cs:multi_pass_id ; mult_pass_id = 3
|
|
call multi_pass ; execute install= commands
|
|
dolast:
|
|
assume es:nothing
|
|
|
|
; [area] has the segment address for the allocated memory of sysinit, confbot.
|
|
; free the confbot area used for config.sys and sysinit itself.
|
|
|
|
|
|
; Now if DOS is supposed to run high, we actually move it into high memory
|
|
; (if HiMem manager is available).
|
|
;
|
|
; There is also this little hack for CPM style DOS calls that needs to
|
|
; be done when A20 is set...
|
|
|
|
cmp runhigh, 0ffh ; are we still waiting to be moved?
|
|
jne @f ; no, our job is over
|
|
call LoadDOSHiOrLo
|
|
@@:
|
|
|
|
cmp runhigh, 0 ; are we running low
|
|
je @f ; yes, no CPM hack needed
|
|
call CPMHack ; make ffff:d0 same as 0:c0
|
|
@@:
|
|
|
|
|
|
; We are now done with CONFIG.SYS processing
|
|
|
|
ConfigDone:
|
|
;; let NTVDM knows that we have done config.sys processing
|
|
xor al, al ;config.sys done
|
|
BOP BOP_NOTIFICATION ;
|
|
call AllocUMB ; allocate remaining UMBs if there are any
|
|
mov cs:[donotshownum],1 ; done with config.sys. do not show line number message.
|
|
mov es,[area]
|
|
|
|
assume es:nothing
|
|
|
|
mov ah,49h ; free allocated memory for command.com
|
|
int 21h
|
|
|
|
test cs:[install_flag],has_installed ; sysinit_base installed?
|
|
jz skip_free_sysinitbase ; no.
|
|
|
|
;set block from the old_area with impossible_owner_size.
|
|
;this will free the unnecessary sysinit_base that had been put in memory to
|
|
;handle install= command.
|
|
|
|
push es
|
|
push bx
|
|
mov es,cs:[old_area]
|
|
mov bx,cs:[impossible_owner_size]
|
|
mov ah,setblock
|
|
int 21h
|
|
mov ax,es
|
|
dec ax
|
|
mov es,ax ;point to arena
|
|
mov es:[arena_owner],8 ;set impossible owner
|
|
mov word ptr es:[arena_name], 'DS' ; System Data
|
|
pop bx
|
|
pop es
|
|
|
|
skip_free_sysinitbase:
|
|
|
|
if noexec
|
|
mov bp,ds ;save command.com segment
|
|
push ds
|
|
pop es
|
|
mov bx,cs
|
|
sub bx,10h ; point to current php
|
|
mov ds,bx
|
|
xor si,si
|
|
mov di,si
|
|
mov cx,80h
|
|
rep movsw ; copy it to new location for shell
|
|
mov word ptr es:[pdb_jfn_pointer + 2],es ; relocate
|
|
mov bx,es
|
|
mov ah,set_current_pdb
|
|
int 21h ; tell dos we moved it
|
|
mov es:[pdb_parent_pid],es ;we are the root
|
|
endif ; noexec
|
|
|
|
push cs
|
|
pop ds ; point DS to sysinitseg
|
|
|
|
assume ds:sysinitseg
|
|
|
|
; set up the parameters for command
|
|
|
|
mov si,offset command_line+1
|
|
|
|
if noexec
|
|
mov di,81h
|
|
else
|
|
push ds
|
|
pop es
|
|
mov di,si
|
|
endif
|
|
|
|
mov cl,-1
|
|
comtranlp: ;find length of command line
|
|
inc cl
|
|
lodsb
|
|
stosb ;copy command line in
|
|
or al,al
|
|
jnz comtranlp
|
|
dec di
|
|
mov al,cr ; cr terminate
|
|
stosb
|
|
|
|
if noexec
|
|
mov es:[80h],cl ; set up header
|
|
mov al,[default_drive]
|
|
mov es:[5ch],al
|
|
else
|
|
mov [command_line],cl ;count
|
|
endif
|
|
|
|
mov dx,offset commnd ;now pointing to file description
|
|
|
|
|
|
if noexec
|
|
mov es,bp ;set load address
|
|
mov bx,100h
|
|
call dfil ;read in command
|
|
jc comerr
|
|
mov ds,bp
|
|
mov dx,80h
|
|
mov ah,set_dma ;set disk tranfer address
|
|
int 21h
|
|
call DOCLI
|
|
mov ss,bp
|
|
mov sp,dx
|
|
call DOSTI
|
|
xor ax,ax ;push a word of zeros
|
|
push ax
|
|
push bp ;set high part of jump address
|
|
mov ax,100h
|
|
push ax ;set low part of jump address
|
|
retf ;crank up command!
|
|
|
|
else ; not noexec
|
|
|
|
; we are going to open the command interpreter and size it as is done in
|
|
; ldfil. the reason we must do this is that sysinit is in free memory. if
|
|
; there is not enough room for the command interpreter,exec will probably
|
|
; overlay our stack and code so when it returns with an error sysinit won't be
|
|
; here to catch it. this code is not perfect (for instance .exe command
|
|
; interpreters are possible) because it does its sizing based on the
|
|
; assumption that the file being loaded is a .com file. it is close enough to
|
|
; correctness to be usable.
|
|
|
|
push dx ; save pointer to name
|
|
|
|
; first, find out where the command interpreter is going to go.
|
|
|
|
mov bx,0ffffh
|
|
mov ah,alloc
|
|
int 21h ;get biggest piece
|
|
mov ah,alloc
|
|
int 21h ; second time gets it
|
|
jc memerrjx ; oooops
|
|
|
|
mov es,ax
|
|
mov ah,dealloc
|
|
int 21h ; give it right back
|
|
mov bp,bx
|
|
|
|
; es:0 points to block,and bp is the size of the block
|
|
; in para.
|
|
|
|
; we will now adjust the size in bp down by the size of sysinit. we
|
|
; need to do this because exec might get upset if some of the exec
|
|
; data in sysinit is overlayed during the exec.
|
|
|
|
mov bx,[memory_size] ; get location of end of memory
|
|
mov ax,cs ; get location of beginning of sysinit
|
|
sub bx,ax ; bx is size of sysinit in para
|
|
add bx,11h ; add the sysinit php
|
|
sub bp,bx ; sub sysinit size from amount of free memory
|
|
jc memerrjx ; if there isn't even this much memory, give up
|
|
|
|
mov ax,(open shl 8) ;open the file being execed
|
|
stc ;in case of int 24
|
|
int 21h
|
|
jc comerr ; ooops
|
|
|
|
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 comerr
|
|
; convert size in dx:ax to para in ax
|
|
add ax,15 ; round up size for conversion to para
|
|
adc dx,0
|
|
call off_to_para
|
|
mov cl,12
|
|
shl dx,cl ; low nibble of dx to high nibble
|
|
or ax,dx ; ax is now # of para for file
|
|
add ax,10h ; 100h byte php
|
|
cmp ax,bp ; will command fit in available mem?
|
|
jb okld ; jump if yes.
|
|
memerrjx:
|
|
jmp mem_err
|
|
|
|
okld:
|
|
mov ah,close
|
|
int 21h ; close file
|
|
|
|
pop dx ; recover pointer to name
|
|
push cs ; point es to sysinitseg
|
|
pop es
|
|
mov bx,offset comexe ; point to exec block
|
|
mov word ptr [bx.exec0_com_line+2],cs ; set segments
|
|
mov word ptr [bx.exec0_5c_fcb+2],cs
|
|
mov word ptr [bx.exec0_6c_fcb+2],cs
|
|
xor ax,ax ;load and go
|
|
mov ah,exec
|
|
stc ;in case of int 24
|
|
int 21h ;go start up command
|
|
endif
|
|
|
|
; note fall through if exec returns (an error)
|
|
|
|
comerr:
|
|
mov dx,offset badcom ;want to print command error
|
|
extrn badfil:near
|
|
call badfil
|
|
public stall
|
|
stall: SVC SVC_DEMEXITVDM ; Will Kill The VDM
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
; procedure : AllocFreeMem
|
|
;
|
|
; Allocate Max memory from DOS to find out where to load DOS.
|
|
; DOS is at temporary location when this call is being made
|
|
;
|
|
; Inputs : None
|
|
; Outputs: The biggest chunk of memory is allocated (all mem at init time)
|
|
; [area] & [memhi] set to the para value of the start of the
|
|
; free memory.
|
|
;
|
|
; Uses : AX, BX
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
AllocFreeMem proc near
|
|
|
|
assume es:nothing, ds:nothing
|
|
mov bx,0ffffh
|
|
mov ah,alloc
|
|
int 21h ;first time fails
|
|
mov ah,alloc
|
|
int 21h ;second time gets it
|
|
mov [area],ax
|
|
mov [memhi],ax ; memhi:memlo now points to
|
|
ret
|
|
; start of free memory
|
|
AllocFreeMem endp
|
|
|
|
; start M000
|
|
include msbio.cl6
|
|
; end M000
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : LoadDOSHiOrLo
|
|
;
|
|
; Tries to move DOS into HMA. If it fails then loads
|
|
; DOS into Low memory.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
LoadDOSHiOrLo proc near
|
|
call TryToMovDOSHi ; Try moving it into HMA (M024)
|
|
jc LdngLo ; If that don't work...
|
|
ret
|
|
LdngLo:
|
|
push cs
|
|
pop ds
|
|
mov ah, 9
|
|
mov dx, offset DOSLOMSG ; inform user that we are
|
|
int 21h ; loading low
|
|
|
|
; actually move the dos, and reinitialize it.
|
|
|
|
mov bx, 1 ; M012
|
|
; use int 21 alloc for mem
|
|
call MovDOSLo
|
|
mov es,[current_dos_location] ; give dos its temporary loc.
|
|
xor ax,ax ; ax = 00 ---> install stub
|
|
call cs:dword ptr [dos_segreinit] ; call dos segreinit
|
|
|
|
mov runhigh, 0 ; mark that we are running lo
|
|
ret
|
|
LoadDOSHiOrLo endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : TryToMovDOSHi
|
|
;
|
|
; This tries to move DOS into HMA.
|
|
; Returns CY if it failed.
|
|
; If it succeeds returns with carry cleared.
|
|
;
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
public TryToMovDOSHi
|
|
|
|
TryToMovDOSHi proc near
|
|
call MovDOSHi
|
|
jc ttldhx
|
|
|
|
|
|
mov es,[current_dos_location] ; give dos its temporary loc.
|
|
|
|
xor ax,ax ; ax = 00 ---> install stub
|
|
call cs:dword ptr [dos_segreinit] ; call dos segreinit
|
|
|
|
mov runhigh, 1
|
|
clc
|
|
ttldhx:
|
|
ret
|
|
TryToMovDOSHi endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : MovDOSHi
|
|
;
|
|
; Tries to allocate HMA and Move DOS/BIOS code into HMA
|
|
;
|
|
; Returns : CY if it failed
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
MovDOSHi proc near
|
|
call AllocHMA
|
|
jc mdhx ; did we get HMA?
|
|
mov ax, 0ffffh ; yes, HMA seg = 0ffffh
|
|
mov es, ax
|
|
|
|
; actually move the BIOS and DOS
|
|
|
|
call MovBIOS ; First move BIOS into HMA
|
|
|
|
; ES:DI points to free HMA after BIOS
|
|
|
|
mov cx, hi_doscod_size ; pass the code size of DOS
|
|
; when it is in HMA
|
|
call MovDOS ; and move it
|
|
|
|
; ES:DI points to free HMA after DOS
|
|
|
|
call SaveFreeHMAPtr ; Save the Free HMA ptr
|
|
clc
|
|
mdhx:
|
|
ret
|
|
MovDOSHi endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : MovDOSLo
|
|
;
|
|
; Allocates memory from DOS and moves BIOS/DOS code into it
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
|
|
MovDOSLo proc near
|
|
call AllocMemForDOS ;
|
|
mov es, ax ; pass the segment to MovBIOS
|
|
call MovBIOS
|
|
;
|
|
;------ ES:DI points memory immediately after BIOS
|
|
;
|
|
mov cx, lo_doscod_size ; DOS code size when loaded
|
|
; low
|
|
call MovDOS
|
|
ret
|
|
MovDOSLo endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : MovBIOS
|
|
;
|
|
; Moves BIOS code into requested segment
|
|
;
|
|
; In : ES - segment to which BIOS is to be moved
|
|
; ( it moves always into offset BCode_Start)
|
|
;
|
|
; Out : ES:DI - pointer to memory immediately after BIOS
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
|
|
MovBIOS proc near
|
|
mov ds, temp_bcode_seg ; current BIOS code seg
|
|
mov si, offset BCode_Start
|
|
mov di, si
|
|
mov cx, offset BCode_End
|
|
sub cx, si ; size of BIOS
|
|
shr cx, 1 ; Both the labels are para
|
|
; aligned
|
|
rep movsw
|
|
push es
|
|
push di ; save end of BIOS
|
|
mov ax, es
|
|
mov BCodeSeg, ax ; save it for later use
|
|
call [seg_reinit_ptr] ; far call to seg_reinit (M022)
|
|
pop di
|
|
pop es ; get back end of BIOS
|
|
ret
|
|
MovBIOS endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : MovDOS
|
|
;
|
|
; Moves DOS code into requested area
|
|
;
|
|
; In : ES:DI - pointer to memory where DOS is to be moved
|
|
; CX - size of DOS code to be moved
|
|
;
|
|
; Out : ES:DI - pointer to memory immediately after DOS
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
|
|
MovDOS proc near
|
|
push es
|
|
push di
|
|
lds si, dos_temp_location ; current location of DOS
|
|
rep movsb
|
|
pop bx ; get back offset into which
|
|
; DOS was moved
|
|
mov ax, dosinit ; get the offset at which DOS
|
|
; wants to run
|
|
sub ax, bx
|
|
call off_to_para
|
|
pop bx ; get the segment at which
|
|
; we moved DOS into
|
|
sub bx, ax ; Adjust segment
|
|
mov current_dos_location, bx ; and save it
|
|
ret
|
|
MovDOS endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : AllocMemForDOS
|
|
;
|
|
; Allocate memory for DOS/BIOS code from DOS !!!
|
|
;
|
|
; Out : AX - seg of allocated memoryblock
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
|
|
AllocMemForDOS proc near
|
|
mov ax, offset BCode_end
|
|
sub ax, offset BCode_start ; BIOS code size
|
|
add ax, lo_doscod_size ; + DOS code size
|
|
add ax, 15
|
|
call off_to_para ; convert to para
|
|
or bx, bx ; M012
|
|
; can we use int 21 for alloc
|
|
mov bx, ax
|
|
jz update_arena ; M012
|
|
mov ah, 48h ; request DOS
|
|
int 21h
|
|
jc FatalErr ; IF ERR WE ARE HOSED
|
|
sub ax, 3 ; Take care ORG 30h of
|
|
; BIOS code
|
|
mov es, ax
|
|
mov word ptr es:[20h+arena_owner], 08h ; mark it as system
|
|
mov word ptr es:[20h+arena_name], 'CS' ; code area
|
|
ret
|
|
|
|
;
|
|
; M012 : BEGIN
|
|
;
|
|
update_arena:
|
|
push ds
|
|
push di
|
|
push cx
|
|
push dx
|
|
lds di, dosinfo ; get ptr to DOS var
|
|
dec di
|
|
dec di ; Arena head is immediately
|
|
; before sysvar
|
|
mov es, ds:[di] ; es = arena head
|
|
mov cx, es:[arena_size] ; cx = total low mem size
|
|
cmp cx, bx ; is it sufficient ?
|
|
jb FatalErr ; no, fatal error
|
|
mov dl, es:[arena_signature]
|
|
mov ax, es
|
|
add ax, bx ; ax = new arena head
|
|
mov ds:[di], ax ; store it in DOS data area
|
|
mov ds, ax
|
|
mov byte ptr ds:[arena_signature], dl ; type of arena
|
|
mov word ptr ds:[arena_owner], 0 ; free
|
|
sub cx, bx ; size of the new block
|
|
mov word ptr ds:[arena_size], cx ; store it in the arena
|
|
mov ax, es ; return seg to the caller
|
|
sub ax, 3 ; Take care ORG 30h of
|
|
; BIOS code
|
|
pop dx
|
|
pop cx
|
|
pop di
|
|
pop ds
|
|
ret
|
|
;
|
|
; M012 : END
|
|
;
|
|
FatalErr:
|
|
push cs
|
|
pop ds
|
|
mov dx, offset FEMsg
|
|
mov ah, 9h
|
|
int 21h
|
|
cli
|
|
hlt
|
|
AllocMemForDOS endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : AllocHMA
|
|
;
|
|
; grab_the_hma tries to enable a20 and make sure there is memory
|
|
; up there. If it gets any sort of error, it will return with
|
|
; carry set so that we can resort to running low.
|
|
;
|
|
; It also returns ES: -> 0ffffh if it returns success
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
AllocHMA proc near
|
|
assume ds:nothing,es:nothing
|
|
;
|
|
; cas note: The pre-286 check is no longer needed here since the
|
|
; presence of XMS is sufficient. However, this code hasn't
|
|
; been deleted because it can be recycled for skipping the
|
|
; extra pass of CONFIG.SYS and assuming we're running low
|
|
; in the case of a pre-286.
|
|
|
|
;
|
|
;; see if we're running on a pre-286. If not, force low.
|
|
;
|
|
; xor ax,ax
|
|
; pushf ; save flags (like int)
|
|
; push ax
|
|
; popf
|
|
; pushf
|
|
; pop ax
|
|
; popf ; restore original flags (like int)
|
|
; and ax,0f000h
|
|
; cmp ax,0f000h ; 8088/8086?
|
|
; jz grab_hma_error
|
|
;
|
|
push ds
|
|
mov ax,Bios_Data
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
|
|
call IsXMSLoaded
|
|
jnz grabhma_error
|
|
|
|
mov ax,4310h
|
|
int 2fh ; get the vector into es:bx
|
|
mov word ptr xms,bx
|
|
mov word ptr xms+2,es
|
|
|
|
mov ah,1 ; request HMA
|
|
mov dx,0ffffh
|
|
call xms
|
|
dec ax
|
|
jz @f ; error if not able to allocate HMA
|
|
|
|
;
|
|
;------ Himem may be lying because it has allocated mem for int 15
|
|
;
|
|
mov ah, 88h
|
|
int 15h
|
|
cmp ax, 64 ; less than 64 K of hma ?
|
|
jb grabhma_error
|
|
|
|
@@: mov ah,5 ; localenableA20
|
|
call xms
|
|
dec ax
|
|
jnz grabhma_error ; error if couldn't enable A20
|
|
|
|
mov ax,0ffffh
|
|
mov es,ax
|
|
mov es:word ptr 10h,1234h ; see if we can really read/write there
|
|
cmp es:word ptr 10h,1234h
|
|
jnz grabhma_error ; don't try to load there if XMS lied
|
|
|
|
clc
|
|
pop ds
|
|
ret
|
|
|
|
grabhma_error:
|
|
stc
|
|
pop ds
|
|
assume ds:nothing
|
|
ret
|
|
|
|
AllocHMA endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : IsXMSLoaded
|
|
;
|
|
; Checks whether a XMS driver is loaded
|
|
;
|
|
; Returns : Z flag set if XMS driver loaded
|
|
; Z flag reset if no XMS drivers are present
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
public IsXMSLoaded
|
|
|
|
IsXMSLoaded proc near
|
|
mov ax,4300h
|
|
int 2fh
|
|
cmp al,80h ; XMS installed?
|
|
ret
|
|
IsXMSLoaded endp
|
|
|
|
;
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
; procedure : FTryToMovDOSHi
|
|
;
|
|
; Called from HMA suballoc calls
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
;
|
|
|
|
public FTryToMovDOSHi
|
|
FTryToMovDOSHi proc far
|
|
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push si
|
|
push di
|
|
push ds
|
|
push es
|
|
cmp runhigh, 0ffh
|
|
jne @f
|
|
|
|
call TryToMovDOSHi
|
|
@@:
|
|
pop es
|
|
pop ds
|
|
pop di
|
|
pop si
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
|
|
ret
|
|
FTryToMovDOSHi endp
|
|
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : SaveFreeHMAPtr
|
|
;
|
|
; Save the Free HMA pointer in BIOS variable for later use.
|
|
; (INT 2f ax==4a01 call returns pointer to free HMA)
|
|
; Normalizes the pointer to ffff:xxxx format and stores only
|
|
; the offset.
|
|
;
|
|
; Inputs : ES:DI - pointer to free HMA
|
|
; Output : FreeHMAPtr in BIOS data segment updated
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
SaveFreeHMAPtr proc near
|
|
mov bx, es
|
|
mov ax, 0ffffh ; HMA segment
|
|
sub ax, bx
|
|
add di, 15 ; para round
|
|
and di, 0fff0h
|
|
mov cl, 4
|
|
shl ax, cl
|
|
sub di, ax
|
|
push ds
|
|
mov ax, Bios_Data
|
|
mov ds, ax
|
|
assume ds:Bios_Data
|
|
mov FreeHMAPtr, di
|
|
mov inHMA, 0ffh
|
|
pop ds
|
|
assume ds:nothing
|
|
ret
|
|
SaveFreeHMAPtr endp
|
|
;
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : CPMHack
|
|
;
|
|
; Copies the code from 0:c0 into ffff:0d0h
|
|
; for CPM comatibilty
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
CPMHack proc near
|
|
push ds
|
|
mov cx, 0ffffH
|
|
mov es, cx ; ES = FFFF
|
|
xor cx, cx
|
|
mov ds, cx ; DS = 0
|
|
mov si, 0c0h
|
|
mov di, 0d0h
|
|
mov cx, 5
|
|
cld
|
|
rep movsb ; move 5 bytes from 0:C0 to FFFF:D0
|
|
pop ds
|
|
ret
|
|
CPMHack endp
|
|
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
; procedure : off_to_para
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
|
|
off_to_para proc near
|
|
shr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
ret
|
|
off_to_para endp
|
|
|
|
|
|
;** TempCDS - Create (Temporary?) CDS
|
|
;
|
|
; ENTRY ?? BUGBUG
|
|
; (DS) = SysInitSeg
|
|
; EXIT ?? BUGBUG
|
|
; USES ?? BUGBUG
|
|
|
|
public tempcds
|
|
Procedure TempCDS
|
|
|
|
assume ds:sysinitseg
|
|
les di,dosinfo
|
|
mov cl,byte ptr es:[di.sysi_numio]
|
|
xor ch,ch ; (cx) = # of block devices
|
|
mov es:[di.sysi_ncds],cl ; one CDS per device
|
|
mov al,cl
|
|
mov ah,size curdir_list
|
|
mul ah ; (ax) = byte size for those CDSs
|
|
call pararound ; (ax) = paragraph size for CDSs
|
|
mov si,[confbot]
|
|
; BUGBUG - we don't update confbot - won't someone else use it?
|
|
sub si,ax
|
|
mov [alloclim],si ; can't alloc past here!
|
|
mov word ptr es:[di.sysi_cds + 2],si
|
|
mov ax,si
|
|
mov word ptr es:[di.sysi_cds],0 ; set address of CDS list
|
|
assume ds:nothing
|
|
mov es,ax
|
|
xor di,di ; (es:di) = address of 1st CDS
|
|
|
|
|
|
|
|
;* Initialize our temporary CDSs.
|
|
;
|
|
; (cx) = count of CDSs left to process
|
|
; (si) = 0 based drive being processed
|
|
; (es:di) = address of next CDS
|
|
|
|
fooset:
|
|
xor dx,dx ; indicator to stop removable checks
|
|
foogo:
|
|
mov ax,word ptr DirStrng
|
|
.errnz CURDIR_TEXT ; setup the root as the curdir
|
|
stosw
|
|
mov ax,word ptr DirStrng+2
|
|
stosw
|
|
xor ax,ax
|
|
push cx
|
|
.errnz CURDIR_FLAGS - CURDIR_TEXT - size CURDIR_TEXT
|
|
mov cx,curdir_flags - 4
|
|
rep stosb ; zero out rest of CURDIR_TEXTs
|
|
|
|
; Here es:di points to CURDIR_FLAGS
|
|
|
|
or dx,dx ; have we found one fixed drive?
|
|
jnz fixed_drv2 ; NZ -> yes dont do IOCTL check
|
|
|
|
cmp byte ptr DirStrng, 'B'
|
|
jbe not_fixed ; 'A' and 'B' are always removable
|
|
|
|
mov bl,byte ptr DirStrng
|
|
sub bl,'A'
|
|
inc bl ; C is 3
|
|
mov ax,4408h
|
|
int 21h ; Is drive removable
|
|
jc fixed_drv ; Could'nt find means NET hence fixed
|
|
or ax,ax
|
|
jnz fixed_drv
|
|
|
|
not_fixed:
|
|
mov ax,CURDIR_LOCAL OR CURDIR_INUSE
|
|
jmp short fill_in
|
|
|
|
|
|
fixed_drv:
|
|
inc dx
|
|
fixed_drv2:
|
|
mov ax,CURDIR_LOCAL OR CURDIR_INUSE OR CURDIR_NT_FIX
|
|
|
|
fill_in:
|
|
|
|
FOLLOWS CURDIR_FLAGS,CURDIR_TEXT,2
|
|
stosw ; Save Flags
|
|
|
|
mov ax,2
|
|
FOLLOWS CURDIR_END,CURDIR_FLAGS,2
|
|
stosw ; Save CURDIR_END
|
|
|
|
inc byte ptr DirStrng
|
|
pop cx
|
|
loop foogo
|
|
mov byte ptr DirStrng,"A"
|
|
ret
|
|
|
|
EndProc TempCDS
|
|
|
|
|
|
;** EndFile - Build DOS structures
|
|
;
|
|
; This procedure is called after the config.sys has been processed and
|
|
; installable device drivers have been loaded (but before "install="
|
|
; programs are loaded) to create the dos structures such as SFTs, buffers,
|
|
; FCBs, CDSs, etc. It also loads the sysinit_base module in low memory
|
|
; to allow for the safe EXECing of "install=" programs. All memory
|
|
; above these structures is deallocated back to DOS.
|
|
;
|
|
; ENTRY ?? BUGBUG
|
|
; EXIT ?? BUGBUG
|
|
; USES ?? BUGBUG
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; allocate files
|
|
;------------------------------------------------------------------------------
|
|
|
|
endfile:
|
|
|
|
; we are now setting up final cdss,buffers,files,fcss strings etc. we no
|
|
; longer need the space taken by the temp stuff below confbot,so set alloclim
|
|
; to confbot.
|
|
|
|
; if this procedure has been called to take care of install= command,
|
|
; then we have to save es,si registers.
|
|
|
|
push ds
|
|
mov ax,Bios_Data
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
|
|
cmp multrk_flag,multrk_off1 ;=0,multrack= command entered?
|
|
jne multrk_flag_done
|
|
or multrk_flag,multrk_on ; default will be on.
|
|
multrk_flag_done:
|
|
|
|
pop ds
|
|
assume ds:nothing
|
|
|
|
mov ax,[confbot]
|
|
mov [alloclim],ax
|
|
|
|
push cs
|
|
pop ds
|
|
extrn round:near
|
|
call round
|
|
mov al,[files]
|
|
sub al,5
|
|
jbe dofcbs
|
|
|
|
push ax
|
|
mov al,devmark_files
|
|
call setdevmark ; set devmark for sfts (files)
|
|
pop ax
|
|
xor ah,ah ; do not use cbw instruction!!!!!
|
|
; it does sign extend.
|
|
mov bx,[memlo]
|
|
mov dx,[memhi]
|
|
lds di,dosinfo ;get pointer to dos data
|
|
lds di,[di+sysi_sft] ;ds:bp points to sft
|
|
mov word ptr [di+sflink],bx
|
|
mov word ptr [di+sflink+2],dx ;set pointer to new sft
|
|
|
|
push cs
|
|
pop ds
|
|
|
|
les di,dword ptr [memlo] ;point to new sft
|
|
mov word ptr es:[di+sflink],-1
|
|
mov es:[di+sfcount],ax
|
|
mov bl,size sf_entry
|
|
mul bl ;ax = number of bytes to clear
|
|
mov cx,ax
|
|
add [memlo],ax ;allocate memory
|
|
mov ax,6
|
|
add [memlo],ax ;remember the header too
|
|
or [setdevmarkflag],for_devmark
|
|
call round ; check for mem error before the stosb
|
|
add di,ax
|
|
xor ax,ax
|
|
rep stosb ;clean out the stuff
|
|
|
|
;------------------------------------------------------------------------------
|
|
; allocate fcbs
|
|
;------------------------------------------------------------------------------
|
|
|
|
dofcbs:
|
|
push cs
|
|
pop ds
|
|
call round
|
|
mov al,devmark_fcbs ;='x'
|
|
call setdevmark
|
|
mov al,[fcbs]
|
|
xor ah,ah ; do not use cbw instruction!!!!!
|
|
; it does sign extend.
|
|
mov bx,[memlo]
|
|
mov dx,[memhi]
|
|
lds di,dosinfo ;get pointer to dos data
|
|
assume ds:nothing
|
|
|
|
mov word ptr [di+sysi_fcb],bx
|
|
mov word ptr [di+sysi_fcb+2],dx ;set pointer to new table
|
|
mov bl,cs:keep
|
|
xor bh,bh
|
|
mov [di+sysi_keep],bx
|
|
|
|
push cs
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
les di,dword ptr [memlo] ;point to new table
|
|
mov word ptr es:[di+sflink],-1
|
|
mov es:[di+sfcount],ax
|
|
mov bl,size sf_entry
|
|
mov cx,ax
|
|
mul bl ;ax = number of bytes to clear
|
|
add [memlo],ax ;allocate memory
|
|
mov ax,size sf-2
|
|
add [memlo],ax ;remember the header too
|
|
or [setdevmarkflag],for_devmark
|
|
call round ; check for mem error before the stosb
|
|
add di,ax ;skip over header
|
|
mov al,"A"
|
|
fillloop:
|
|
push cx ; save count
|
|
mov cx,size sf_entry ; number of bytes to fill
|
|
cld
|
|
rep stosb ; filled
|
|
|
|
mov word ptr es:[di-(size sf_entry)+sf_ref_count],0
|
|
mov word ptr es:[di-(size sf_entry)+sf_position],0
|
|
mov word ptr es:[di-(size sf_entry)+sf_position+2],0
|
|
|
|
pop cx
|
|
loop fillloop
|
|
|
|
;------------------------------------------------------------------------------
|
|
; allocate cdss
|
|
;------------------------------------------------------------------------------
|
|
buf1:
|
|
call round
|
|
|
|
push ax
|
|
mov ax,devmark_cds ;='l'
|
|
call setdevmark
|
|
pop ax
|
|
|
|
les di,dosinfo
|
|
mov cl,byte ptr es:[di.sysi_numio]
|
|
|
|
;NTVDM Ignore the lastdrive command. There exists only one cds for all
|
|
; network drives and dos has already set sysi_numio to be
|
|
; num real drives + 1 for all network drives 17-Aug-1992 Jonle
|
|
;
|
|
; cmp cl,[num_cds]
|
|
; jae gotncds ; user setting must be at least numio
|
|
; mov cl,[num_cds]
|
|
;gotncds:
|
|
;
|
|
xor ch,ch
|
|
mov es:[di.sysi_ncds],cl
|
|
mov ax,[memhi]
|
|
mov word ptr es:[di.sysi_cds + 2],ax
|
|
mov ax,[memlo]
|
|
mov word ptr es:[di.sysi_cds],ax
|
|
mov al,cl
|
|
mov ah,size curdir_list
|
|
mul ah
|
|
call pararound
|
|
add [memhi],ax
|
|
|
|
or [setdevmarkflag],for_devmark
|
|
call round ; check for mem error before initializing
|
|
assume ds:nothing
|
|
les di,es:[di.sysi_cds]
|
|
call fooset
|
|
|
|
;------------------------------------------------------------------------------
|
|
; allocate space for internal stack
|
|
;------------------------------------------------------------------------------
|
|
|
|
if stacksw
|
|
|
|
push cs
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
doinstallstack:
|
|
mov ax,[stack_count] ; stack_count = 0?
|
|
or ax,ax ;then,stack size must be 0 too.
|
|
jz skipstack ;don't install stack.
|
|
|
|
; dynamic relocation of stack code.
|
|
|
|
call round ;[memhi] = seg. for stack code
|
|
;[memlo] = 0
|
|
|
|
; set devmark block into memory for mem command
|
|
; devmark_id = 's' for stack
|
|
|
|
mov al,devmark_stk ;='s'
|
|
call setdevmark
|
|
|
|
mov ax,[memhi]
|
|
mov es,ax ;es -> seg. the stack code is going to move.
|
|
assume es:nothing
|
|
push cs
|
|
pop ds
|
|
xor si,si ;!!we know that stack code is at the beginning of sysinit.
|
|
xor di,di
|
|
mov cx,offset endstackcode
|
|
mov [memlo],cx
|
|
call round ;have enough space for relocation?
|
|
rep movsb
|
|
|
|
push ds ; stick the location of the NextStack entry
|
|
mov ax,Bios_Data ; into the Win386 Instance Data tables
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
mov word ptr NextStack,offset nextentry
|
|
mov word ptr NextStack+2,es
|
|
|
|
mov ax,[memlo]
|
|
mov word ptr [stack_addr],ax ;set for stack area initialization
|
|
mov word ptr IT_StackLoc,ax ; pass it as Instance Data, too
|
|
mov ax,[memhi] ;this will be used by stack_init routine.
|
|
mov word ptr [stack_addr+2],ax
|
|
mov word ptr IT_StackLoc+2,ax
|
|
|
|
; space for internal stack area = stack_count(entrysize + stack_size)
|
|
|
|
mov ax,entrysize
|
|
add ax,[stack_size]
|
|
mul [stack_count]
|
|
|
|
mov IT_StackSize,ax ; pass through to Instance Tables
|
|
|
|
pop ds ; no more need to access Instance Table
|
|
assume ds:nothing
|
|
|
|
call pararound ; convert size to pargraphs
|
|
add [memhi],ax
|
|
or [setdevmarkflag],for_devmark ;to set the devmark_size for stack by round routine.
|
|
call round ; check for memory error before
|
|
; continuing
|
|
call stackinit ; initialize hardware stack. cs=ds=sysinitseg,es=relocated stack code & data
|
|
|
|
skipstack:
|
|
endif
|
|
|
|
push cs
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
mov al,[files]
|
|
xor ah,ah ; do not use cbw instruction!!!!!
|
|
; it does sign extend.
|
|
mov cx,ax
|
|
xor bx,bx ;close standard input
|
|
mov ah,close
|
|
int 21h
|
|
;; go directly to the handle table; donot close any invalid handles
|
|
push si
|
|
mov ah, Get_Current_PDB ;
|
|
int 21h
|
|
les si, es:[pdb_jfn_pointer]
|
|
mov bx, 2
|
|
rcclloop:
|
|
cmp byte ptr es:[bx][si], 0FFh ;skip invalid handle
|
|
je skip_the_handle
|
|
mov ah,close ; need output so we can print message
|
|
int 21h ; in case we can't get new one open.
|
|
skip_the_handle:
|
|
inc bx
|
|
loop rcclloop
|
|
pop si
|
|
|
|
mov dx,offset condev
|
|
mov al,2
|
|
mov ah,open ;open con for read/write
|
|
stc ; set for possible int 24
|
|
int 21h
|
|
jnc goaux
|
|
call badfil
|
|
jmp short goaux2
|
|
|
|
goaux: push ax
|
|
mov bx,1 ;close standard output
|
|
mov ah,close
|
|
int 21h
|
|
pop ax
|
|
|
|
mov bx,ax ;new device handle
|
|
mov ah,xdup
|
|
int 21h ;dup to 1,stdout
|
|
mov ah,xdup
|
|
int 21h ;dup to 2,stderr
|
|
|
|
goaux2: mov dx,offset auxdev
|
|
mov al,2 ;read/write access
|
|
extrn open_dev:near
|
|
call open_dev
|
|
|
|
mov dx,offset prndev
|
|
mov al,1 ;write only
|
|
call open_dev
|
|
|
|
;global rearm command for shared interrupt devices attached in the system;
|
|
;shared interrupt attachment has some problem when it issues interrupt
|
|
;during a warm reboot. once the interrupt is presented by the attachment,
|
|
;no further interrupts on that level will be presented until a global rearm
|
|
;is issued. by the request of the system architecture group, msbio will
|
|
;issue a global rearm after every device driver is loaded.
|
|
;to issue a global rearm: ;for pc1,xt,palace
|
|
;
|
|
; out 02f2h,xx ; interrupt level 2
|
|
; out 02f3h,xx ; interrupt level 3
|
|
; out 02f4h,xx ; interrupt level 4
|
|
; out 02f5h,xx ; interrupt level 5
|
|
; out 02f6h,xx ; interrupt level 6
|
|
; out 02f7h,xx ; interrupt level 7
|
|
;
|
|
; for pc at,in addition to the above commands,
|
|
; need to handle the secondary interrupt handler
|
|
;
|
|
; out 06f2h,xx ; interrupt level 10
|
|
; out 06f3h,xx ; interrupt level 11
|
|
; out 06f4h,xx ; interrupt level 12
|
|
; out 06f6h,xx ; interrupt level 14
|
|
; out 06f7h,xx ; interrupt level 15
|
|
;
|
|
; for round-up machine
|
|
;
|
|
; none.
|
|
|
|
; where xx stands for any value.
|
|
;
|
|
; for your information,after naples level machine,the system service bios
|
|
; call (int 15h),function ah=0c0h returns the system configuration parameters
|
|
;
|
|
;
|
|
; Sudeepb 31-Dec-1991 Commented out for NT
|
|
if 0
|
|
push ax
|
|
push bx
|
|
push dx
|
|
push es
|
|
|
|
mov al,0ffh ;reset h/w by writing to port
|
|
mov dx,2f2h ;get starting address
|
|
out dx,al ; out 02f2h,0ffh
|
|
inc dx
|
|
out dx,al ; out 02f3h,0ffh
|
|
inc dx
|
|
out dx,al ; out 02f4h,0ffh
|
|
inc dx
|
|
out dx,al ; out 02f5h,0ffh
|
|
inc dx
|
|
out dx,al ; out 02f6h,0ffh
|
|
inc dx
|
|
out dx,al ; out 02f7h,0ffh
|
|
|
|
;sb secondary global rearm
|
|
|
|
mov ax,0f000h ;get machine type
|
|
mov es,ax
|
|
cmp byte ptr es:[0fffeh],0fch ;q:is it a at type machine
|
|
je startrearm ; *if at no need to check
|
|
|
|
mov ah,0c0h ;get system configuration
|
|
int 15h ; *
|
|
jc finishrearm ; *jmp if old rom
|
|
|
|
; test feature byte for secondary interrupt controller
|
|
|
|
test es:[bx.bios_sd_featurebyte1],scndintcontroller
|
|
je finishrearm ;jmp if it is there
|
|
|
|
startrearm:
|
|
mov al,0ffh ;write any pattern to port
|
|
mov dx,6f2h ;get starting address
|
|
out dx,al ;out 06f2h,0ffh
|
|
inc dx ;bump address
|
|
out dx,al ;out 06f3h,0ffh
|
|
inc dx ;bump address
|
|
out dx,al ;out 06f4h,0ffh
|
|
inc dx ;bump address
|
|
inc dx ;bump address
|
|
out dx,al ;out 06f6h,0ffh
|
|
inc dx ;bump address
|
|
out dx,al ;out 06f7h,0ffh
|
|
|
|
finishrearm:
|
|
pop es
|
|
pop dx
|
|
pop bx
|
|
pop ax
|
|
endif
|
|
|
|
; global rearm end *******************
|
|
|
|
;------------------------------------------------------------------------------
|
|
; allocate sysinit_base for install= command
|
|
;------------------------------------------------------------------------------
|
|
; sysinit_base allocation.
|
|
; check if endfile has been called to handle install= command.
|
|
|
|
set_sysinit_base:
|
|
|
|
;--------------------------------------------------------------------------
|
|
;sysinit_base will be established in the secure area of
|
|
;lower memory when it handles the first install= command.
|
|
;sysinit_base is the place where the actual exec function will be called and
|
|
;will check sysinit module in high memory if it is damaged by the application
|
|
;program. if sysinit module has been broken,then "memory error..." message
|
|
;is displayed by sysinit_base.
|
|
;--------------------------------------------------------------------------
|
|
|
|
push ax ; set devmark for mem command
|
|
mov ax,[memhi]
|
|
sub ax,[area]
|
|
mov [impossible_owner_size],ax ;remember the size in case.
|
|
mov al,devmark_inst
|
|
call setdevmark
|
|
pop ax
|
|
|
|
mov di,[memhi]
|
|
mov es,di
|
|
assume es:nothing
|
|
mov word ptr [sysinit_base_ptr+2],di ; save this entry for the next use.
|
|
xor di,di
|
|
mov word ptr [sysinit_base_ptr],di ; es:di -> destination.
|
|
mov si,offset sysinit_base ;ds:si -> source code to be relocated.
|
|
mov cx,(offset end_sysinit_base) - (offset sysinit_base)
|
|
add [memlo],cx
|
|
or cs:[setdevmarkflag],for_devmark
|
|
call round ; check mem error. also,readjust memhi for the next use.
|
|
rep movsb ; reallocate it.
|
|
|
|
mov word ptr [sysinit_ptr],offset sysinitptr ; returing address from
|
|
mov word ptr [sysinit_ptr+2],cs ; sysinit_base back to sysinit.
|
|
or [install_flag],has_installed ; set the flag.
|
|
|
|
;------------------------------------------------------------------------------
|
|
; free the rest of the memory from memhi to confbot. still from confbot to
|
|
; the top of the memory will be allocated for sysinit and config.sys if
|
|
; have_install_cmd.
|
|
;------------------------------------------------------------------------------
|
|
|
|
call round
|
|
mov bx,[memhi]
|
|
mov ax,[area]
|
|
mov [old_area],ax ; save [area]
|
|
mov es,ax ;calc what we needed
|
|
sub bx,ax
|
|
mov ah,setblock
|
|
int 21h ;give the rest back
|
|
|
|
push es
|
|
mov ax,es
|
|
dec ax
|
|
mov es,ax ;point to arena
|
|
mov es:[arena_owner],8 ;set impossible owner
|
|
mov word ptr es:[arena_name], 'DS' ; System Data
|
|
pop es
|
|
|
|
mov bx,0ffffh
|
|
mov ah,alloc
|
|
int 21h
|
|
mov ah,alloc
|
|
int 21h ; allocate the rest of the memory
|
|
|
|
mov [memhi],ax ; start of the allocated memory
|
|
mov [memlo],0 ; to be used next.
|
|
|
|
;;;; at this moment,memory from [memhi]:0 to top-of-the memory is
|
|
;;;; allocated.
|
|
;;;; to protect sysinit,confbot module (from confbot (or =alloclim at
|
|
;;;; this time) to the top-of-the memory),here we are going to
|
|
;;;; 1). "setblock" from memhi to confbot.
|
|
;;;; 2). "alloc" from confbot to the top of the memory.
|
|
;;;; 3). "free alloc memory" from memhi to confbot.
|
|
|
|
;memory allocation for sysinit,confbot module.
|
|
|
|
mov es,ax
|
|
mov bx,[confbot]
|
|
sub bx,ax ; confbot - memhi
|
|
dec bx ; make a room for the memory block id.
|
|
dec bx ; make sure!!!.
|
|
mov ah,setblock
|
|
int 21h ; this will free (confbot to top of memory)
|
|
mov bx,0ffffh
|
|
mov ah,alloc
|
|
int 21h
|
|
mov ah,alloc
|
|
int 21h ; allocate (confbot to top of memory)
|
|
mov [area],ax ; save allocated memory segment.
|
|
; need this to free this area for command.com.
|
|
mov es,[memhi]
|
|
mov ah,49h ; free allocated memory.
|
|
int 21h ; free (memhi to confbot(=area))
|
|
|
|
endfile_ret:
|
|
ret
|
|
|
|
; End of "EndFile" DOS structure configuration.
|
|
|
|
|
|
;-------------------------------------------------------------------------
|
|
; Do_Install_Exec
|
|
;
|
|
; This procedure is used to EXEC a program being loaded via the
|
|
; "install=" mechanism in config.sys. It does this by setting up
|
|
; the parameters, and then jumping to sysinit_base, which has been
|
|
; setup in low memory. When complete, sysinit_base will jump back
|
|
; up to this procedure (if sysinit remains uncorrupted by the installed
|
|
; program).
|
|
|
|
do_install_exec proc near ; now,handles install= command.
|
|
|
|
push si ; save si for config.sys again.
|
|
|
|
; we are going to call load/exec function.
|
|
; set es:bx to the parameter block here;;;;;;;
|
|
; set ds:dx to the asciiz string. remember that we already has 0
|
|
; after the filename. so parameter starts after that. if next
|
|
; character is a line feed (i.e. 10),then assume that the 0
|
|
; we already encountered used to be a carrage return. in this
|
|
; case,let's set the length to 0 which will be followed by
|
|
; carridge return.
|
|
|
|
; es:si -> command line in config.sys. points to the first non blank
|
|
;character after =.
|
|
|
|
push es
|
|
push ds
|
|
pop es
|
|
pop ds ; es->sysinitseg,ds->confbot seg
|
|
assume ds:nothing
|
|
mov dx,si ; ds:dx->file name,0 in config.sys image.
|
|
|
|
xor cx,cx
|
|
cld
|
|
mov cs:ldexec_start,' ' ; clear out the parm area
|
|
mov di,offset ldexec_parm
|
|
installfilename: ; skip the file name
|
|
lodsb ; al = ds:si; si++
|
|
cmp al,0
|
|
je got_installparm
|
|
jmp installfilename
|
|
got_installparm: ; copy the parameters to ldexec_parm
|
|
lodsb
|
|
mov es:[di],al
|
|
cmp al,lf ; line feed?
|
|
je done_installparm
|
|
inc cl ; # of char. in the parm.
|
|
inc di
|
|
jmp got_installparm
|
|
done_installparm:
|
|
mov byte ptr cs:[ldexec_line],cl ; length of the parm.
|
|
cmp cl,0 ;if no parm,then
|
|
jne install_seg_set ; let the parm area
|
|
mov byte ptr cs:[ldexec_start],cr ; starts with cr.
|
|
install_seg_set:
|
|
mov word ptr cs:0,0 ; make a null environment segment
|
|
mov ax,cs ; by overlap jmp instruction of sysinitseg.
|
|
|
|
;hkn; the environment pointer is made 0. so the current environment ptr.
|
|
;hkn; will be the same as pdb_environ which after dosinit is 0.
|
|
|
|
mov cs:[instexe.exec0_environ],0 ; set the environment seg.
|
|
|
|
|
|
mov word ptr cs:[instexe.exec0_com_line+2],ax ; set the seg.
|
|
mov word ptr cs:[instexe.exec0_5c_fcb+2],ax
|
|
mov word ptr cs:[instexe.exec0_6c_fcb+2],ax
|
|
call sum_up
|
|
mov es:checksum,ax ; save the value of the sum
|
|
xor ax,ax
|
|
mov ah,exec ; load/exec
|
|
mov bx,offset instexe ; es:bx -> parm block.
|
|
push es ; save es,ds for load/exec
|
|
push ds ; these registers will be restored in sysinit_base.
|
|
jmp cs:dword ptr sysinit_base_ptr ; jmp to sysinit_base to execute
|
|
; load/exec function and check sum.
|
|
|
|
;j.k. this is the returning address from sysinit_base.
|
|
|
|
sysinitptr: ; returning far address from sysinit_base
|
|
pop si ; restore si for config.sys file.
|
|
push es
|
|
push ds
|
|
pop es
|
|
pop ds ; now ds - sysinitseg,es - confbot
|
|
jnc exec_exit_code
|
|
|
|
|
|
push si ; error in loading the file for install=.
|
|
call badload ; es:si-> path,filename,0.
|
|
pop si
|
|
jmp short install_exit_ret
|
|
|
|
exec_exit_code:
|
|
mov ah,4dh
|
|
int 21h
|
|
cmp ah,3 ;only accept "stay resident" prog.
|
|
je install_exit_ret
|
|
call error_line ;inform the user
|
|
|
|
stc
|
|
|
|
install_exit_ret:
|
|
ret
|
|
|
|
do_install_exec endp
|
|
|
|
|
|
|
|
;** ParaRound - Round Up length to paragraph multiple
|
|
;
|
|
; ParaRound rounds a byte count up to a multiple of 16, then divides
|
|
; by 16 yielding a "length in paragraphs" value.
|
|
;
|
|
; ENTRY (ax) = byte length
|
|
; EXIT (ax) = rounded up length in paragraphs
|
|
; USES ax, flags
|
|
|
|
Procedure ParaRound
|
|
|
|
add ax,15
|
|
rcr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
ret
|
|
|
|
EndProc ParaRound
|
|
|
|
|
|
;------------------------------------------------------------------------------
|
|
; sysinit_base module.
|
|
;
|
|
; This module is relocated by the routine EndFile to a location in low
|
|
; memory. It is then called by SYSINIT to perform the EXEC of programs
|
|
; that are being loaded by the "install=" command. After the EXEC call
|
|
; completes, this module performs a checksum on the SYSINIT code (at the
|
|
; top of memory) to be sure that the EXECed program did not damage it.
|
|
; If it did, then this module will print an error message and stop the
|
|
; system. Otherwise, it returns control to SYSINIT.
|
|
;
|
|
;
|
|
;in: after relocation,
|
|
; ax = 4b00h - load and execute the program dos function.
|
|
; ds = confbot. segment of config.sys file image
|
|
; es = sysinitseg. segment of sysinit module itself.
|
|
; ds:dx = pointer to asciiz string of the path,filename to be executed.
|
|
; es:bx = pointer to a parameter block for load.
|
|
; SI_end (byte) - offset vaule of end of sysinit module label
|
|
; bigsize (word) - # of word from confbot to SI_end.
|
|
; chksum (word) - sum of every byte from confbot to SI_end in a
|
|
; word boundary moduler form.
|
|
; sysinit_ptr (dword ptr) - return address to sysinit module.
|
|
;
|
|
;note: sysinit should save necessary registers and when the control is back
|
|
|
|
public sysinit_base
|
|
sysinit_base:
|
|
mov word ptr cs:sysinit_base_ss,ss ; save stack
|
|
mov word ptr cs:sysinit_base_sp,sp
|
|
int 21h ; load/exec dos call.
|
|
mov ss,word ptr cs:sysinit_base_ss ; restore stack
|
|
mov sp,word ptr cs:sysinit_base_sp
|
|
pop ds ; restore confbot seg
|
|
pop es ; restore sysinitseg
|
|
jc sysinit_base_end ; load/exec function failed.
|
|
; at this time,i don't have to worry about
|
|
; that sysinit module has been broken or not.
|
|
call sum_up ; otherwise,check if it is good.
|
|
cmp es:checksum,ax
|
|
je sysinit_base_end
|
|
|
|
; memory broken. show "memory allocation error" message and stall.
|
|
|
|
mov ah,9
|
|
push cs
|
|
pop ds
|
|
mov dx,offset mem_alloc_err_msgx - sysinit_base
|
|
int 21h
|
|
jmp $ ; hang here!!!!
|
|
|
|
sysinit_base_end: jmp es:sysinit_ptr ;return back to sysinit module
|
|
|
|
sum_up:
|
|
|
|
;in: es - sysinitseg.
|
|
;out: ax - result
|
|
;
|
|
;remark: since this routine will only check starting from "locstack" to the end of
|
|
; sysinit segment,the data area, and the current stack area are not
|
|
; coverd. in this sense,this check sum routine only gives a minimal
|
|
; gaurantee to be safe.
|
|
;
|
|
;first sum up confbot seg.
|
|
|
|
push ds
|
|
mov ax,es:confbot
|
|
mov ds,ax
|
|
xor si,si
|
|
xor ax,ax
|
|
mov cx,es:config_size ; if config_size has been broken,then this
|
|
;whole test better fail.
|
|
shr cx,1 ; make it a word count
|
|
jz sum_sys_code ; when config.sys file not exist.
|
|
sum1:
|
|
add ax,ds:word ptr [si]
|
|
inc si
|
|
inc si
|
|
loop sum1
|
|
;now,sum up sysinit module.
|
|
sum_sys_code:
|
|
mov si,offset locstack ; starting after the stack.
|
|
; this does not cover the possible stack code!!!
|
|
mov cx,offset sysinitgrp:SI_end ; SI_end is the label at the end of sysinit
|
|
sub cx,si ; from after_checksum to SI_end
|
|
shr cx,1
|
|
sum2:
|
|
add ax,es:word ptr [si]
|
|
inc si
|
|
inc si
|
|
loop sum2
|
|
pop ds
|
|
ret
|
|
|
|
sysinit_base_ss equ $-sysinit_base
|
|
dw ?
|
|
sysinit_base_sp equ $-sysinit_base
|
|
dw ?
|
|
mem_alloc_err_msgx:
|
|
|
|
include msbio.cl4 ; memory allocation error message
|
|
|
|
end_sysinit_base label byte
|
|
|
|
;------------------------------------------------------------------------------
|
|
; ibmstack initialization routine.
|
|
if stacksw
|
|
.sall
|
|
;
|
|
; to follow the standard interrupt sharing scheme, msstack.asm
|
|
; has been modified. this initialization routine also has to
|
|
; be modified because for the interrupt level 7 and 15, firstflag
|
|
; should be set to signal that this interrupt handler is the
|
|
; first handler hooked to this interrupt vector.
|
|
; we determine this by looking at the instruction pointed by
|
|
; this vector. if it is iret, then this handler should be the
|
|
; first one. in our case, only the interrupt vector 77h is the
|
|
; interrupt level 15. (we don't hook interrupt level 7.)
|
|
;
|
|
; the followings are mainly due to m.r.t; ptm fix of p886 12/3/86
|
|
; some design changes are needed to the above interrupt sharing
|
|
; method. the above sharing scheme assumes that 1). interrupt
|
|
; sharing is never done on levels that have bios support. 2). "phantom"
|
|
; interrupts would only be generated on levels 7 and 15.
|
|
; these assumptions are not true any more. we have to use the firstflag
|
|
; for every level of interrupt. we will set the firstflag on the following
|
|
; conditions:
|
|
;
|
|
; a. if the cs portion of the vector is 0000, then "first"
|
|
; b. else if cs:ip points to valid shared header, then not "first"
|
|
; c. else if cs:ip points to an iret, then "first"
|
|
; d. else if cs:ip points to dummy, then "first"
|
|
;
|
|
; where dummy is - the cs portion must be f000, and the ip portion must
|
|
; be equal to the value at f000:ff01. this location is the initial value
|
|
; from vector_table for interrupt 7, one of the preserved addresses in all
|
|
; the bioses for all of the machines.
|
|
;
|
|
; system design group requests bios to handle the phantom interrupts.
|
|
;
|
|
; the "phantom" interrupt is an illegal interrupt such as an interrupt
|
|
; produced by the bogus adapter card even without interrupt request is
|
|
; set. more specifically, 1). the 8259 has a feature when running in
|
|
; edge triggered mode to latch a pulse and present the interrupt when
|
|
; the processor indicates interrupt acknowledge (inta). the interrupt
|
|
; pulse was exist at the time of inta to get a "phantom" interrupt.
|
|
; 2). or, this is caused by adapter cards placing a glitch on the
|
|
; interrupt line.
|
|
;
|
|
; to handle those "phantom" interrupts, the main stack code will check
|
|
; the own firstflag, and if it is not "first" (which means the forward
|
|
; pointer points to the legal shared interrupt handler), then pass the
|
|
; control. if it is the first, then the following action should be
|
|
; taken. we don't have to implement skack logic in this case.
|
|
;
|
|
; to implement this logic, we rather choose a simple method.
|
|
; if ont of the above "firstflag" conditions is met, we are not
|
|
; going to hook this interrupt vector. the reason is if the original
|
|
; vector points to "iret" and do nothing, we don't need
|
|
; to implement the stack logic for it. this will simplify implementation
|
|
; while maintaining compatibility with the old version of dos.
|
|
; this implies that in the main stack code, there might be a stack code
|
|
; that will never be used, a dead code.
|
|
;
|
|
;in - cs, ds -> sysinitseg, es -> relocated stack code & data.
|
|
|
|
page
|
|
assume ds:sysinitseg
|
|
stackinit proc near
|
|
|
|
push ax
|
|
push ds
|
|
push es
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push di
|
|
push si
|
|
push bp
|
|
|
|
;currently es -> stack code area
|
|
|
|
mov ax, cs:[stack_count] ;defined in cs
|
|
mov es:[stackcount], ax ;defined in stack code area
|
|
mov ax, [stack_size] ;in cs
|
|
mov es:[stacksize], ax
|
|
mov ax, word ptr cs:[stack_addr] ; offset
|
|
mov word ptr es:[stacks], ax
|
|
mov ax, word ptr cs:[stack_addr+word] ; segment
|
|
mov word ptr es:[stacks+word], ax
|
|
|
|
; initialize the data fields with the parameters
|
|
|
|
; "firstentry" will always be at stacks
|
|
|
|
mov bp, word ptr es:stacks ; get offset of stack
|
|
mov es:firstentry,bp
|
|
|
|
; the stacks will always immediately follow the table entries
|
|
|
|
mov ax,entrysize
|
|
mov cx,es:stackcount
|
|
mul cx
|
|
add ax,bp
|
|
mov es:stackat,ax
|
|
mov bx,ax
|
|
sub bx,2
|
|
|
|
; zero the entire stack area to start with
|
|
|
|
mov di,es:stackat
|
|
mov ax,es:stacksize
|
|
mul cx
|
|
mov cx,ax
|
|
xor ax,ax
|
|
push es
|
|
pop ds ;ds = relocated stack code seg.
|
|
assume ds:nothing
|
|
|
|
;now, ds -> stack code area
|
|
|
|
mov es, word ptr ds:[stacks+2] ; get segment of stack area.
|
|
cld
|
|
rep stosb
|
|
|
|
mov cx, ds:stackcount
|
|
|
|
; loop for "count" times, building a table entry
|
|
; cs = sysinitseg, ds = relocated stack code seg , es = segment of stack space
|
|
; cx = number of entries
|
|
; es:bp => base of stacks - 2
|
|
; es:bx => first table entry
|
|
|
|
buildloop:
|
|
mov es:byte ptr allocbyte[bp],free
|
|
mov es:byte ptr intlevel[bp],al ;ax = 0
|
|
mov es:word ptr savedsp[bp],ax
|
|
mov es:word ptr savedss[bp],ax
|
|
add bx,ds:stacksize
|
|
mov es:word ptr newsp[bp],bx
|
|
mov es:[bx],bp
|
|
add bp,entrysize
|
|
|
|
loop buildloop
|
|
|
|
sub bp,entrysize
|
|
mov ds:lastentry,bp
|
|
mov ds:nextentry,bp
|
|
|
|
; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle
|
|
; push ds
|
|
; mov ax, 0f000h ;look at the model byte
|
|
; mov ds, ax
|
|
; cmp ds:byte ptr [0fffeh], mdl_convert ;convertible?
|
|
; pop ds
|
|
; jne skip_disablenmis
|
|
;
|
|
; mov al,07h ; disable convertible nmis
|
|
; out 72h,al
|
|
;
|
|
;skip_disablenmis:
|
|
|
|
xor ax,ax
|
|
mov es,ax ;es - segid of vector table at 0
|
|
assume es:nothing ;ds - relocated stack code segment
|
|
|
|
call DOCLI
|
|
|
|
irp aa,<02,70>
|
|
|
|
mov si,aa&h*4 ;pass where vector is to be adjusted
|
|
mov di, offset int19old&aa ;we have to set old&aa for int19 handler too.
|
|
mov bx,offset old&aa ;pass where to save original owner pointer
|
|
mov dx,offset int&aa ;pass where new handler is
|
|
call new_init_loop ;adjust the vector to new handler,
|
|
; saving pointer to original owner
|
|
endm
|
|
|
|
|
|
; NTVDM int 08, 09, special handling 24-Jan-1993 Jonle
|
|
;
|
|
; These Ints are usually done in the macro above with int 02,70
|
|
; However, we don't need stack swapping as long as no device
|
|
; driver has hooked it. These ints are also left alone so that
|
|
; softpc will know if they have been hooked by an app.
|
|
|
|
mov si, 09h*4
|
|
mov ax, word ptr es:[si+0]
|
|
cmp word ptr old09, ax
|
|
jne do_I9StkSwap
|
|
mov ax, word ptr es:[si+2]
|
|
cmp word ptr old09+2, ax
|
|
je skip_I9StkSwap
|
|
do_I9StkSwap:
|
|
mov di, offset int19old09
|
|
mov bx,offset old09
|
|
mov dx,offset int09
|
|
call new_init_loop
|
|
skip_I9StkSwap:
|
|
|
|
mov si, 08h*4
|
|
mov ax, word ptr es:[si+0]
|
|
cmp word ptr old08, ax
|
|
jne do_I8StkSwap
|
|
mov ax, word ptr es:[si+2]
|
|
cmp word ptr old08+2, ax
|
|
je skip_I8StkSwap
|
|
do_I8StkSwap:
|
|
mov di, offset int19old08
|
|
mov bx,offset old08
|
|
mov dx,offset int08
|
|
call new_init_loop
|
|
skip_I8StkSwap:
|
|
|
|
|
|
irp aa,<0a,0b,0c,0d,0e,72,73,74,76,77> ;shared interrupts
|
|
|
|
mov si,aa&h*4 ;pass where vector is to be adjusted
|
|
push ds ;save relocated stack code segment
|
|
lds bx, es:[si] ;ds:bx -> original interrupt handler
|
|
push ds
|
|
pop dx ;dx = segment value
|
|
|
|
cmp dx,0
|
|
jz int&aa&_first
|
|
|
|
cmp byte ptr ds:[bx],0cfh ;does vector point to an iret?
|
|
jz int&aa&_first
|
|
|
|
cmp word ptr ds:[bx.6],424bh ;magic offset (see int&aa, msstack.inc)
|
|
jz int&aa&_not_first
|
|
|
|
cmp dx,0f000h ;rom bios segment
|
|
jnz int&aa&_not_first
|
|
|
|
push es
|
|
push dx
|
|
mov dx,0f000h
|
|
mov es,dx
|
|
cmp bx,word ptr es:0ff01h
|
|
pop dx
|
|
pop es
|
|
jz int&aa&_first
|
|
|
|
int&aa&_not_first: ;not the first. we are going to hook vector.
|
|
pop ds
|
|
mov di, offset int19old&aa ;we have to set old&aa for int19 handler too.
|
|
mov bx, offset old&aa ;pass where to save original owner pointer
|
|
mov dx, offset int&aa ;pass where new handler is
|
|
call new_init_loop ;adjust the vector to new handler, saving
|
|
;pointer to original owner.
|
|
jmp short int&aa&_end
|
|
int&aa&_first: ;the first. don't have to hook stack code.
|
|
pop ds
|
|
int&aa&_end:
|
|
|
|
endm
|
|
|
|
; NTVDM support for pc convertable is NOT NEEDED 10-Aug-1992 Jonle
|
|
; push ds
|
|
; mov ax, 0f000h ;loook at the model byte
|
|
; mov ds, ax
|
|
; cmp ds:byte ptr [0fffeh], mdl_convert ;pc convertible?
|
|
; pop ds
|
|
; jne skip_enablenmis
|
|
;
|
|
; mov al,27h ; enable convertible nmis
|
|
; out 72h,al
|
|
;
|
|
; skip_enablenmis:
|
|
|
|
call DOSTI
|
|
mov ax,Bios_Data
|
|
mov ds,ax
|
|
assume ds:Bios_Data
|
|
|
|
|
|
mov [int19sem],1 ; indicate that int 19
|
|
; initialization is complete
|
|
|
|
pop bp ; restore all
|
|
pop si
|
|
pop di
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
|
|
pop es
|
|
pop ds
|
|
assume ds:sysinitseg
|
|
|
|
pop ax
|
|
ret
|
|
stackinit endp
|
|
|
|
new_init_loop proc near
|
|
|
|
;input: si=ofset into vector table of the particular int vector being adjusted
|
|
; bx=ds:offset of oldxx, where will be saved the pointer to original owner
|
|
; dx=ds:offset of intxx, the new interrupt handler
|
|
; di=offset value of int19old&aa variable in bios.
|
|
; es=zero, segid of vector table
|
|
; ds=relocated stack code segment
|
|
|
|
mov ax,es:[si+0] ;remember offset in vector
|
|
mov word ptr ds:[bx],ax ; to original owner in ds
|
|
mov ax,es:[si+2] ;remember segid in vector
|
|
mov word ptr ds:[bx]+2,ax ; to original owner in ds
|
|
|
|
push ds
|
|
mov ax,Bios_Data
|
|
mov ds,ax ;set int19oldxx value in bios for
|
|
mov ax,es:[si+0] ;int 19 handler
|
|
mov word ptr ds:[di],ax
|
|
mov ax,es:[si+2]
|
|
mov word ptr ds:[di]+2,ax
|
|
pop ds
|
|
|
|
mov word ptr es:[si+0],dx ;set vector to point to new int handler
|
|
mov es:[si+2],ds
|
|
ret
|
|
new_init_loop endp
|
|
|
|
|
|
.xall
|
|
endif
|
|
;------------------------------------------------------------------------------
|
|
public setdevmark
|
|
setdevmark proc
|
|
|
|
;set the devmark for mem command.
|
|
;in: [memhi] - the address to place devmark
|
|
; [memlo] = 0
|
|
; al = id for devmark_id
|
|
;out: devmark established.
|
|
; the address saved in cs:[devmark_addr]
|
|
; [memhi] increase by 1.
|
|
|
|
push es
|
|
push cx
|
|
|
|
mov cx,cs:[memhi]
|
|
mov cs:[devmark_addr],cx
|
|
mov es,cx
|
|
mov es:[devmark_id],al
|
|
inc cx
|
|
mov es:[devmark_seg],cx
|
|
|
|
pop cx
|
|
pop es
|
|
inc cs:[memhi]
|
|
ret
|
|
setdevmark endp
|
|
|
|
|
|
ifdef TAIWAN
|
|
|
|
;---------------------
|
|
; entry : none
|
|
; exit : ax = 0 --> oem local driver not found
|
|
; = 1 --> oem local driver found
|
|
; destore : ds,es,bx,cx,dx,si,di
|
|
; description :
|
|
; search config.sys to find oem local driver.
|
|
; oem local driver should in \csi\driver\ directory .
|
|
; if (found oem local driver in config.sys)
|
|
; ax=1;
|
|
; else
|
|
; ax=0;
|
|
; return;
|
|
; ps. please see state diagram for state description.
|
|
;---------------------
|
|
|
|
chkoemlocaldrv proc near
|
|
push es
|
|
push ds
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push di
|
|
push si
|
|
call chkconfig
|
|
pop si
|
|
pop di
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ds
|
|
pop es
|
|
ret
|
|
chkoemlocaldrv endp
|
|
|
|
config_sys db "C:\CONFIG.SYS",0
|
|
sizeofconfig dw 0
|
|
filehandle dw 0
|
|
workingmemptr dw 0
|
|
deviceid db "DEVICE"
|
|
csidrvid db "CSI\DRIVER\"
|
|
localdrvname dw 0
|
|
chkconfig proc near
|
|
call preprocess
|
|
jnc initstate
|
|
jmp notfoundret
|
|
|
|
;
|
|
; processing config.sys
|
|
;
|
|
; state 0
|
|
; ds:si --> current line ( end of line is oah or 0dh )
|
|
|
|
initstate:
|
|
mov si,dx
|
|
state_0:
|
|
push cs
|
|
pop es
|
|
mov di,offset deviceid
|
|
mov cx,3
|
|
repz cmpsw
|
|
jz state_1
|
|
mov ax,0ffffh
|
|
jmp state_10
|
|
state_1:
|
|
lodsb
|
|
cmp al,' '
|
|
jz state_1
|
|
cmp al,'='
|
|
jz state_2
|
|
state_10a:
|
|
jmp state_10
|
|
state_2:
|
|
lodsb
|
|
cmp al,' '
|
|
jz state_2
|
|
cmp al,'\'
|
|
jz state_5
|
|
cmp al,'A'
|
|
jb state_10a
|
|
cmp al,'z'
|
|
ja state_10a
|
|
state_3:
|
|
dec si
|
|
mov cs:[localdrvname],si
|
|
inc si
|
|
state_4:
|
|
lodsb
|
|
cmp al,':'
|
|
jz state_6
|
|
jmp state_10
|
|
state_5:
|
|
dec si
|
|
mov cs:[localdrvname],si
|
|
inc si
|
|
jmp state_7
|
|
state_6:
|
|
lodsb
|
|
cmp al,'\'
|
|
jz state_7
|
|
cmp al,'c'
|
|
jne state_10a
|
|
inc si
|
|
state_7:
|
|
mov di,offset csidrvid
|
|
mov cx,11
|
|
repz cmpsb
|
|
jnz state_10a
|
|
state_8:
|
|
lodsb
|
|
cmp al,'1'
|
|
jb state_10
|
|
cmp al,'z'
|
|
ja state_10
|
|
state_9:
|
|
tryopenlocaldrv:
|
|
mov dx,cs:[localdrvname]
|
|
mov si,dx
|
|
chknextbyte:
|
|
lodsb
|
|
cmp al,0h
|
|
jz openfile
|
|
cmp al,' '
|
|
jne chknextbyte
|
|
dec si
|
|
mov byte ptr ds:[si],0
|
|
openfile:
|
|
mov ax,3d00h ; open config.sys
|
|
stc
|
|
int 21h
|
|
jc notfoundret
|
|
mov bx,ax ; bx = file handle
|
|
mov ah,3eh
|
|
int 21h ; close local driver
|
|
jc notfoundret
|
|
jmp foundret
|
|
|
|
state_10:
|
|
cmp al,1ah ; look current char. == eof ?
|
|
jz notfoundret
|
|
lodsb
|
|
cmp al,0
|
|
jz newlinestate
|
|
cmp al,1ah
|
|
jz notfoundret
|
|
jmp state_10
|
|
newlinestate:
|
|
lodsb
|
|
cmp al,1ah
|
|
jz notfoundret
|
|
cmp al,0
|
|
jz newlinestate
|
|
dec si
|
|
jmp state_0
|
|
notfoundret:
|
|
mov ax,0
|
|
jmp freemem
|
|
foundret:
|
|
mov ax,1
|
|
freemem:
|
|
push ax
|
|
call freememory
|
|
pop ax
|
|
ret
|
|
|
|
chkconfig endp
|
|
|
|
preprocess proc near
|
|
push cs
|
|
pop ds
|
|
mov dx,offset config_sys
|
|
mov ax,3d00h ; open config.sys
|
|
stc
|
|
int 21h
|
|
jc errorfile
|
|
|
|
; get size of config.sys
|
|
|
|
mov bx,ax ; bx = file handle
|
|
mov cs:[filehandle],bx
|
|
xor cx,cx
|
|
xor dx,dx
|
|
mov ax,4202h ; move file ptr
|
|
int 21h
|
|
mov cs:[sizeofconfig],ax ; ax == size of config.sys
|
|
xor dx,dx ; ignore more than 64k of config
|
|
mov ax,4200h ; mov file ptr to beginning of file
|
|
int 21h
|
|
|
|
; allocate for config.sys
|
|
|
|
mov ax,cs:[sizeofconfig]
|
|
add ax,15 ; change to para
|
|
rcr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
shr ax,1
|
|
add ax,20h
|
|
mov bx,ax ; size of memory in para
|
|
mov ah,48h
|
|
int 21h
|
|
jc memerr
|
|
; ax --> free memory
|
|
mov cs:[workingmemptr],ax
|
|
|
|
; read config.sys
|
|
|
|
mov bx,cs:[filehandle] ; file handle
|
|
mov cx,cs:[sizeofconfig] ; byte count of reading
|
|
xor dx,dx
|
|
mov ds,ax ; ds:dx --> buffer
|
|
mov ah,3fh
|
|
int 21h
|
|
jc errorfile
|
|
|
|
; translate to upper case
|
|
|
|
call transtoupper
|
|
clc
|
|
ret
|
|
errorfile:
|
|
memerr:
|
|
stc
|
|
ret
|
|
preprocess endp
|
|
|
|
; entry : ds:dx --> buffer
|
|
; exit : none
|
|
; description : translate all letter in buffer to upper type
|
|
; ps ,don't change ds:dx
|
|
|
|
transtoupper proc near
|
|
cld
|
|
mov cx,cs:[sizeofconfig]
|
|
mov si,dx
|
|
transnext:
|
|
lodsb
|
|
cmp al,'A'
|
|
jb chklfcr
|
|
cmp al,'z'
|
|
ja chkcounter
|
|
sub al,'a'-'A'
|
|
mov ds:[si-1],al
|
|
jmp chkcounter
|
|
chklfcr:
|
|
cmp al,0dh
|
|
jz setzero
|
|
cmp al,0ah
|
|
jz setzero
|
|
jmp chkcounter
|
|
setzero:
|
|
mov al,0
|
|
mov ds:[si-1],al
|
|
chkcounter:
|
|
loop transnext
|
|
ret
|
|
transtoupper endp
|
|
|
|
;entry : none ( free memory block ptr in [workingmem] )
|
|
;exit : none
|
|
|
|
freememory proc near
|
|
mov ax,cs:[workingmemptr]
|
|
mov es,ax
|
|
mov ah,49h
|
|
int 21h
|
|
ret
|
|
freememory endp
|
|
|
|
|
|
; name : maketempvector
|
|
; entry : es:bx -->
|
|
; dd original int 9 vector ( offfset ,segment )
|
|
; dd original int 10h vector ( offfset ,segment )
|
|
; dd original int 16h vector ( offfset ,segment )
|
|
;
|
|
; exit : none
|
|
; description : 1. save local driver table in static area
|
|
; 2. make temp. vector for int9 ,10h ,16h
|
|
;
|
|
oemdriverinst dw 0
|
|
orgvectblptr dd 0
|
|
|
|
db 0eah
|
|
dummyint9 dd 0
|
|
db 0eah
|
|
dummyint10h dd 0
|
|
db 0eah
|
|
dummyint16h dd 0
|
|
|
|
csiint9 dd 0
|
|
csiint10h dd 0
|
|
csiint16h dd 0
|
|
|
|
maketempvector proc near
|
|
push ds
|
|
push ax
|
|
push di
|
|
push si
|
|
push cx
|
|
|
|
; save table ptr
|
|
|
|
mov word ptr cs:[orgvectblptr],bx
|
|
mov word ptr cs:[orgvectblptr+2],es
|
|
cmp cs:oemdriverinst,0
|
|
jnz ignoreint9
|
|
|
|
; make temp. vector for int 9 ,
|
|
|
|
mov bx,9 ; int #
|
|
push cs
|
|
pop es
|
|
mov di,offset csiint9 ; es:di --> store area for csi vector
|
|
push cs
|
|
pop ds
|
|
mov si,offset dummyint9 ; ds:si --> dummy int service
|
|
call dummyvector
|
|
|
|
ignoreint9:
|
|
|
|
; make temp. vector for int 10h
|
|
|
|
mov bx,10h ; int #
|
|
push cs
|
|
pop es
|
|
mov di,offset csiint10h ; es:di --> store area for csi vector
|
|
push cs
|
|
pop ds
|
|
mov si,offset dummyint10h ; ds:si --> dummy int service
|
|
call dummyvector
|
|
|
|
; make temp. vector for int 16h
|
|
|
|
mov bx,16h ; int #
|
|
push cs
|
|
pop es
|
|
mov di,offset csiint16h ; es:di --> store area for csi vector
|
|
push cs
|
|
pop ds
|
|
mov si,offset dummyint16h ; ds:si --> dummy int service
|
|
call dummyvector
|
|
pop cx
|
|
pop si
|
|
pop di
|
|
pop ax
|
|
pop ds
|
|
ret
|
|
|
|
|
|
maketempvector endp
|
|
|
|
;name : dummyvector
|
|
; entey : ds:si --> dummy int sevice routine
|
|
; es:di --> point to csi vector store area
|
|
; bx == int number
|
|
; exit : none
|
|
; description :
|
|
; setting dummy vector of int 9 ,10h,16h
|
|
; for recover csi vector
|
|
; /* phase 1*/
|
|
; [ds:si]=[0:bx*4]
|
|
; [ds:si+2]=[0:bx*4+2]
|
|
; /* phase 2*/
|
|
; [es:di]=[0:bx*4]
|
|
; [es:di+2]=[0:bx*4+2]
|
|
; /* phase 2*/
|
|
; [0:bx*4]=si-1;
|
|
; [0:bx*4+2]=ds;
|
|
|
|
dummyvector proc near
|
|
shl bx,1 ; bx <- bx*4
|
|
shl bx,1 ; ie ,get offset of vector
|
|
|
|
; phase 1
|
|
; es --> 0
|
|
; es:bx --> cpu int vector table
|
|
|
|
xor ax,ax
|
|
push es
|
|
mov es,ax
|
|
mov ax,es:[bx] ; get offset ds-->0
|
|
mov ds:[si],ax ; store offset
|
|
mov ax,es:[bx+2] ; get offset ds-->0
|
|
mov ds:[si+2],ax ; store segment
|
|
pop es
|
|
|
|
; phase 2
|
|
; ds --> 0
|
|
; ds:bx --> cpu int vector table
|
|
|
|
xor ax,ax
|
|
push ds
|
|
mov ds,ax
|
|
mov ax,ds:[bx] ; get offset
|
|
mov es:[di],ax ; store offset
|
|
mov ax,ds:[bx+2] ; get offset
|
|
mov es:[di+2],ax ; store segment
|
|
pop ds
|
|
|
|
; phase 3
|
|
; es --> 0
|
|
; es:bx --> cpu int vector table
|
|
|
|
xor ax,ax
|
|
push es
|
|
mov es,ax
|
|
dec si
|
|
mov es:[bx],si
|
|
mov ax,ds
|
|
mov es:[bx+2],ax
|
|
pop es
|
|
ret
|
|
dummyvector endp
|
|
|
|
; name : recovercsiint
|
|
; entry : none
|
|
; exit :none
|
|
; description :
|
|
; recover int 9 ,10h,16h ,for csi vector
|
|
|
|
recovercsiint proc near
|
|
push es
|
|
push ds
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push si
|
|
push di
|
|
|
|
;recover int 9
|
|
|
|
cmp cs:oemdriverinst,0
|
|
jnz ignoreint9recover
|
|
|
|
push cs
|
|
pop ds
|
|
mov si,offset dummyint9
|
|
push cs
|
|
pop es
|
|
|
|
mov di,offset csiint9
|
|
mov bx,9
|
|
mov ax,0
|
|
call recoverint
|
|
ignoreint9recover:
|
|
|
|
; recover int 10h
|
|
|
|
push cs
|
|
pop ds
|
|
mov si,offset dummyint10h
|
|
push cs
|
|
pop es
|
|
mov di,offset csiint10h
|
|
mov bx,10h
|
|
mov ax,0+4
|
|
call recoverint
|
|
|
|
;recover int 16h
|
|
|
|
push cs
|
|
pop ds
|
|
mov si,offset dummyint16h
|
|
push cs
|
|
pop es
|
|
mov di,offset csiint16h
|
|
mov bx,16h
|
|
mov ax,0+4+4
|
|
call recoverint
|
|
pop di
|
|
pop si
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
pop ds
|
|
pop es
|
|
ret
|
|
recovercsiint endp
|
|
|
|
; name : recoverint
|
|
; entey : ds:si --> dummy int sevice routine
|
|
; es:di --> point to csi vector store area
|
|
; bx == int number
|
|
; ax == 0 ; int 9
|
|
; 4 ; int 10h
|
|
; 4+4 ; int 16h
|
|
; exit : none
|
|
; description :
|
|
; 1. if( [0:bx*4] == si-1 .and. [es:bx*4+2] == ds )
|
|
; {
|
|
; [0:bx*4] = [es:di];
|
|
; [0:bx*4+2] = [es:di+2];
|
|
; }
|
|
; else
|
|
; {
|
|
; /* phase 1 */
|
|
; [ds:si] = [(*orgvectblptr)+ax]
|
|
; [ds:si+2]= [(*orgvectblptr)+ax+2];
|
|
; /* phase 2 */
|
|
; [orgvectblptr+ax) ]=[0:bx*4] ;
|
|
; [orgvectblptr+ax+2 ]=[0:bx*4+2] ;
|
|
; /* phase 3 */
|
|
; [0:bx*4] = [es:di];
|
|
; [0:bx*4+2] = [es:di+2];
|
|
;
|
|
;
|
|
; }
|
|
|
|
;
|
|
|
|
recoverint proc near
|
|
;chek vector change ?
|
|
; es --> 0
|
|
|
|
push es
|
|
mov cx,ax
|
|
xor ax,ax
|
|
mov es,ax
|
|
shl bx,1
|
|
shl bx,1 ; es:bx --> cpu int vector
|
|
mov ax,si
|
|
dec ax
|
|
cmp es:[bx],ax ; offset same ?
|
|
jne vectorbechanged
|
|
|
|
mov ax,ds
|
|
cmp es:[bx+2],ax ; segmnet same ?
|
|
jne vectorbechanged
|
|
pop es
|
|
|
|
; vector not be changed
|
|
; ds --> 0
|
|
|
|
xor ax,ax
|
|
mov ds,ax ; ds:bx --> cpu int vector
|
|
mov ax,es:[di]
|
|
mov ds:[bx],ax
|
|
mov ax,es:[di+2]
|
|
mov ds:[bx+2],ax
|
|
ret
|
|
|
|
vectorbechanged:
|
|
|
|
;phase 1
|
|
; di:es --> addres of local driver
|
|
|
|
pop es
|
|
push di
|
|
push es
|
|
mov di,word ptr cs:[orgvectblptr]
|
|
mov es,word ptr cs:[orgvectblptr+2]
|
|
add di,cx
|
|
mov ax,es:[di]
|
|
mov ds:[si],ax
|
|
mov ax,es:[di+2]
|
|
mov ds:[si+2],ax
|
|
|
|
;phase2
|
|
; di:es --> addres of local driver
|
|
; ds --> 0
|
|
|
|
push ds
|
|
xor ax,ax
|
|
mov ds,ax
|
|
mov ax,ds:[bx] ; ds:bx --> cpu int vector
|
|
mov es:[di],ax
|
|
mov ax,ds:[bx+2]
|
|
mov es:[di+2],ax
|
|
pop ds
|
|
pop es
|
|
pop di
|
|
|
|
;phase3
|
|
; ds --> 0
|
|
|
|
xor ax,ax
|
|
push ds
|
|
mov ds,ax
|
|
mov cx,es:[di]
|
|
mov ds:[bx],cx ; ds:bx --> cpu int vector
|
|
mov cx,es:[di+2]
|
|
mov ds:[bx+2],cx
|
|
pop ds
|
|
ret
|
|
|
|
recoverint endp
|
|
|
|
;name : chklocalexist
|
|
;entry : none
|
|
;exit :none
|
|
; descriptin : check local driver exist ?
|
|
; if not exist system halt !
|
|
; otherwise null return
|
|
|
|
chklocalexist proc near
|
|
push ax
|
|
push cx
|
|
push dx
|
|
mov ah,0dbh
|
|
mov al,80h ; module_extsysutil
|
|
mov cx,01 ; syscmd_extquerysysmode
|
|
int 16h
|
|
test ax,8000h ; bit 15 on
|
|
jnz csisystemerror ; no,system halt
|
|
; yes ,dx == country id
|
|
push dx ; save current id
|
|
mov dx,58h
|
|
mov ah,0dbh
|
|
mov al,80h ; module_extsysutil
|
|
mov cx,02 ; syscmd_extsetsysmode
|
|
int 16h
|
|
test ax,8000h ; bit 15 on
|
|
jnz localdrvnotfound ; no ,local driver error
|
|
|
|
pop cx
|
|
cmp cx,dx ; current id == previous id ?
|
|
jnz localdrvnotfound ; no ,local driver error
|
|
|
|
pop dx
|
|
pop cx
|
|
pop ax
|
|
ret
|
|
|
|
localdrvnotfound:
|
|
csisystemerror:
|
|
push cs
|
|
pop ds
|
|
mov dx,offset bootfailmsg
|
|
mov ah,9
|
|
int 21h
|
|
cli
|
|
hlt
|
|
ret
|
|
|
|
chklocalexist endp
|
|
endif
|
|
|
|
sysinitseg ends
|
|
end
|