; 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