Files
DR-DOS-OpenDOS/IBMBIO/BIOSINIT.A86
2020-11-04 23:59:28 +01:00

1806 lines
47 KiB
Plaintext

; File : $BIOSINIT.A86$
;
; Description :
;
; Original Author : DIGITAL RESEARCH
;
; Last Edited By : $CALDERA$
;
;-----------------------------------------------------------------------;
; Copyright Work of Caldera, Inc. All Rights Reserved.
;
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
; CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
; *** Current Edit History ***
; *** End of Current Edit History ***
;
; $Log$
; BIOSINIT.A86 1.43 93/12/03 00:38:19
; Fix bug in AllocHMA when base not para aligned
; BIOSINIT.A86 1.42 93/11/29 21:40:03
; Fill in name field of system DMD's (owner=8) with 'SC'
; BIOSINIT.A86 1.41 93/11/18 15:43:14
; Add primitive multi-master checking
; BIOSINIT.A86 1.40 93/11/11 12:25:29
; VDISK header changes
; BIOSINIT.A86 1.39 93/11/08 23:19:22
; SetupHMA does CALL5 initialisation
; BIOSINIT.A86 1.38 93/10/29 20:03:48
; BIOS relocation services restored for possible 3rd party memory manager use
; BIOSINIT.A86 1.37 93/10/29 19:42:27
; Change HIDOS default to off
; BIOSINIT.A86 1.36 93/09/22 15:22:14
; Change int21/4458 to les bx,cs:drdos_ptr (smaller, faster)
; BIOSINIT.A86 1.35 93/09/03 20:10:55
; Support intl YES/NO
; BIOSINIT.A86 1.34 93/09/02 22:34:42
; Add header to system allocations
; BIOSINIT.A86 1.33 93/09/01 17:36:57
; increase stack size for aspi4dos.sys
; BIOSINIT.A86 1.31 93/08/06 20:55:16
; re-arrange device init order for SCREATE.SYS on a VDISK.SYS
; BIOSINIT.A86 1.28 93/08/02 14:45:43
; hide preload drives from func_device
; ENDLOG
include i:msdos.equ ; DOS Function Equates
include i:psp.def ; PSP Definition
include i:f52data.def ; Internal DOS data area
include i:doshndl.def ; Dummy DOS structures
include config.equ
include i:fdos.equ
include i:modfunc.def
TRUE equ 0FFFFh ; value of TRUE
FALSE equ 0 ; value of FALSE
;
; Equates for INIT_FLAGS which can be modified by the BIOS
; the default is a RAM based BDOS (Code and Data) with INIT_DRV
; specifing the default drive and the initial drive for COMSPEC
;
INIT_ROMCODE equ 0001h ; Rom based DOS CODE
INIT_COMSPEC equ 0002h ; COMSPEC_DRV specifies the default
; Command Processor Drive
INIT_WINDOWS equ 0004h ; Disable windows support
COMMAND_BASE equ 000E0h ; must cover FFFF:D0 for CALL5 fixup
COMMAND_SIZE equ 015C0h
CGROUP GROUP CODE, INITCODE, INITDATA, INITPSP, INITENV, DATAEND
CODE CSEG
eject
;
; The DOS Code Segment is formatted as follows.
;
DOS_OFFSET equ word ptr .0008h ; Offset of code in segment
HISTORY_CODE equ word ptr .000Ch ; Start of history code
INIT_CODE equ word ptr .000Eh ; Start of initialisation code
DOS_FLAG equ word ptr .001Ch ; Compressed Data Flag
DOS_CODE equ word ptr .001Eh ; DOS Code Length (Bytes)
DOS_DATA equ word ptr .0020h ; DOS Data Length (Bytes)
NO_YES_CHARS equ word ptr .0028h ; DOS Data No/Yes characters
INT31_SEGMENT equ word ptr .00C6h ; DOS Data Segment pointer
; for ROM systems
JMPF_OPCODE equ 0EAh ; 8086 JMPF instruction
INITCODE CSEG PARA 'INITCODE'
extrn cleanup:near ; BIOS Clean Up routine
extrn config_init:near ; CONFIG Code Init
extrn config_finish:near ; Update DOS with Device Info
extrn config:near ; CONFIG.SYS Processor
extrn crlf:near ; Output CR/LF to screen
extrn resident_device_init:near ; Device Driver Init
extrn read_dos:near ; load DOS file
extrn setup_ldt:near
extrn setup_stacks:near
extrn dos_version_check:near
db 'Copyright (c) 1983,1996 '
db 'Caldera, Inc. All Rights Reserved '
db 'XXXX-0000-987654321X'
Public biosinit
;========
biosinit:
;========
; entry: MEM_SIZE = memory size in paragraphs
; DEVICE_ROOT = address of 1st resident device driver
; INIT_DRV = boot drive (0 = A:, 1 = B:, etc.)
; INIT_BUF = minimum # of disk buffers
; CURRENT_DOS = code segment of DOS (if loaded)
; INIT_FLAGS = Control Flags
; COMSPEC_DRV = Drive for Command Processor
;
;
; we set up the following variables
; BIOS_SEG = low memory BIOS code/data (static)
; DOS_DSEG = low memory DOS data area (static)
; RCODE_SEG = relocated BIOS code segment
; DOS_CSEG = relocated DOS code segment
; INIT_DSEG = segment based initialisation data
;
cld
cli
mov ax,cs ; Initialise our stack and Data Segment
mov ds,ax
mov ss,ax
mov sp,offset stack
sti
mov bios_seg,ax ; Save the BIOS Segment
; Now some code which allows Remote Program Loader to reserve some memory
; which will be safe from being trampled on by the system.
; The RPL takes over Int 2F and has a magic signature "RPL" at offset 3 from
; it's entry point. If this is detected an Int2f is issued
;
; On Entry:
; AX = 4A06, DX = Segment address of top of memory
; On Exit:
; DX = segment address of the RPL
;
; On return the system will build a DMD entry for the RPL, with an owner field
; of 8 (ie. System). The RPL can poke this entry to 0 when it wishes to free
; the memory.
;
; In addition we now look for "RPLOADER", and if found we remember the address
; of the entry point so we can call it with status information
mov dx,mem_size ; get existing size
dec dx ; one para less for upper mem DMD link
xor ax,ax
mov es,ax ; point to vectors
mov bx,4*2fh ; we want Int 2F vector
les bx,es:dword ptr [bx] ; pick up the contents
lea di,3[bx] ; point to magic signature "RPL"
mov si,offset rpl_name
mov cx,3
repe cmpsb ; does the signature match ?
jne biosinit20
mov cx,5 ; look also for "RPLOADER"
repe cmpsb
jne biosinit10
mov rpl_off,bx ; save entry point for use later
mov rpl_seg,es
biosinit10:
mov ax,4a06h ; magic number for RPL
int 2fh ; does anyone want to steal memory ?
inc dx
cmp dx,mem_size ; is memory size unchanged ?
jnb biosinit20
dec dx ; point back at start of memory
dec dx ; then one below for DMD start
mov es,dx ; ES points to DMD
mov DMD_ID,IDZ ; make it last in the chain
mov DMD_PSP,8 ; owned by system
lea di,DMD_NAME ; point to name field
mov si,offset rpl_name
mov cx,(length rpl_name)/2
rep movsw ; initialise name field too
inc dx ; skip the DMD for real top
xchg dx,mem_size ; replace memory size with new value
sub dx,mem_size ; whats the difference ?
mov DMD_LEN,dx ; save it's this length
biosinit20:
; End of RPL support
mov ax,mem_size ; get top of memory
sub ax,MOVE_DOWN
mov mem_max,ax ; last available paragraph
mov init_dseg,ax ; initialisation data lives here
mov cl,4
mov dx,offset DYNAMIC_DATA_END+15
shr dx,cl ; we need this much dynamic data
add ax,dx
; Now we try to relocate the BIOS
mov dx,rcode_len ; we want to keep this much BIOS code
add systemSize,dx ; so add to reserved space in HMA
mov dx,icode_len ; how much do we want to move ?
shr dx,cl
jz biosinit30 ; if ROMed we have nothing to relocate
mov rcode_seg,ax ; relocated BIOS lives here
add ax,dx ; remember how much we allocated
mov dx,rcode_offset
mov si,dx
mov di,dx
shr dx,cl ; DX = para offset of data
sub rcode_seg,dx ; adjust our segment value
mov es,rcode_seg
mov cx,icode_len
rep movsb ; copy it up
biosinit30:
mov dos_cseg,ax ; a relocated DOS image will live here
mov ax,offset biosinit_end+32
mov cl,4 ; Leave the Last Paragraph Free for
shr ax,cl ; himem DMD
neg ax ; Calculate the destination
add ax,mem_size ; Segment for the BIOS relocation
mov cx,offset biosinit_end ; Relocate the BIOSINIT code to
mov si,offset biosinit ; the top of available memory
mov di,si
sub cx,si ; Size of BIOSINIT
mov es,ax ; Initialize ES and copy CX words
rep movsb
push es ; fiddle RETF to relocated code
mov ax,offset relocated_init
push ax
retf
;
; Generic BIOS INIT Patch area
;
include i:patch.cod
;
; BIOSINIT CODE and DATA have now been relocated to high memory
;
relocated_init:
mov ax,cs
cli
mov ss,ax
mov sp,offset stack
sti
mov ds,ax ; All Segment registers now point
mov es,ax ; to the relocated BIOSINIT
call config_init ; initialize setup module
call dd_fixup ; fixup relocatable device drivers
les di,device_root ; initialize all the resident
call resident_device_init ; device drivers
push cs ! pop es
mov dx,1 ; phase one of RPL initialisation
call rploader ; inform RPLoader if present
call Verify386 ; CY set if not a 386
mov ax,mem_current ; get ending address returned by BIOS
jc dont_align
cmp ax,0100h
jae dont_align ; lets be 4 KByte aligned to benefit
mov ax,0100h ; the multi tasker (386 or above)
dont_align:
mov free_seg,ax ; and save as first Free Segment
cmp current_dos,0 ; does the OEM want us to read
jnz dos_reloc ; the DOS file from disk?
mov ax,dos_cseg
mov current_dos,ax ; the file is held on the INIT_DRV with
call read_dos ; the name specified in DOS_NAME
eject
;
; The following code will relocate the DOS code.
;
dos_reloc:
;
; We now move the DOS data to low memory
;
mov ax,current_dos
mov dos_cseg,ax ; Update the DOS Code Segment
mov ds,ax
mov cl,4
mov ax,ds:DOS_CODE ; get size of DOS code
add cs:systemSize,ax ; and add to the system size
shr ax,cl ; convert to para's
mov cs:dosCodeParaSize,ax ; save for EMM386.SYS
mov ax,ds:DOS_OFFSET ; remember we have padding
add cs:dos_coff,ax ; and adjust DOS init offset
shr ax,cl ; also adjust DOS segment
sub cs:dos_cseg,ax ; to account for padding
xor ax,ax
mov es,ax ; ES -> interrupt vectors
mov ax,ds:DOS_DATA ; get # of bytes of DOS data
shr ax,cl ; get para size of DOS data
xchg ax,cs:free_seg ; get seg for DOS data
add cs:free_seg,ax ; remember how much we used
mov es:INT31_SEGMENT,ax ; update the segment value of INT31
mov es,ax ; so ROMMED systems can find PCM_DSEG
mov cs:dos_dseg,ax ; we need to remember where too...
mov si,ds:DOS_CODE ; offset of DOS Data
xor di,di ; destination offset
test DOS_FLAG,1 ; has the DOS Data been compressed
jnz dos_r20 ; yes so call the decompress routine
mov cx,ds:DOS_DATA ; otherwise just copy the data.
rep movsb
jmps dos_r40
;
; This routine will decompress the DOS data area which has
; been compressed after linking using Andy Wightmans data
; compression algorithm.
;
dos_r20:
lodsw ; get control word
mov cx,ax ; as a count
jcxz dos_r40 ; all done
test cx,8000h ; negative ?
jnz dos_r30 ; yes do zeros
rep movsb ; else move in data bytes
jmps dos_r20 ; and to the next
dos_r30:
and cx,7fffh ; remove sign
jcxz dos_r20 ; none to do
xor ax,ax
rep stosb ; fill with zeros
jmps dos_r20
dos_r40:
push cs ! pop ds
push cs ! pop es
mov cl,4 ; reserve space for resident DDSC's
mov ax,DDSC_LEN
mul dev_count ; AX byte are required
add ax,15
shr ax,cl ; AX para are required
xchg ax,free_seg
add free_seg,ax ; we have allocated the space
mov res_ddsc_seg,ax ; point res_ddsc_ptr at the space
mov dx,dos_dseg
sub ax,dx ; DOS resident DDSC_'s use DOS data seg
cmp ax,1000h ; surely we must fit ?
jae dos_r50
shl ax,cl ; offset within pcmode data segment
mov res_ddsc_off,ax
mov res_ddsc_seg,dx ; setup pointer to resident DDSC's
dos_r50:
;
; Call the DOS INIT Code passing all the information setup
; by the BIOS.
;
mov ax,mem_size ; pass the Memory Size, the first free
mov bx,free_seg ; segment and the initial
mov dl,init_drv ; drive to the DOS init routine
cli
mov ds,dos_dseg ; DS -> DOS data segment
callf cs:dos_init
mov es,cs:dos_dseg
mov bx,26h ; ES:BX -> list of lists
mov ax,es:word ptr F52_FCBPTR[bx]
shr ax,1 ! shr ax,1
shr ax,1 ! shr ax,1
and es:word ptr F52_FCBPTR[bx],15
add es:word ptr F52_FCBPTR+2[bx],ax
sti
push cs ! pop ds
mov es,current_dos ; internationalise the yes/no chars
mov di,es:NO_YES_CHARS
mov es,dos_dseg ; ES:DI -> internal table
mov ax,word ptr no_char
stosw ; replace default no chars
mov ax,word ptr yes_char
stosw ; replace default yes chars
push cs ! pop es
add dos_coff,3 ; next dos_init call just fixes up
; segment relocations
mov dx,2 ; phase two of RPL initialisation
call rploader ; inform RPLoader if present
call config_start ; get free memory
call config ; read and process CONFIG.SYS
call config_end ; relocate DOS code and free memory
mov ax,(MS_X_OPEN*256)+2 ; Open for Write
mov dx,offset idle_dev ; Get the IDLE Device Name#
int DOS_INT ; Open the device
jc dos_r70 ; Quit on Error
push ax ; Save the Handle
mov ax,4458h ; Get the address of the IDLE data
int DOS_INT ; area in ES:AX
pop bx ; Restore the Handle
mov idle_off,ax ; Save the data area offset and
mov idle_seg,es ; segment
mov ax,4403h
mov dx,offset idle_off
mov cx,DWORD
int DOS_INT
mov ah,MS_X_CLOSE
int DOS_INT
dos_r70:
call mark_system_memory ; ensure any memory we have allocated
; is marked as system
mov bios_offset,offset cleanup
callf bios ; execute BIOS cleanup code
mov ax,(MS_M_STRATEGY*256)+3
xor bx,bx ; unlink in upper memory region
int 21h
mov dx,3 ; phase three of RPL initialisation
call rploader ; inform RPLoader if present
mov ax,12ffh ; magic cleanup call to MemMAX
mov bx,5 ; to do any tidy ups it wishes
xor cx,cx
xor dx,dx
int 2fh
push cs ! pop es
load_e10:
mov ax,(MS_X_EXEC * 256)+0 ; Exec the Command Processor
mov bx,offset exec_env ; Get the Parameter Block Address
mov dx,offset shell ; and the Command Processor
mov exec_clseg,ds
mov exec_fcb1seg,ds
mov exec_fcb2seg,ds
int DOS_INT ; Go for it
mov ah,MS_C_WRITESTR ; Print an error message and wait for
mov dx,offset bad_exec ; the user to enter new name
int DOS_INT
mov ah,MS_C_READSTR ; get user to input new COMMAND
mov dx,offset shell_ask ; location
int DOS_INT
call crlf ; tidy up with CR/LF
xor bx,bx
mov bl,shell_end
mov shell[bx],bh ; replace CR with NULL
jmps load_e10
eject
;
; Initialise the PSP and inform DOS of the
; location of the BIOSINIT PSP. The MS_P_SETPSP *MUST* be the first
; INT21 function call because the PSP Address is used during the
; entry code except when the INDOS flag is set and certain function
; calls are made.
;
; Then open the Resident character devices so that the dynamically
; devices can output messages to the screen etc.
;
config_start:
mov cl,4
mov bx,ds
mov ax,offset psp ; Now force DOS Plus to use the
shr ax,cl ; internal PSP for all disk and
add bx,ax ; character I/O
mov xftbl_seg,bx ; Update the Handle Table Pointer
mov parent_psp,bx ; and make this the root process
mov ah,MS_P_SETPSP ; Set the current PSP
int DOS_INT
if DOS5
mov ax,3306h
int 21h ; get true version
mov dosVersion,bx ; and plant in initial PSP
endif
call dos_version_check ; make sure we are on correct DOS
mov ax,4458h
int DOS_INT ; we need to access local data
mov drdos_off,bx ; so save a pointer to it
mov drdos_seg,es
mov ax,ext_mem_size
mov es:DRDOS_EXT_MEM[bx],ax ; save extended memory size in DOS
mov ax,5200h
int DOS_INT
mov func52_off,bx
mov func52_seg,es ; save pointer to internal data
if DOS5
mov ax,ext_mem_size
mov es:F52_EXT_MEM[bx],ax ; save extended memory size in DOS
endif
mov ax,(offset TEMP_LDT)/16 ; use our temporary LDT's
add ax,init_dseg ; during system init
mov es:F52_PATHOFF[bx],0 ; point at the LDT's
mov es:F52_PATHSEG[bx],ax
push cs ! pop es
mov ah,MS_M_ALLOC ; Allocate all available memory
mov bx,0FFFFh ; BX is returned with the maximum
int DOS_INT ; available block size
mov ah,MS_M_ALLOC
int DOS_INT
mov mem_first_base,ax ; Base of 1st allocated block
mov mem_current_base,ax ; Base of allocated memory
mov mem_current,ax ; Next available Segment
call config_finish ; Update DOS with the information
; obtained from loading the resident
; drivers.
mov ah,MS_DRV_SET ; Select the Default Drive
mov dl,init_drv ; passed to us by the BIOS
int DOS_INT
mov ah,MS_F_DMAOFF ; Initialise the DMA address for
mov dx,offset search_state ; the Search First State data
int DOS_INT
mov al,init_drv ; get the boot drive then check
test init_flags,INIT_COMSPEC ; flags to see if this is the
jz config_s05 ; default COMSPEC drive.
mov al,comspec_drv
config_s05:
add shell,al ; update the drive letter of shell
add shell_drv,al ; and the reload path
call open_stdaux ; Open STDAUX as internal handle #0
call open_stdcon ; Open Standard CON Devices as #1
mov ah,MS_X_CLOSE ; now close AUX again
mov bx,STDAUX ; for CONFIG processing
int DOS_INT
ret
;
; Relocate the DOS CODE from high memory to immediately above
; the device drivers, buffers etc. Then call the DOS_CLEANUP code
; so that any self segment pointers maintained in the DOS DATA
; can be updated. Then free all the unused memory and reopen the
; standard devices.
;
config_end:
push es
mov al,last_drv ; get lastdrive value
les bx,func52_ptr
cmp al,es:F52_PHYDRV[bx] ; less than the # of Physical drives ?
ja config_end10
mov al,es:F52_PHYDRV[bx] ; ensure minimum of # physical drives
config_end10:
mov es:F52_LASTDRV[bx],al ; set # of drives installed
mov cl,4 ; we will be converting byte-paras
mov ah,LDT_LEN ; we need this many bytes per drive
mul ah ; *lastdrive
add ax,15 ; round LDT's size up to para
shr ax,cl
mov dl,'L' ; allocate LDT's
call alloc_instseg ; Allocate memory AX is destination
mov es:F52_PATHOFF[bx],0 ; point at the LDT's
mov es:F52_PATHSEG[bx],ax ; save seg we just allocated
pop es
call setup_ldt ; initialise LDT structures
call setup_stacks ; allocate stacks
call relocate_system ; relocate system as requested
push es ; Free all of the unused memory
mov es,mem_current_base ; ES: Base Allocated Memory
mov bx,mem_current ; Get the currently allocated memory
sub bx,mem_current_base ; and subtract mem_current_base to
mov ah,MS_M_SETBLOCK ; give the number of paragraphs used
int DOS_INT ; and modify block accordingly
; Kludge - if the CONFIG file has had a line of the form INSTALL= to load a TSR
; then that TSR will have inherited the handles, so bumping the open count, but
; the func 31 exit leaves all these files open. As a result we will get the
; wrong internal file numbers unless we force complete closure. So we keep
; trying to close each internal handle until we get an error.
mov ah,MS_P_GETPSP
int DOS_INT ; get current PSP
mov es,bx
mov cx,PSP_XFNMAX ; Close all the standard handles
les di,PSP_XFTPTR ; and then reopen them in case a
mov bx,0 ; dynamicly loadable device has
cfg_e10: ; replaced the BIOS driver
mov dl,es:[di+bx] ; save old internal handle
mov ah,MS_X_CLOSE
int DOS_INT ; try and close this handle
mov es:[di+bx],dl ; put the internal handle back
jnc cfg_e10 ; and try and close it again
mov es:byte ptr [di+bx],0ffh
inc bx ; mark as closed and try next handle
loop cfg_e10
pop es
;; jmps open_std
open_std:
call open_stdaux ; open AUX device as STDAUX
call open_stdcon ; now STDIN, STDOUT, STDERR
; jmp open_stdprn ; finally STDPRN
open_stdprn:
mov ax,(MS_X_OPEN * 256) + 1
mov dx,offset printer ; Open the PRN device
int DOS_INT
jc open_sp10 ; No PRN device
cmp ax,STDPRN ; If all the previous Opens were
jz open_sp10 ; successful then this is STDPRN
mov bx,ax ; otherwise force this to STDPRN
mov cx,STDPRN
mov ah,MS_X_DUP2
int DOS_INT
mov ah,MS_X_CLOSE
int DOS_INT
open_sp10:
ret
open_stdcon:
mov ax,(MS_X_OPEN * 256) + 2
mov dx,offset console ; Open the CON device
int DOS_INT
jc open_sc10 ; No CON device
mov bx,ax ; First Open should be STDIN
mov cx,STDOUT ; Force Duplicate to STDOUT
mov ah,MS_X_DUP2
int DOS_INT
mov cx,STDERR ; Then Force Duplicate to STDERR
mov ah,MS_X_DUP2
int DOS_INT
open_sc10:
ret
open_stdaux:
mov ax,(MS_X_OPEN * 256) + 2
mov dx,offset auxilary ; Open the AUX device
int DOS_INT ; to get internal handle 0
jc open_sa10 ; No AUX device
mov bx,ax ; Force DUP to STDAUX
mov cx,STDAUX
mov ah,MS_X_DUP2
int DOS_INT
mov ah,MS_X_CLOSE
int DOS_INT
open_sa10:
ret
eject
relocate_system:
push ds ! push es
cmp dos_target_seg,0FFFFh ; is the OS going high ?
jne relocate_system10
call SetupHMA ; make sure HMA chain is established
xor cx,cx
xchg cx,systemHMA ; free up any space reserved for the OS
call FreeHMA
call ReserveCommandHMA ; reserve space for COMMAND.COM
relocate_system10:
call reloc_bios ; move down relocatable drivers
call reloc_dos ; move DOS above drivers if RAM based
xor cx,cx
xchg cx,commandHMA
call FreeHMA ; return command.com HMA space to pool
cli
mov ds,dos_dseg ; DS -> DOS data segment
callf cs:dos_init ; (in case of CS relative fixups)
sti
pop es ! pop ds
ret
eject
reloc_dos: ; move DOS down to just above drivers
;----------
push ds
push es
test init_flags,INIT_ROMCODE ; Run the DOS code in ROM
jz $+5 ! jmp reloc_dos90 ; at CURRENT_DOS - No Code Reloc
mov es,current_dos
mov cx,es:DOS_CODE ; get DOS code size in bytes
mov ax,dos_target_seg ; get DOS target
cmp ax,0FFFFh ; it it seg FFFF ?
jne reloc_dos10
mov es,current_dos
mov dx,es:DOS_OFFSET
call AllocHMA ; allocate CX bytes, offset < DX
jnc reloc_dos50 ; if we can use high memory
xor ax,ax ; can't, so try auto-allocation
reloc_dos10:
test ax,ax ; has a specific address been
jnz reloc_dos40 ; specified ?
push cx ; save DOS code size
xchg ax,cx
mov cl,4
shr ax,cl ; convert to paragraphs
pop cx
cmp hidos,0 ; do we want to relocate DOS ?
je reloc_dos20 ; no, allocate conventionally
call alloc_upper ; else allocate space for the DOS
jnc reloc_dos40 ; in upper memory if possible
reloc_dos20:
mov es,current_dos ; if conventional memory we
mov ax,es:INIT_CODE ; can discard INIT code
cmp history_flg,0 ; is history enabled ?
jne reloc_dos30
mov ax,es:HISTORY_CODE ; no, discard history code as well
reloc_dos30:
push cx
add ax,15
mov cl,4 ; convert to paragraphs
shr ax,cl
pop cx
call alloc_seg_with_padding ; allocate in conventional memory
reloc_dos40:
xchg ax,dx ; save segment address
mov es,current_dos ; point at code
mov ax,es:DOS_OFFSET ; get offset of code start
xor di,di
mov es,dx ; ES:DI -> destination address
push cx ; save DOS size
mov cl,4
shr ax,cl ; AX = header size in para's
sub dx,ax ; adjust DOS segment accordingly
pop cx ; CX = DOS size in bytes
reloc_dos50:
; At this point
; CX = # bytes to move
; ES:DI -> destination
; DX = segment to fixup
;
mov dos_cseg,dx ; new code segment for DOS
mov ds,current_dos ; DS -> DOS code
xor si,si
shr cx,1 ; CX = # of words in DOS
rep movsw ; copy DOS down
reloc_dos90: ; fixups performed
pop es
pop ds
ret
Public HookInt2F
HookInt2F:
;---------
; Hook Int 2F during device driver initialisation so we can intercept
; some broadcasts
; On Entry:
; None (beware DS/ES can be anything)
; On Exit:
; None (All regs preserved)
;
push es
push ax
push bx
les bx,cs:drdos_ptr
mov bx,es:DRDOS_INT2F[bx] ; ES:BX -> Int 2F hooks
mov ax,offset Int2FHandler
xchg ax,es:4[bx] ; get Int 2F offset
mov cs:int2FOff,ax
mov ax,cs
xchg ax,es:6[bx] ; get Int 2F segment
mov cs:int2FSeg,ax
pop bx
pop ax
pop es
ret
Public UnhookInt2F
UnhookInt2F:
;-----------
; Device driver initialisation has finished, so unhook from Int 2F
; On Entry:
; None (beware DS/ES can be anything)
; On Exit:
; None (All regs preserved)
;
push es
push ax
push bx
les bx,cs:drdos_ptr
mov bx,es:DRDOS_INT2F[bx] ; ES:BX -> Int 2F hooks
mov ax,cs:int2FOff
mov es:4[bx],ax ; restore Int 2F offset
mov ax,cs:int2FSeg
mov es:6[bx],ax ; restore Int 2F segment
pop bx
pop ax
pop es
ret
; During device driver init we provide some services on Int 2F
; eg. 12FF for EMM386.SYS and 4A01/4A02 for Windows HIMEM.SYS
Int2FHandler:
;------------
; On Entry:
; callers DS on stack
; On Exit:
; if not handled pass on to BIOS, callers DS on stack, all regs preserved
;
pop ds ; pop DS from stack
cmp ax,4A01h ; Query Free HMA Space ?
je HMAQueryFree
cmp ax,4A02h ; Allocate HMA Space ?
je HMAAlloc
cmp ax,12FFh ; is it a relocation service ?
jne OldInt2F
sti ; if we RETF don't leave IF disabled
cmp bx,9 ; register upper memory link
je DOSUpperMemoryRoot
cmp bx,1 ; Relocate BDOS
jb DOSQuerySize ; what's the size of DOS
je DOSRelocate ; where to put it
cmp bx,3 ; Relocate BIOS
jb BIOSQuerySize ; what's the size of BIOS
je BIOSRelocate ; where to put it
OldInt2F:
push ds ; DS on stack as expected
db JMPF_OPCODE
int2FOff dw 0
int2FSeg dw 0
; Enquire DOS size
DOSQuerySize:
;------------
; On Entry:
; None
; On Exit:
; AX = 0
; DX = DOS Size in para's
;
mov dx,cs:dosCodeParaSize ; DX = para's required for DOS code
jmps RelocExit
; Relocate DOS
DOSRelocate:
;-----------
; On Entry:
; DX = para to reloacte to (FFFF=HMA)
; On Exit:
; AX = 0
;
mov cs:dos_target_seg,dx ; save where
jmps RelocExit
; Enquire BIOS size
BIOSQuerySize:
;-------------
; On Entry:
; None
; On Exit:
; AX = 0
; DX = BIOS Size in para's
;
mov dx,cs:rcode_len ; DX = bytes required for BIOS code
add dx,15
mov cl,4
shr dx,cl ; DX para's required
jmps RelocExit
; Relocate BIOS
BIOSRelocate:
;------------
; On Entry:
; DX = para to reloacte to (FFFF=HMA)
; On Exit:
; AX = 0
;
mov cs:bios_target_seg,dx ; save where
; jmps RelocExit
RelocExit:
xor ax,ax ; indicate success
retf 2
DOSUpperMemoryRoot:
;------------------
les bx,cs:drdos_ptr
mov es:DRDOS_DMD_UPPER[bx],dx ; remember upper memory link
if DOS5
les bx,cs:func52_ptr
mov es:F52_DMD_UPPER[bx],dx ; remember upper memory link
endif
xor ax,ax
retf 2
HMAAlloc:
;--------
; On Entry:
; BX = # bytes to allocate
; On Exit:
; ES:DI -> start of allocated block
; BX trashed
;
push ds
push ax
push cx
push dx
push si
push bp
push cs ! pop ds ; establish data seg
mov cx,bx ; CX = bytes wanted
mov dx,0FFFFh ; anywhere is OK
call AllocHMA ; ES:DI -> allocated data
pop bp
pop si
pop dx
pop cx
pop ax
pop ds
iret
HMAQueryFree:
;------------
; On Entry:
; None
; On Exit:
; BX = Size of block remaining (0 if no HMA)
; ES:DI -> start of available HMA (FFFF:FFFF if no HMA)
;
push ds
push ax
push cx
push dx
push si
push bp
push cs ! pop ds ; establish data seg
call SetupHMA ; allocate the HMA for OS use
les bx,cs:drdos_ptr
mov di,es:DRDOS_HIMEM_ROOT[bx]
mov ax,0FFFFh ; get offset of HMA entry
mov es,ax
test di,di ; do we have a himem root ?
jz HMAQueryFree10 ; no, return failure
mov bx,es:2[di] ; BX = size of region
mov ax,di ; para align the base
add ax,15 ; because the allocation will
and ax,not 15
sub ax,di ; AX bytes left in the para
add di,ax ; bias the starting location
sub bx,ax ; that many less available
ja HMAQueryFree20 ; if non-zero, return it
HMAQueryFree10:
xor bx,bx ; BX = zero on failure
mov di,0FFFFh ; ES:DI -> FFFF:FFFF
HMAQueryFree20:
pop bp
pop si
pop dx
pop cx
pop ax
pop ds
iret
Public AllocHMA
AllocHMA:
;--------
; On Entry:
; CX = bytes to allocate
; DX = offset of allocation
; On Exit:
; CY set if no can do and ES:DI = FFFF:FFFF
; else
; ES:DI -> memory allocated (para aligned)
; CX preserved
; DX = segment to fixup
;
les bx,cs:drdos_ptr
mov di,es:DRDOS_HIMEM_ROOT[bx]
test di,di ; have we a HIMEM chain ?
jz AllocHMA20
cmp di,dx ; low enough for us
ja AllocHMA20
mov ax,0FFFFh ; relocate to magic segment
mov es,ax ; lets examine high memory
mov ax,es:2[di] ; get size of himem entry
mov si,es:[di] ; and get himem link
mov bx,di
add bx,15
and bx,not 15 ; BX is now para aligned
sub bx,di ; BX is bytes left in para
sub ax,bx ; so we only have this much
jc AllocHMA20 ; less than a para ?
add di,15 ; para align the base, dropping
and di,not 15 ; non-aligned bit on floor
cmp ax,cx ; is himem entry big enough ?
jb AllocHMA20 ; no, allocate from 1st MByte
je AllocHMA10 ; just made it!
sub ax,cx ; how much is left
cmp ax,2*WORD ; is it to small to keep ?
jb AllocHMA10 ; no, discard the remainder
mov bx,di ; point to new entry
add bx,cx ; this many byte up
mov es:[bx],si ; fill in link field
mov es:2[bx],ax ; and length
mov si,bx ; make this new root
AllocHMA10:
push cx ; save length of CODE
push dx ; and offset of CODE
les bx,cs:drdos_ptr
mov es:DRDOS_HIMEM_ROOT[bx],si
pop ax ; AX = offset of CODE
mov cl,4
shr ax,cl ; make it paras
mov dx,0ffffh
mov es,dx ; ES:DI -> destination of CODE
mov dx,di
mov cl,4
shr dx,cl ; DX = offset from FFFF in para's
dec dx ; DX = offset from 10000
sub dx,ax ; DX = fixup segment
pop cx ; CX = bytes to move
clc ; made it!
ret
AllocHMA20:
mov di,0FFFFh ; set ES:DI = FFFF:FFFF
mov es,di
stc ; can't do it
ret
Public SetupHMA
SetupHMA:
;--------
; We have a client for the high memory area at segment FFFF
; We should try and setup a high memory free chain
; XMS only supports allocation of the complete area, so try and grab
; it all and do our own sub-allocations within it.
;
push es
les bx,cs:drdos_ptr
cmp es:DRDOS_HIMEM_ROOT[bx],0; do we already have a chain ?
jnz SetupHMA10 ; if so skip XMS allocation
mov ax,4300h ; check for XMS installation
int 2fh
cmp al,80h
jne SetupHMA20
mov ax,4310h ; get address of XMS driver
int 2fh
mov word ptr xms_driver,bx
mov word ptr xms_driver+2,es
mov ah,0 ; version number check
callf xms_driver
cmp dx,1 ; does HiMem exist ?
jne SetupHMA20
mov ah,1 ; allocate whole HiMem
mov dx,0ffffh
callf xms_driver
cmp ax,1 ; did we succeed ?
jne SetupHMA20
mov ah,3 ; enable a20 gate
callf xms_driver
cmp ax,1 ; did we succeed ?
jne SetupHMA20
les bx,cs:drdos_ptr
mov es:DRDOS_HIMEM_ROOT[bx],COMMAND_BASE
mov ax,0FFFFh ; one entry of FFF0 bytes covers
mov es,ax ; the complete HMA
inc ax
mov es:word ptr .COMMAND_BASE,ax
mov es:word ptr .COMMAND_BASE+2,-COMMAND_BASE
mov di,10h ; copy a dummy VDISK header
mov si,offset dummyVDISK
mov cx,10h
rep movsw ; copy up 0x20 bytes
push ds ; now fixup JMPF in hi-memory for CALL5
mov ds,ax ; link for PC-NFS
mov si,4*30h ; DS:SI -> Int 30 vector
lea di,10h[si] ; ES:DI -> himem alias
movsw ! movsw ! movsb ; copy the JMPF
pop ds
SetupHMA10:
les bx,cs:drdos_ptr ; private data area in ES:BX
mov dx,COMMAND_BASE
cmp dx,es:DRDOS_HIMEM_ROOT[bx]
jne SetupHMA20 ; should we be reserving space for OS?
mov cx,systemSize ; we should reserve this much
call ReserveHMA ; for the OS in the HMA
jc SetupHMA20
mov systemHMA,ax ; save for re-use
SetupHMA20:
pop es
ret
Public alloc_instseg
alloc_instseg:
; allocate AX paragraphs for data that will have to be instanced during
; multitasking. if Vladivar kernel available ask that, or else just
; try for normal upper memory
push ax
push bx ; save registers
push cx
mov cx,F_Version ; is the multi-tasker loaded ?
mov ax,OS386_FUNC
int OS386_INT
int 2Fh ; check for Vladivar
test cx,cx ; CX=0 if it's there
pop cx
pop bx
pop ax
jnz alloc_hiseg ; no, allocate normally
push ax
push bx
push cx
push dx
mov dx,ax ; DX = paragraphs required
mov cx,F_RealAllocI ; ask nicely for memory
mov ax,OS386_FUNC
int OS386_INT
pop dx
pop cx
pop bx
jc alloc_intseg10 ; did we get any ?
add sp,WORD
clc ; we've done it !!
ret
alloc_intseg10:
pop ax ; we didn't manage it...
; jmp alloc_hiseg
Public alloc_hiseg
alloc_hiseg:
; allocate AX paragraphs in high memory if possible, otherwise allocate
; it in conventional memory
cmp hidos,0 ; do we want to relocate DOS ?
je alloc_seg ; no, allocate conventionally
call alloc_upper ; try to allocate some upper memory
jc alloc_seg ; can't, so allocate conventional
ret ; else return address of allocated mem
alloc_seg_with_padding:
; On Entry:
; AX = para's required
; DX = minimum acceptable offset
; On Exit:
; AX = base para
;
; If gate A20 is enabled we can't use negative offset's for DOS/BIOS so
; we pad conventional memory to avoid this. Avoid seg=0 while here.
push cx
push dx
add dx,15+16 ; DX is the offset we will be using
mov cl,4 ; so make sure base is high enough
shr dx,cl ; convert "offset" to a segment value
cmp dx,mem_current ; make sure we don't generate a
jbe alloc_seg_nopad ; negative segement value as this
mov mem_current,dx ; will crash if a20 enabled
alloc_seg_nopad: ; pad if necessary
mov dl,'M' ; allocate for DOS
call alloc_seg ; now we can allocate OK
pop dx
pop cx
ret
Public alloc_seg
alloc_seg:
;---------
; On Entry:
; AX = para's required
; DL = subsegment type
; On Exit:
; AX = base para
;
push ds
push cx
mov cx,ax ; remember how much was wanted
inc ax ; allow an extra para for a header
add ax,mem_current ; Return a pointer to AX paragraphs
cmp ax,mem_max ; of memory to the calling routine.
jae alloc_s10
xchg ax,mem_current
mov ds,ax ; DS:0 -> header
inc ax ; AX:0 -> buffer
mov ds:DMD_ID,dl ; remember the type
mov ds:DMD_PSP,ax ; owner = itself
mov ds:DMD_LEN,cx ; size in para
xor cx,cx ; zero rest for cosmetic reasons
mov ds:word ptr DMD_NAME-3,cx
mov ds:word ptr DMD_NAME-2,cx
mov ds:word ptr DMD_NAME,'S'+256*'D'
mov ds:word ptr DMD_NAME+2,cx
mov ds:word ptr DMD_NAME+4,cx
mov ds:word ptr DMD_NAME+6,cx
pop cx
pop ds
ret
alloc_s10:
hlt ; ##jc##
jmps alloc_s10
alloc_upper:
;-----------
; On Entry:
; AX = paragraphs required
; On Exit:
; CY clear: AX = paragraphs address of allocated memory
; CY set: cannot allocate memory (All regs preserved)
;
push bx
push ax ; save para required
cmp himem_base,0 ; we have already allocated some ?
je alloc_upper10 ; nothing to grow, allocate new block
mov bx,himem_size ; himem was this big
add bx,ax ; try and extend it
push es
mov es,himem_base ; point at existing himem
mov ah,MS_M_SETBLOCK ; and try and set to new size
int DOS_INT
pop es
jc alloc_upper10 ; can't grow, so allocate new block
mov ax,himem_base
add ax,himem_size ; return seg above old alloc
pop bx ; recover para required
add himem_size,bx ; add into himem size
pop bx
clc ; success..
ret ; return AX = seg
alloc_upper10:
mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
mov bl,41h ; to best fit, high only
int DOS_INT
pop bx ! push bx ; recover para required in BX
mov ah, MS_M_ALLOC ; and try to allocate them
int DOS_INT
pushf ! push ax ; save CF and possible address
mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
mov bl,0 ; to first fit
int DOS_INT
pop ax ! popf ; restore CF and possible address
jc alloc_upper20 ; can't allocate, use conventional
cmp ax,mem_size ; is it from upper memory ?
ja alloc_upper15 ; yes, we can use it
push es ; it's conventional, free it up
mov es,ax ; seg address in ES
mov ah,MS_M_FREE
int DOS_INT ; free up this memory
pop es
jmps alloc_upper20 ; try again with XMS
alloc_upper15:
mov himem_base,ax ; save base value
pop himem_size ; save size
pop bx ; and return seg in AX
clc ; success..
ret
alloc_upper20:
pop ax
pop bx ; restore regs
push ds ! push es
push bx ! push cx ! push dx ! push si ! push di ! push bp
push ax ; save allocation size
mov ax,4300h ; check for XMS installation
int 2fh
cmp al,80h
jne alloc_upper30
mov ax,4310h ; get address of XMS driver
int 2fh
mov word ptr xms_driver,bx
mov word ptr xms_driver+2,es
pop dx ! push dx ; DX = allocation size
mov ah,10h ; allocate upper memory block
callf xms_driver
cmp ax,1 ; did we succeed ?
jne alloc_upper30
pop ax ; recover allocation size
mov ax,bx ; return para address of himem
pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx
pop es ! pop ds
clc ; success
ret
alloc_upper30:
pop ax ; recover allocation size
pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx
pop es ! pop ds
stc ; failure....
ret
mark_system_memory:
;------------------
; ensure any memory we have allocated is owned by PSP 0008, a magic value
; used to indicate system memory
push es
les bx,func52_ptr ; get internal data in ES:BX
mov es,es:F52_DMDROOT[bx] ; get 1st DMD entry
mov ah,MS_P_GETPSP
int DOS_INT ; get our PSP in BX
mark_sm10:
cmp es:DMD_ID,'M'
je mark_sm20 ; check we have a valid DMD
cmp es:DMD_ID,'Z'
jne mark_sm50 ; stop if we don't
mark_sm20:
cmp bx,es:DMD_PSP ; is it ours ??
jne mark_sm30
mov es:DMD_PSP,0008 ; mark as system
mark_sm30:
cmp es:DMD_PSP,0008 ; if system mark as SC
jne mark_sm40
xor ax,ax ; zero rest for cosmetic reasons
mov ds:word ptr DMD_NAME-3,ax
mov ds:word ptr DMD_NAME-2,ax
mov ds:word ptr DMD_NAME,'S'+256*'C'
mov ds:word ptr DMD_NAME+2,ax
mov ds:word ptr DMD_NAME+4,ax
mov ds:word ptr DMD_NAME+6,ax
mark_sm40:
cmp es:DMD_ID,'Z' ; is it the last DMD ?
je mark_sm50 ; then stop
mov ax,es
inc ax ; skip DMD header and add
add ax,DMD_LEN ; length to find next DMD
mov es,ax
jmps mark_sm10 ; now go and look at that
mark_sm50:
pop es
ret
; Relocate the BIOS code from top of memory
reloc_bios:
mov dx,rcode_offset
mov cx,rcode_len ; we need to relocate this much
test cx,cx ; do we need to move anything ?
jnz reloc_bios10
ret
reloc_bios10:
add cx,15 ; round rcode size up to a para
and cx,not 15
mov ax,bios_target_seg ; where do we go
test ax,ax
jz reloc_bios20 ; zero - do it ourselves
inc ax ; FFFF - unlikely as it's not
jz reloc_bios25 ; currently supported
dec ax ; else we've been given a seg
jmps reloc_bios40
reloc_bios20:
cmp dos_target_seg,0FFFFh ; if DOS goes up, so does BIOS
jne reloc_bios30
reloc_bios25:
call AllocHMA ; in HIGH memory
jnc reloc_bios50
reloc_bios30:
mov ax,cx ; allocate conventionally
shr ax,1 ! shr ax,1 ; in para's of course
shr ax,1 ! shr ax,1
cmp hidos,0 ; do we want to relocate DOS ?
je reloc_bios35 ; no, allocate conventionally
call alloc_upper ; try to allocate some upper memory
jnc reloc_bios40 ; can't, so allocate conventional
reloc_bios35: ; padding out if required
call alloc_seg_with_padding
reloc_bios40:
mov es,ax
xor di,di ; ES:DI -> destination
shr dx,1 ! shr dx,1 ; convert offset to para's
shr dx,1 ! shr dx,1
sub ax,dx ; bias segment appropriately
xchg ax,dx ; and have in DX
reloc_bios50:
push es
push cx
push di
push ds
mov si,rcode_offset
mov ds,rcode_seg
rep movsb
pop ds
mov rcode_seg,dx ; new RCODE location
call dd_fixup ; fixup any device drivers
pop di
pop cx
pop es
ret
;
; The following code performs the fixups necessary for RELOCATABLE executable
; internal device drivers.
dd_fixup:
; On Entry:
; None
; On Exit:
; None
push es
mov di,rcode_seg ; fixup to this segment
mov si,rcode_fixups ; get fixup table
test si,si ; is there one ?
jz dd_fixup20
mov es,bios_seg
dd_fixup10:
lodsw ; get a fixup offset
test ax,ax ; last of the fixups ?
jz dd_fixup20
xchg ax,di ; point to the fixup
stosw ; do the fixup
xchg ax,di ; save segment again
jmps dd_fixup10
dd_fixup20:
pop es
ret
ReserveOSHMA:
;------------
; reserve space in HMA for OS
; On Entry:
; None
; On Exit:
; None
;
ReserveCommandHMA:
;----------------
; reserve space in HMA for COMMAND.COM
; On Entry:
; None
; On Exit:
; None
;
cmp commandHMA,0 ; been here already ??
jne ReserveCommandHMA10
mov cx,COMMAND_SIZE
mov dx,COMMAND_BASE
call ReserveHMA ; reserve the space in HMA
jc ReserveCommandHMA10 ; if we can
mov commandHMA,ax ; save for re-use
ReserveCommandHMA10:
ret
ReserveHMA:
;----------
; reserve some space in the HMA
; On Entry:
; CX = size require
; DX = maximum offset acceptable
; On Exit:
; AX = offset of reserved space
;
push es
call AllocHMA ; allocate space in HIGH memory
jc ReserveHMA10
mov es:word ptr [di],0 ; no link, it's this big
mov es:word ptr 2[di],cx
mov bx,es
mov ax,0FFFFh
sub ax,bx ; AX = para offset adjustment required
mov cl,4
shl ax,cl ; convert to byte offset
add ax,di ; AX = offset from FFFF:0
ReserveHMA10:
pop es
ret
FreeHMA:
;-------
; Return reserved HMA space to pool
; On Entry:
; CX = offset of HMA block to relink (0 = noblock)
; On Exit:
; None
;
jcxz free_himem10 ; no block, don't recycle
push es
push cx ; save offset
les bx,cs:drdos_ptr
pop ax ; recover offset
mov di,ax ; remember offset for later
xchg ax,es:DRDOS_HIMEM_ROOT[bx]; become new head of HMA
mov bx,0FFFFh
mov es,bx ; point ES:DI at our section
stosw ; chain on rest of HMA
pop es
free_himem10:
ret
rploader:
;--------
; On Entry:
; DX = phase code
; On Exit:
; None, All regs preserved
push es
push ax
push bx
push cx
push dx
mov ax,rpl_off ; do we have an RPL sitting on
or ax,rpl_seg ; Int 13h
jz rploader10
mov ax,12ffh ; magic cleanup call to RPL
mov bx,5 ; to do any tidy ups it wishes
xor cx,cx ; following resident BIOS
mov dx,1 ; initialisation
pushf
cli
callf rpl_entry ; fake an INT
rploader10:
pop dx
pop cx
pop bx
pop ax
pop es
ret
Public Verify386
Verify386:
;---------
; On Entry:
; None
; On Exit:
; CY clear if 386 or above
;
push sp ; really old CPU's inc SP
pop ax ; before pushing
cmp ax,sp ; newer ones push original SP
jne Verify386fail
mov ax,3000h ; now try to set IOPL = 3
push ax
popf
pushf
pop bx
and ax,bx ; any IOPL bits set ?
jz Verify386fail
; clc ; it's at least a 386
ret
Verify386fail:
stc ; it's not a 386
ret
INITDATA dseg 'INITDATA'
include initmsgs.def ; Include TFT Header File
extrn history_flg:byte
extrn next_drv:byte
extrn dev_count:byte
;
; PUBLIC Variables which are initialised by the BIOS before the
; BIOSINIT code has been executed.
;
data_start rb 0 ; used to para-align PSP & ENV
Public func52_ptr
func52_ptr rd 0 ; address of internal BDOS variables
func52_off dw 0 ; offset " " "
func52_seg dw 0 ; segment " " "
Public drdos_ptr
drdos_ptr rd 0 ; address of internal BDOS variables
drdos_off dw 0 ; offset " " "
drdos_seg dw 0 ; segment " " "
Public res_ddsc_ptr
res_ddsc_ptr rd 0
res_ddsc_off dw 0
res_ddsc_seg dw 0
Public rcode_offset, rcode_seg, icode_len, rcode_len, rcode_fixups
rcode_offset dw 0 ; current offset of relocated code
rcode_seg dw 0 ; current segment of relocated code
icode_len dw 0 ; initial size of relocated code
rcode_len dw 0 ; final size of relocated code
rcode_fixups dw 0 ; offset of rcode fixup table
Public current_dos
current_dos dw 0 ; Current Segment Address of DOS Code
Public dos_target_seg, bios_target_seg
dos_target_seg dw 0 ; target address for DOS relocation
bios_target_seg dw 0 ; 0000 - auto-relocate
; FFFF - high memory (not allocated)
; xxxx - driver allocated address
dosCodeParaSize dw 0 ; Size of DOS code in para's
systemSize dw COMMAND_SIZE ; BIOS+DOS code sizes are added to
; give total size to reserve in HMA
systemHMA dw 0 ; offset of area in HMA reserved
; for SYSTEM (BIOS/DOS/COMMAND)
commandHMA dw 0 ; offset of area in HMA reserved
; for COMMAND.COM
Public device_root
device_root rd 1 ; Root of Resident Device driver Chain
Public mem_size, ext_mem_size, comspec_drv
Public init_flags, init_drv
mem_size dw 0 ; Total Memory Size (in Paragraphs)
ext_mem_size dw 0 ; Total Extended Memory Size (in KB.)
init_flags dw 0 ; BIOS INIT Flags
init_drv db 0 ; Boot Drive (A is 0 .....)
comspec_drv db 0 ; Default COMSPEC Drive
Public num_stacks, stack_size
num_stacks dw DEF_NUM_STACKS
stack_size dw DEF_SIZE_STACK
Public num_files, num_fcbs, num_fopen
Public country_code, code_page
num_files dw DEF_NUM_FILES ; # of file handles
num_fcbs dw DEF_NUM_FCBS ; # of fcb file handles
num_fopen dw -1 ; "unset" value for fast open
country_code dw DEF_COUNTRY ; Country Code
code_page dw DEF_CODEPAGE ; Code Page
Public dos_name
IF DRDOS35
dos_name db 'DRBDOS SYS',0
ELSE
dos_name db 'IBMDOS COM',0 ; default DOS filename
ENDIF
rpl_name db 'RPLOADER'
rpl_entry rd 0 ; remember RPL entry point for
rpl_off dw 0 ; startup broadcasts
rpl_seg dw 0
eject
;
; Internal variables used by the BIOSINIT code
;
Public bios_seg
bios rd 0 ; Far pointer to the BIOS Cleanup
bios_offset rw 1 ; routines.
bios_seg rw 1
Public init_dseg
init_dseg dw 0 ; Init data segment
Public dos_dseg
dos_dseg dw 0 ; DOS Data Segment Address
Public mem_current_base, mem_current, mem_max
mem_first_base rw 1 ; Base of First Allocated Memory
mem_current_base rw 1 ; Base of Current Allocated Memory
mem_current rw 1 ; Next Free Paragraph
mem_max rw 1 ; Last available Paragraph
dos_init rd 0 ; DOS Initialization Code
dos_coff dw 0 ; DOS Init Code Offset
dos_cseg rw 1 ; DOS Init Code Segment
free_seg rw 1 ; First available paragraph.
xms_driver rd 1 ; address of himem driver
Public hidos
hidos db 0 ; set true if HIDOS requested
himem_base dw 0 ; base of HIMEM seg allocations
himem_size dw 0 ; length of HIMEM seg allocations
Public last_drv
last_drv db 5 ; default is "E:"
console db 'CON',0 ; Default Console Device
printer db 'PRN',0 ; Default Printer Device
auxilary db 'AUX',0 ; Default Auxilary Device
idle_dev db '$IDLE$',0 ; Idle Device Name
idle_off rw 1 ; Idle Data Area Offset
idle_seg rw 1 ; Idle Data Area Segment
dummy_fcb db 0,' '
exec_env dw 0 ; Environment Segment
exec_cloff dw shell_cline ; Command Line Offset
exec_clseg dw 0 ; Command Line Segment
dw dummy_fcb
exec_fcb1seg dw 0 ; FCB 1 Offset and Segment
dw dummy_fcb
exec_fcb2seg dw 0 ; FCB 2 Offset and Segment
rd 1 ; SS:SP
rd 1 ; CS:IP
Public shell_cline
shell_cline db length shell_drv; Initial Command Line
shell_drv db 'A: /P'
db 0Dh
rb 126 - length shell_drv
dummyVDISK db 0, 0, 0 ; jump instruction
db 'VDISK3.3' ; OEM name
dw 128 ; bytes per sector
db 1 ; sectors per allocation unit
dw 1 ; number of reserved sectors
db 1 ; number of FATs
dw 40 ; number of root directory entries
dw 512 ; total number of sectors
db 0FEh ; media descriptor byte
dw 6 ; sectors per FAT
dw 8 ; sectors per track
dw 1 ; number of heads
dw 0 ; number of hidden sectors
dw 1024+64 ; KB of extended memory used
search_state rb 43 ; Search First/Next State
rw 384 ; big stack for ASPI4DOS.SYS driver
stack rw 0
INITPSP DSEG PARA 'INITDATA'
db 'Z' ; dummy DMD header
dw 0008h ; owner is system
dw 0010h ; length of PSP
rb 3 ; pad to 8 bytes
db 'DOS',0,0,0,0,0 ; name field (must be 8 bytes)
psp rb 16h ; Zero Fill PSP Header
parent_psp dw 0 ; parent, patched to itself
db 0FFh, 0FFh, 0FFh ; STDIN, STDOUT, STDERR
db 0FFh, 0FFh ; STDAUX, STDPRN
db 0FFh, 0FFh, 0FFh ; Remainder CLOSED
db 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh
db 0FFh, 0FFh, 0FFh
dw 0000 ; PSP Environment Pointer
dw 0000, 0000 ; DOS User SS:SP
dw 20 ; Maximum of 20 Handles
dw offset PSP_XFT ; Handle Table Offset
xftbl_seg dw 0 ; Handle Table Segment
rb offset PSP_VERSION - offset PSP_RES1
Public dosVersion
dosVersion dw 7 ; DOS version is 7.0
rb PSPILEN - offset PSP_VERSION - 2
; PAD to Partial PSP Size
INITENV DSEG PARA 'INITDATA'
shell_ask db 79 ; max len
shell_end db 0 ; end of the line
Public shell
shell db 'A:\COMMAND.COM', 0
rb 80-length shell
DATAEND DSEG PARA 'INITDATA'
Public biosinit_end
biosinit_end rb 0
end