home *** CD-ROM | disk | FTP | other *** search
- ;
- ; prot.asm - Protected mode assembler code for gserver
- ;
- ;************************************************************************/
- ;* Copyright (C) 1986-1988 Phar Lap Software, Inc. */
- ;* Unpublished - rights reserved under the Copyright Laws of the */
- ;* United States. Use, duplication, or disclosure by the */
- ;* Government is subject to restrictions as set forth in */
- ;* subparagraph (c)(1)(ii) of the Rights in Technical Data and */
- ;* Computer Software clause at 252.227-7013. */
- ;* Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138 */
- ;************************************************************************/
- ;
- ; This code can be built in two ways: one to use -REALBREAK and the
- ; other to use -CALLBUFS. The -REALBREAK method will yield higher
- ; performance but is not DPMI compliant. The REALBREAK symbol is
- ; used to signal that the -REALBREAK method should be used. If it
- ; is not defined, the the -CALLBUFS method is used.
- ;
- ; To build for -CALLBUFS method:
- ; 386asm prot.asm -nolist
- ;
- ; To build for -REALBREAK method:
- ; 386asm prot.asm -DREALBREAK -nolist
- ;
-
- ;
- ; Here we define the segments in this module to force their
- ; ordering.
- ;
- ; We need the real mode communications segment if we are going to
- ; use the -REALBREAK method. Otherwise we will use the buffer
- ; allocated with the -CALLBUFS switch for communication.
- ;
- IFDEF REALBREAK
- commseg segment public byte 'realcomm'
- commseg ends
- ENDIF
-
- codeseg segment public byte 'code'
- codeseg ends
-
- dataseg segment public byte 'data'
- dataseg ends
-
- ;
- ; Set up the dgroup appropriately
- ;
- IFDEF REALBREAK
- dgroup group commseg,dataseg
- ELSE
- dgroup group dataseg
- ENDIF
-
- assume cs:codeseg,ds:dgroup,ss:dgroup,es:dgroup
-
- ;
- ; Export the names for the graphics buffer pointer and
- ; size variables.
- ;
- public _gbuffsize,_gbuffp
- public __gbuffsize,__gbuffp
-
- ;
- ; Define the real mode communications segment and its variables
- ; if we are going to use the -REALBREAK method.
- ;
- IFDEF REALBREAK
-
- public _realend
-
- commseg segment public byte 'realcomm'
-
- buffsize equ 4096
-
- __gbuffsize:
- _gbuffsize dd buffsize
- __gbuffp:
- _gbuffp dd _gbuff
- _gbuff db buffsize dup (?)
-
- _realend equ $
-
- commseg ends
-
- ENDIF
-
- codeseg segment public byte 'code'
-
- ;
- ; realload - Load and initialize a real mode driver
- ;
- ; retcode = realload(filenameptr, &realptr);
- ;
- ; int retcode; /* Return code */
- ; char *filenameptr; /* Pointer to the file name */
- ; unsigned long *realptr; /* Segment:offset address of server */
- ;
- ; This routine loads a real mode server and calls the initialization
- ; routine for the server. The caller passes in the file name of
- ; the server to be loaded. No path searching is done by the routine for
- ; file therefore a complete file path must be given for the file or the
- ; file must be located in the current directory. If the load is
- ; successful, then the return code is set to zero and the real mode
- ; address in segment:offset format of the server is returned
- ; to the caller. The server is called by passing this address to
- ; the routine "realcall". If the load is unsuccesful, then the return
- ; code is set to one of the following MS-DOS error codes:
- ;
- ; 2 = File not found or invalid path
- ; 5 = Access denied
- ; 8 = Not enough memory to load program
- ; 10 = Invalid environment segment
- ; 11 = Invalid file format
- ;
-
- public realload,protret ; Publics for High-C
- public _realload,_protret ; Publics for NDP-C
-
- realload proc near
- _realload:
-
-
- ; EQU's for the argument list
-
- #filenamep equ dword ptr [ebp + 8] ; File name pointer
- #srvptrp equ dword ptr [ebp + 12] ; Pointer to returned server address
-
- ; Function prologue
-
- push ebp ; Set-up a stack frame and save registers.
- mov ebp,esp ;
- push ebx ;
- push ecx ;
- push edx ;
- push edi ;
- push esi ;
- push es ;
-
- ; Build up the parameter block for the real mode code that contains
- ; (1) the address of the DOS-Extender routine that switches from real
- ; mode back to protected mode, (2) the protected mode return address,
- ; and (3) the segment pointer to the protected mode PSP. This
- ; parameter block is passed to the real mode server as a command
- ; tail in the PSP.
-
- sub ebx,ebx ; Convert the address of the protected
- mov ax,4h ; mode PSP from a protected mode selector
- mov es,ax ; to a real mode segment pointer.
- sub ecx,ecx ;
- mov ax,250Fh ;
- int 21h ;
-
- push ecx ; Save it in our parameter block for use
- pop cx ; by the real mode code.
- pop cx ;
- mov protpsp,cx ;
-
- mov protcs,cs ; Save the CS register for our protected mode
- ; return address. The offset is filled in
- ; at link time.
-
- mov ax,250DH ; Get the real-to-protected mode
- int 21h ; call-back address and save it in our
- mov callback,eax ; parameter block.
-
- ;
- ; If we are using the -CALLBUFS method, then we will set up the _gbuffp
- ; and _gbuffsize variables to point at and contain the size of the
- ; intermode call buffer. We will be using this buffer as the real mode
- ; communications buffer. The far pointer to the buffer came back in es:edx
- ; after the 250D call. We will also make sure that the buffer is at least
- ; 1Kb in size. If it is too small, we will return an insufficient memory
- ; error.
- ;
- IFNDEF REALBREAK
- cmp ecx,1024 ; Is the buffer big enough?
- jge #l10 ; Yes, go set up pointer and size variables.
- mov eax,8 ; No, load insufficient memory error code
- jmp #ret ; and branch to return it.
- #l10:
- lea esi,_gbuffp ; Get a pointer to the far pointer
- mov [esi],edx ; Store the offset portion of the pointer
- mov [esi+4],es ; and then the segment portion of the pointer
- mov _gbuffsize,ecx ; Store the size of the bugger.
- ENDIF
-
- ; We now switch to a special stack for the EXEC system call because
- ; the stack will be re-used in strange ways when we exit from the
- ; real mode code and it will conflict with the regular stack.
-
- mov ebpsave,ebp ; Save EBP and SS:ESP.
- mov espsave,esp ;
- mov sssave,ss ;
-
- mov edx,#filenamep ; Load the file name pointer into EDX
- ; while we still have the caller's
- ; stack.
-
- mov esp,offset endxstack ; Switch to the EXEC stack.
-
- ; Load the real mode server and execute its initialization code.
- ; We use the special EXEC system call (25C3) instead of system
- ; call 4B so that the DOS-Extender run-time environment is not
- ; disturbed.
-
- mov ebx,offset ldparm ; EXEC to the real mode program.
- push ds ;
- pop es ;
- mov ax,25C3H ;
- int 21H ;
-
- jc #err ; Branch if a load error.
-
- jmp exitret ; If EXEC returns it must be an exit
- ; from the real mode code. Therefore
- ; go to the exit routine.
-
- ; If everything went okay, we get control back to the label
- ; "protret" from the real mode initialization routine.
-
- protret:
- _protret:
-
- mov ssexit,ss ; Save the current stack for when we
- mov espexit,esp ; want to return to the real mode
- ; code in order to force an exit.
-
- mov ebp,ebpsave ; Switch back to our regular stack.
- mov ss,sssave ;
- mov esp,espsave ;
-
- mov ebx,#srvptrp ; Return the server pointer to the caller.
- mov [ebx],eax ;
-
- call psprest ; Restore the protected mode PSP.
-
- sub eax,eax ; Zero the return to indicate a successful
- ; load.
-
- #ret: pop es ; Restore the registers and return.
- pop esi ;
- pop edi ;
- pop edx ;
- pop ecx ;
- pop ebx ;
- pop ebp ;
- ret ;
-
- ; Error exit code
-
- #err: mov ebp,ebpsave ; Switch back to our regular stack.
- mov ss,sssave ;
- mov esp,espsave ;
-
- jmp #ret ; Go return.
-
- realload endp
-
-
- ;
- ; realcall - Call a real mode procedure and pass in a single far
- ; pointer argument
- ;
- ; retcode = realcall(funcptr, dataptr);
- ;
- ; int retcode; /* Return code */
- ; unsigned long funcptr; /* Segment:offset address of function */
- ; unsigned long dataptr; /* Segment:offset address of data */
- ;
- ; This function is used to call a real mode function from protected
- ; mode. The caller passes in the real mode address in segment:offset
- ; format of the real mode function to be called as well as a single
- ; real mode address to a data block to be passed to the real mode
- ; function. The return code from the routine is the contents of the
- ; EAX register that the real mode function exits with.
- ;
-
- public realcall ; Public for High-C
- public _realcall ; Public for NDP-C
-
- realcall proc near
- _realcall:
-
- ; Argument list EQU's
-
- #funcptr equ dword ptr [ebp + 8]
- #farptr equ dword ptr [ebp + 12]
-
- ; This routine calls the real mode function using
- ; system call number 250E.
-
- push ebp ; Set-up a stack frame.
- mov ebp,esp ;
- push ebx ;
- push ecx ;
- push edx ;
- push edi ;
- push esi ;
-
- push #farptr ; Call the real mode procedure.
- mov ebx,#funcptr ;
- mov ecx,2 ;
- mov ax,250eh ;
- int 21h ;
-
- add esp,4 ; Clean up the stack.
-
- pop esi ; Restore the registers.
- pop edi ;
- pop edx ;
- pop ecx ;
- pop ebx ;
- pop ebp ;
-
- ret ; Return.
-
- realcall endp
-
-
- ;
- ; realexit - Force the real mode code to exit
- ;
- ; realexit();
- ;
- ; The "realexit" routine is called to force the real mode server to
- ; exit. It must be called by the protected mode code so that the
- ; memory allocated to the real mode code is freed and the real mode
- ; open files are closed. The routine is implemented by returning
- ; to the real mode code to the point when it did a call back after
- ; the EXEC system call.
- ;
-
- public realexit
- public _realexit
-
- realexit proc near
- _realexit:
-
- ; Argument list EQU's
-
- #funcptr equ dword ptr [ebp + 8]
-
- ; Function prologue
-
- push ebp ; Set-up a stack frame.
- mov ebp,esp ;
- push ebx ;
- push ecx ;
- push edx ;
- push edi ;
- push esi ;
- push es ;
-
-
- ; Save the stack pointer
-
- mov ebpsave,ebp ; Save EBP and SS:ESP.
- mov espsave,esp ;
- mov sssave,ss ;
-
-
- ; Switch back to the stack that we had when we returned from EXEC
-
- mov ss,ssexit ; Reload SS:ESP.
- mov esp,espexit ;
-
- ; Turn on the real mode exit flag
-
- mov exitflag,1 ;
-
- ; Return back to the real mode code which will then do an exit
-
- db 0cbh ; Use a far return instruction to go back
- ; to the real mode code.
-
-
- ; Switch back to the standard protected mode stack and return.
-
- exitret:
-
- cmp exitflag,0 ; Branch if the exit flag is off. (oops!)
- je #err ;
-
- mov exitflag,0 ; Clear the exit flag.
-
- mov ebp,ebpsave ; Switch back to our regular stack.
- mov ss,sssave ;
- mov esp,espsave ;
-
- call psprest ; Restore the protected mode PSP.
-
- pop es ; Restore the registers and return.
- pop esi ;
- pop edi ;
- pop edx ;
- pop ecx ;
- pop ebx ;
- pop ebp ;
- ret ;
-
- #err: mov edx,offset #errmsg ; Output error message "Fatal error:
- push cs ; Unexpected exit from real mode code.".
- pop ds ;
- mov ah,09h ;
- int 21h ;
-
- mov ax,4c01h ; Exit ourselves.
- int 21h ;
-
- #errmsg db 'Fatal error: Unexpected exit from real mode code.'
- db 0dh,0ah,'$'
-
- realexit endp
-
-
- ;
- ; prottoreal - Convert a protected mode address to a real mode address
- ;
- ; realptr = prottoreal(offset32, selector);
- ;
- ; unsigned long realptr; /* Segment:offset real mode address */
- ; unsigned long offset32; /* Protected mode offset */
- ; unsigned short selector;/* Protected mode selector */
- ;
- ; This routine converts a 48-bit protected mode pointer (selector +
- ; 32-bit offset) to the equivalent segment:offset real mode address.
- ; If the protected mode address maps to a memory location outside of
- ; the first 1-megabyte of the real mode address space, then a NULL
- ; pointer is returned.
- ;
-
- public prottoreal
- public _prottoreal
-
- prottoreal proc near
- _prottoreal:
-
- ; Argument list EQU's
-
- #offset equ dword ptr [ebp + 8]
- #sel equ word ptr [ebp + 12]
-
- ; System call 250F does all of the work for us
-
- push ebp ; Save all of the registers
- mov ebp,esp ;
- push ebx ;
- push ecx ;
- push es ;
-
- mov ebx,#offset ; Do the conversion.
- mov es,#sel ;
- sub ecx,ecx ;
- mov ax,250fh ;
- int 21h ;
-
- jnc #skip ; If there is an error, return a null
- sub ecx,ecx ; pointer.
-
- #skip: mov eax,ecx ; Load the final real pointer into EAX.
-
- pop es ; Clean up.
- pop ecx ;
- pop ebx ;
- pop ebp ;
-
- ret ; Return.
-
- prottoreal endp
-
-
- ;
- ; psprest - Restore the protected mode PSP
- ;
- ; This routine is only used internally by this module.
- ;
-
- psprest proc near ;
-
- push ebx ; Save registers.
- push es ;
-
- mov bx,protpsp ; Switch back to the protected mode PSP.
- mov ah,50h ;
- int 21h ;
-
- pop es ; Restore registers.
- pop ebx ;
-
- ret ; Return.
-
- psprest endp
-
- codeseg ends
-
- ;
- ; The data segment
- ;
-
- dataseg segment public byte 'data'
-
- IFNDEF REALBREAK
- ;
- ; If we are using the -CALLBUFS method, then we will put the
- ; far pointer to the intermode call buffer and its size here.
- ;
- __gbuffsize:
- _gbuffsize dd ?
- __gbuffp:
- _gbuffp dp ?
- ENDIF
-
- ;
- ; ldparm - Parameter block using by the EXEC system call to
- ; load the real mode server
- ;
-
- ldparm dd 0 ; Environment offset
- dw 0 ; Environment selector
- dd offset cmdtail ; Offset of the command tail
- dw 14h ; Selector of the command tail
-
-
- ;
- ; The parameter block passed to the real mode code as a fake
- ; command tail. The format of the parameter block is:
- ;
- ; word 0 - Offset of the 386|DOS-Extender routine that
- ; the real mode server calls to switch back
- ; to protected mode
- ; word 2 - Segment of the 386|DOS-Extender routine that
- ; the real mode code calls to switch back
- ; to protected mode
- ; dword 4 - 32-bit protected mode offset that the real
- ; mode code is to return to when it completes
- ; its initialization
- ; word 8 - Real segment pointer to the PSP of the protected
- ; mode code
- ;
-
- cmdtail db 12 ; Length of the command tail is 12
- callback dd ? ; First address is call back address
- dd protret ; Second address is the return address
- protcs dw ?
- protpsp dw ? ; Protected mode PSP segment pointer
- db 0dh ; CR to make DOS happy
-
- ;
- ; Saved registers
- ;
-
- ebpsave dd ? ; Saved protected mode EBP
- espsave dd ? ; Saved protected mode ESP
- sssave dw ? ; Saved protected mode SS
-
- ssexit dw ? ; Saved SS for exit
- espexit dd ? ; Save ESP for exit
-
- ;
- ; Special stack used only during the EXEC call
- ;
-
- xstack db 512 dup (?) ;
- endxstack label byte
-
-
- ;
- ; Misc. variables
- ;
-
- exitflag db 0 ; Exiting from real mode server flag
-
- dataseg ends
-
- end
-