mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-22 07:54:28 +00:00
1806 lines
47 KiB
Plaintext
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
|