|
|
PAGE ,132 TITLE DXROM.ASM -- Dos Extender ROM Specific Code
; Copyright (c) Microsoft Corporation 1990-1991. All Rights Reserved.
;*********************************************************************** ; ; DXROM.ASM -- Dos Extender ROM Specific Code ; ;----------------------------------------------------------------------- ; ; This module contains code specific to the ROM version of the DOS ; Extender. ; ;----------------------------------------------------------------------- ; ; 11/05/90 jimmat Created. ; ;***********************************************************************
.286p
IFDEF ROM
; ------------------------------------------------------- ; INCLUDE FILE DEFINITIONS ; -------------------------------------------------------
.xlist .sall include segdefs.inc include gendefs.inc include pmdefs.inc include dxrom.inc .list
; ------------------------------------------------------- ; GENERAL SYMBOL DEFINITIONS ; -------------------------------------------------------
; Define some pubilc symbols to be exported for the ROM Image Builder
public __selDXCODE, __selDXDGROUP, __selDXPMCODE
__selDXCODE = SEL_DXCODE __selDXDGROUP = SEL_DXDATA __selDXPMCODE = SEL_DXPMCODE
public __selFirstLDT, __selLDTAlias
__selFirstLDT = SEL_USER __selLDTAlias = SEL_LDT_ALIAS
; ------------------------------------------------------- ; EXTERNAL SYMBOL DEFINITIONS ; -------------------------------------------------------
extrn ParaToLinear:NEAR extrn AllocateLDTSelector:NEAR extrn ChildTerminationHandler:NEAR
externFP NSetSegmentDscr
; ------------------------------------------------------- ; DATA SEGMENT DEFINITIONS ; -------------------------------------------------------
DXDATA segment
extrn selGDTFree:WORD extrn segDXData:WORD extrn ExitCode:BYTE
SaveROMVector dw ?
cparChildMem dw ? ; size of child DOS mem block in para's regOurSSSP dd ? ; SS:SP save location
DXDATA ends
; ------------------------------------------------------- ; CODE SEGMENT VARIABLES ; -------------------------------------------------------
DXCODE segment
; For the ROM version, the following items locate (and size) the ; DGROUP and DXPMCODE segments. These items are 'imported' from ; the ROM Image Builder which sets the values when the ROM image ; is created.
extrn lmaDXDGROUP:DWORD, cparDXDGROUP:ABS, lmaDXPMCODE:DWORD public lmaRomDXPMCode
cparDgroup dw cparDXDGROUP lmaDGroup dd lmaDXDGROUP lmaRomDXPMCode dd lmaDXPMCODE
DXCODE ends
DXPMCODE segment
extrn selDgroupPM:WORD
extrn lmaROMTOC:DWORD
MyLmaROMTOC dd lmaROMTOC
DXPMCODE ends
; ------------------------------------------------------- subttl ROM Real Mode ROM Specific Routines page ; ------------------------------------------------------- ; ROM REAL MODE ROM SPECIFIC ROUTINES ; -------------------------------------------------------
DXCODE segment assume cs:DXCODE
; ------------------------------------------------------- ; ROMEntry -- Setup the special ROM environment needed ; immediately by DOSX. ; ; Note: This routine runs in real mode only! ; ; Input: ES -> PSP for use by DOSX ; Output: CY clear if successful, set if init failed ; DS -> DOSX RAM DGROUP ; DX:AX = far return address to app that invoked DOSX ; Errors: none ; Uses: All except ES
assume ds:NOTHING,es:NOTHING,ss:NOTHING public ROMEntry
ROMEntry proc near
; Allocate a data segment in RAM and copy down the ROM version
mov ah,48h ;allocate RAM for DGROUP mov bx,cparDgroup int 21h jc REAllocFailed ;big trouble if this happens
push ax ;save RAM DGROUP
mov dx, word ptr lmaDGroup[0] mov bx, word ptr lmaDGroup[2] mov cx, 4 xor si, si @@: shr bx, 1 ;determine if its in conventional rcr dx, 1 ;memory and if so the canonical rcr si, 1 ;segment:offset in dx:si loop @B
or bx, bx jnz RECopyFromExtended
RECopyFromConventional: push es ;save es mov es,ax mov ds,dx mov cx,cparDgroup ; (CS variable) shl cx,3 ;DGROUP size in words xor di,di cld rep movsw pop es ;restore es
pop ds ;point to RAM dgroup assume ds:DGROUP, es:NOTHING
clc ;worked!
REAllocFailed:
ret
RECopyFromExtended:
sub sp, 30h mov si, sp push ss pop es mov di, si push ax xor ax,ax mov cx, 18h rep stosw dec ax mov es:[si+10h], ax ; Limits to FFFF mov es:[si+18h], ax mov al, 93h mov es:[si+15h], al ; access to data rw mov es:[si+1Dh], al pop ax mov cx, 4 sub dx, dx @@: shl ax, 1 ;compute new DGROUP lma rcl dx, 1 loop @B mov es:[si+1Ah], ax ;stuff into dest descr mov es:[si+1Ch], dl mov ax, word ptr lmaDGroup[0] mov dx, word ptr lmaDGroup[2] mov es:[si+12h], ax mov es:[si+14h], dl ;put ROM lma in source descr mov cx, cparDGroup shl cx, 3 ;length of dgroup ***in words *** mov ah, 87h ;fn 87h = copy extended memory int 15h jc REExtCopyFailed add sp, 30h pop ds ;get ram address in ds clc ret
REExtCopyFailed: add sp, 32h ;remove stuff from stack stc ret
ROMEntry endp
; ------------------------------------------------------- ; InvokeROMChild -- ROM specific method of invoking the ; child application. ; ; Note: This routine must be called in real mode! ; It returns to the caller after the child returns. Control ; passes directly to ChildTerminationHandler if child does a ; DOS exit call. ; ; Input: none ; Output: CY clear if child executed successfully, set if failed ; AX = error code if failure (8 = insufficient DOS memory) ; Errors: none ; Uses: All except DS
assume ds:DGROUP,es:NOTHING,ss:NOTHING public InvokeROMChild
InvokeROMChild proc near
; Setup the environment for the ROM child app. First, allocate ; the largest conventional memory block available and build a PSP ; at the start of it.
mov bx,-1 ; how big is the largest avail block? dossvc 48h
cmp bx,64 SHL 6 ; is there at least 64k available? jae @f mov ax,8 ; DOS insufficient memory error jmp short IRCFail @@: mov cparChildMem,bx ; save block size dossvc 48h ; allocate block
IF DEBUG jnc @f ; shouldn't fail, but... int 3 @@: ENDIF
; Got conventional memory, now build a PSP at the start of it.
mov dx,ax ; new PSP here mov si,10h ; use this as mem length for now dossvc 55h ; duplicate PSP call
; Set up the termination vector in the child's PSP to point to ; the Dos Extender termination code.
mov es,dx assume es:PSPSEG
mov word ptr [lpfnParent],offset ChildTerminationHandler mov word ptr [lpfnParent+2],cs
; Switch to protected mode to complete initialization of child environment
SwitchToProtectedMode assume ds:DGROUP,es:DGROUP
sti
; Allocate/init a selector mapping first 64k of child memory block & PSP
call AllocateLDTSelector ; get new selector in AX
; DX still has PSP segment, call ParaToLinear ; convert to linear memory address
push bx ; save lma for later push dx push ax ; save mem/PSP selector too
cCall NSetSegmentDscr,<ax,bx,dx,0,0FFFFh,STD_DATA>
; Allocate/init a zero length selector pointing to just past the end of ; the child's memory block and plug the selector into the PSP.
call AllocateLDTSelector ; get another selector
pop es assume es:PSPSEG
mov segMemEnd,ax ; store in child's PSP
mov dx,cparChildMem ; get size of memory block in bytes call ParaToLinear ; in BX:DX
pop ax ; recover lma of block start pop cx ; in CX:AX
add dx,ax adc bx,cx ; BX:DX = lma of block end
cCall NSetSegmentDscr,<segMemEnd,bx,dx,0,0,STD_DATA>
; Allocate/init a selector pointin to our DOS environment block--plug this ; into the child's PSP so it can party on the same env block.
call AllocateLDTSelector
mov dx,segEnviron ; segment from PSP call ParaToLinear
cCall NSetSegmentDscr,<ax,bx,dx,0,7FFFH,STD_DATA>
mov segEnviron,ax ; selector to PSP
; The child environment is now build, invoke the child with DS = ES = ; memory/PSP block. Set the stack 64k (less one word) into the block, ; push our far return address on the stack.
mov word ptr [regOurSSSP],sp ;save DOSX stack location mov word ptr [regOurSSSP+2],ss
mov ax,es ; switch to child stack mov ss,ax mov sp,0FFFEh
push cs ; far return address to us push offset IRCReturn
call GetROMTOCPointer ; push the kernel entry CS:IP on stack assume es:ROMTOC
push word ptr [KRNL_CSIP+2] push word ptr [KRNL_CSIP]
mov ds,ax mov es,ax assume ds:NOTHING,es:NOTHING
xor cx, cx ; tell KRNL386 linear == physical xor dx, dx
retf ; invoke the kernel
public IRCReturn ;public for debugging IRCReturn:
mov ds,selDgroupPM ; restore our DS assume ds:DGROUP
mov ss,word ptr [regOurSSSP+2] ; and our stack mov sp,word ptr [regOurSSSP]
mov ExitCode,al ; save the child exit code
SwitchToRealMode sti
clc ret
IRCFail: stc ret
InvokeROMChild endp
; ------------------------------------------------------- ; ROMInitialization -- This routine performs the initial ROM ; specific DOS Extender initialization. ; ; Note: This routine runs in real mode only! ; ; Input: none ; Output: CY clear if successful, set if init failed ; Errors: none ; Uses: AX
assume ds:DGROUP,es:NOTHING,ss:NOTHING public ROMInitialization
ROMInitialization proc near
; Point 2nd word of DOSX ROM Int vector to the data segment.
push es xor ax,ax mov es,ax
mov ax, word ptr es:[ROMIntVector*4][2] ;save current vector mov SaveROMVector,ax ; contents
mov word ptr es:[ROMIntVector*4][2],ds ;point vector to data pop es
clc
ROMInitFailed:
ret
ROMInitialization endp
; ------------------------------------------------------- ; ROMCleanUp -- This routine performs the ROM specific ; DOS Extender termination clean up. ; ; Note: This routine runs in real mode only! ; ; Input: none ; Output: none ; Errors: none ; Uses: none
assume ds:DGROUP,es:NOTHING,ss:NOTHING public ROMCleanUp
ROMCleanUp proc near
; Remove DOSX Int vector pointer to the data segment.
push es xor ax,ax mov es,ax
mov ax,SaveROMVector ;restore prior contents mov word ptr es:[ROMIntVector*4][2],ax
pop es
ret
ROMCleanUp endp
; ------------------------------------------------------- subttl ROM Real Mode Utility Routines page ; ------------------------------------------------------- ; ROM REAL MODE UTILITY ROUTINES ; -------------------------------------------------------
; GetDXDataRM -- This routine returns the paragraph address of ; the DOS Extender data segment. It should only be called ; by real mode code. ; ; Input: none ; Output: AX = DOSX data segment paragraph address ; Errors: none ; Uses: none
assume ds:NOTHING,es:NOTHING,ss:NOTHING public GetDXDataRM
GetDXDataRM proc near
; Get data segment value from 2nd word of DOSX Int vector
push ds
xor ax,ax mov ds,ax mov ax,word ptr ds:[ROMIntVector*4][2]
IF DEBUG mov ds,ax cmp ax,ds:[segDXData] ; Make sure ax points to the jz @f ; right place int 3 @@: ENDIF pop ds ret
GetDXDataRM endp
; ------------------------------------------------------- ; SetDXDataRM -- This routine sets DS equal to the DOS Extender ; data segment address. It should only be called by real ; mode code. ; ; Input: none ; Output: DS -> DOSX data segment ; Errors: none ; Uses: none
assume ds:NOTHING,es:NOTHING,ss:NOTHING public SetDXDataRM
SetDXDataRM proc near
; Get data segment value from 2nd word of DOSX Int vector
push ax
xor ax,ax mov ds,ax mov ds,word ptr ds:[ROMIntVector*4][2]
IF DEBUG mov ax,ds ; Make sure DS points to the cmp ax,ds:[segDXData] ; right place jz @f int 3 @@: ENDIF pop ax ret
SetDXDataRM endp
DXCODE ends
;****************************************************************
DXPMCODE SEGMENT assume cs:DXPMCODE
; ------------------------------------------------------- subttl ROM Protect Mode Utility Routines page ; ------------------------------------------------------- ; ROM PROTECT MODE UTILITY ROUTINES ; -------------------------------------------------------
; ROMInitLDT -- This routine initializes the LDT descriptors ; defined in the ROM prototype LDT. ; ; Input: none ; Output: none ; Errors: none ; Uses: none
assume ds:DGROUP,es:NOTHING,ss:NOTHING public ROMInitLDT
ROMInitLDT proc near
; Access the ROM Table of Contents to find out where the proto LDT ; is, and how many descriptors it contains.
pusha push ds push es
call GetROMTOCPointer ; Note: uses SEL_SCR0 assume es:ROMTOC
mov cx,cROMsels ; # descriptors defined in proto LDT mov bx,word ptr [lmaROMLDT+2] mov dx,word ptr [lmaROMLDT] ; bx:dx = lma of proto LDT mov ax,FirstROMSel mov di, ax
; Do a quick (and dirty?) allocation of the correct number of LDT selectors. ; DANGER: this code has intimate knowledge of how the LDT free list is kept! ; We could make CX calls to AllocateLDTSelector, but that is slow and would ; do zillions and zillions of segment loads. ; cmp ax,selGDTFree ; next free descriptor in LDT jne alloc_in_chain
IF DEBUG cmp ax,__selFirstLDT ; first one free better be the one jz @f ; the ROM Image Builder used. int 3 @@: ENDIF shl cx,3 ; 'allocate' all these by setting add ax,cx ; the next free to be beyond them mov selGDTFree,ax push SEL_LDT_ALIAS OR STD_RING pop es jmp short sels_alloced
alloc_in_chain: mov si, ax sub si, 8 push SEL_LDT_ALIAS OR STD_RING pop es shl cx, 3 add ax, cx mov es:[si], ax
sels_alloced:
; Copy the prototype descriptors into the actual LDT
cCall NSetSegmentDscr,<SEL_SCR0,bx,dx,0,-1,STD_DATA>
push SEL_SCR0 OR STD_TBL_RING pop ds ; ds -> proto LDT descriptors assume ds:NOTHING
xor si,si
shr cx,1 ; # words of descriptors to copy
cld rep movsw ; move'm into the LDT
pop es pop ds assume ds:DGROUP,es:NOTHING popa
ret
ROMInitLDT endp
; ------------------------------------------------------- ; GetROMTOCPointer -- return ES:0 pointing to the ROM Table of ; Contents. ; ; Note: modifies the SEL_SCR0 descriptor! ; ; Input: none ; Output: ES:0 -> ROM TOC ; Errors: none ; Uses: none
assume ds:DGROUP,es:NOTHING,ss:NOTHING public GetROMTOCPointer
GetROMTOCPointer proc near
push bx push dx
mov bx,word ptr [MyLmaROMTOC+2] mov dx,word ptr [MyLmaROMTOC] ;bx:dx = lma of ROMTOC
cCall NSetSegmentDscr,<SEL_SCR0,bx,dx,0,-1,STD_DATA>
push SEL_SCR0 OR STD_TBL_RING pop es
pop dx pop bx
ret
GetROMTOCPointer endp
; ------------------------------------------------------- ; GetDXDataPM -- This routine returns the paragraph address of ; the DOS Extender data segment. It should only be called ; by protected mode code. ; ; Input: none ; Output: AX = DOSX data segment paragraph address ; Errors: none ; Uses: none
assume ds:NOTHING,es:NOTHING,ss:NOTHING public GetDXDataPM
GetDXDataPM proc near
; Get data segment value from 1st word of DOSX Int vector
push ds
mov ax,SEL_RMIVT or STD_RING mov ds,ax mov ax,word ptr ds:[ROMIntVector*4][2]
pop ds ret
GetDXDataPM endp
if 0 ;*************************************************************** ; ------------------------------------------------------- ; SetDXDataPM -- This routine sets DS equal to the DOS Extender ; data segment address. It should only be called by protected ; mode code. ; ; Input: none ; Output: DS -> DOSX data segment ; Errors: none ; Uses: none
assume ds:NOTHING,es:NOTHING,ss:NOTHING public SetDXDataPM
SetDXDataPM proc near
; Set DS = data segment selector.
push SEL_DXDATA OR STD_RING pop ds ret
SetDXDataPM endp endif ;***************************************************************
DXPMCODE ends
;****************************************************************
ifdef ROMSTUB ;--------------------------------------------------------
********************************************* ********************************************* ***** ***** ***** THIS CODE IS NO LONGER USED ***** ***** ***** ********************************************* *********************************************
DXSTUB SEGMENT assume cs:DXSTUB
; ------------------------------------------------------- subttl Real Mode RAM Stub Segment page ; ------------------------------------------------------- ; REAL MODE RAM STUB SEGMENT ; -------------------------------------------------------
; This segment contains code and data that is moved to conventional ; RAM during initialization. The code is only executed from RAM ; mode and exists for those few cases where it is most convenient ; to have code segement variables. ; ; Note: Since this code is moved to RAM, be very carefull of the ; instructions it contains. In particular, realize the the code segment ; value is going to be different from the copy in ROM.
; ------------------------------------------------------- ; CODE SEGMENT VARIABLES ; -------------------------------------------------------
public PrevInt2FHandler
PrevInt2FHandler dd ?
; ------------------------------------------------------- ; StubInt2FHook -- This code is used by the DOS Extender real mode ; Int 2Fh hook to chain the interrupt to the previous Int 2Fh ; handler. ; ; Note: This code executes in real mode only! ; ; Input: stack = [DS] [IP] [CS] [FL] ; Output: none ; Errors: none ; Uses: none
assume ds:NOTHING,es:NOTHING,ss:NOTHING public StubInt2FHook
StubInt2FHook proc far
pop ds jmp [PrevInt2FHandler]
StubInt2FHook endp
; -------------------------------------------------------
DXSTUB ends
endif ;----------------------------------------------------------------
;****************************************************************
ENDIF ;ROM
end
|