blob: f1332e8e24a88f6b1a4b1e85d78098a3617242dc [file] [log] [blame]
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;; Boston MA 02111-1307, USA; either version 2 of the License, or
;; (at your option) any later version; incorporated herein by reference.
;;
;; -----------------------------------------------------------------------
;;
;; callback.inc
;;
;; Callbacks from 32-bit mode to 16-bit mode
;;
;
; 16-bit intcall/farcall handling code
;
;
; 32-bit support code
;
bits 32
section .text
;
; Intcall/farcall invocation. We manifest a structure on the real-mode stack,
; containing the com32sys_t structure from <com32.h> as well as
; the following entries (from low to high address):
; - Target offset
; - Target segment
; - Return offset
; - Return segment (== real mode cs == 0)
; - Return flags
;
global core_farcall:function hidden
core_farcall:
mov eax,[esp+1*4] ; CS:IP
jmp core_syscall
global core_intcall:function hidden
core_intcall:
movzx eax,byte [esp+1*4] ; INT number
mov eax,[eax*4] ; Get CS:IP from low memory
core_syscall:
pushfd ; Save IF among other things...
inc dword [CallbackCtr]
push ebx
push ebp
push esi
push edi
push dword [CallbackSP]
cld
movzx edi,word [word RealModeSSSP]
movzx ebx,word [word RealModeSSSP+2]
sub edi,54 ; Allocate 54 bytes
mov [word RealModeSSSP],di
shl ebx,4
add edi,ebx ; Create linear address
mov esi,[esp+8*4] ; Source regs
xor ecx,ecx
mov cl,11 ; 44 bytes to copy
rep movsd
; EAX is already set up to be CS:IP
stosd ; Save in stack frame
mov eax,.rm_return ; Return seg:offs
stosd ; Save in stack frame
mov eax,[edi-12] ; Return flags
and eax,0x200ed7 ; Mask (potentially) unsafe flags
mov [edi-12],eax ; Primary flags entry
stosw ; Return flags
mov bx,.rm
jmp enter_rm ; Go to real mode
bits 16
section .text16
.rm:
mov ax,sp
add ax,9*4+4*2
mov [CallbackSP],ax
pop gs
pop fs
pop es
pop ds
popad
popfd
retf ; Invoke routine
.rm_return:
; We clean up SP here because we don't know if the
; routine returned with RET, RETF or IRET
mov sp,[cs:CallbackSP]
pushfd
pushad
push ds
push es
push fs
push gs
mov ebx,.pm_return
jmp enter_pm
; On return, the 44-byte return structure is on the
; real-mode stack, plus the 10 additional bytes used
; by the target address (see above.)
bits 32
section .text
.pm_return:
movzx esi,word [word RealModeSSSP]
movzx eax,word [word RealModeSSSP+2]
mov edi,[esp+9*4] ; Dest regs
shl eax,4
add esi,eax ; Create linear address
and edi,edi ; NULL pointer?
jnz .do_copy
.no_copy: mov edi,esi ; Do a dummy copy-to-self
.do_copy: xor ecx,ecx
mov cl,11 ; 44 bytes
rep movsd ; Copy register block
add dword [word RealModeSSSP],54
; Remove from stack
pop dword [CallbackSP]
dec dword [CallbackCtr]
jnz .skip
call [core_pm_hook]
.skip:
pop edi
pop esi
pop ebp
pop ebx
popfd
ret ; Return to 32-bit program
;
; Cfarcall invocation. We copy the stack frame to the real-mode stack,
; followed by the return CS:IP and the CS:IP of the target function.
; The value of IF is copied from the calling routine.
;
global core_cfarcall:function hidden
core_cfarcall:
pushfd ; Save IF among other things...
inc dword [CallbackCtr]
push ebx
push ebp
push esi
push edi
push dword [CallbackSP]
cld
mov ecx,[esp+9*4] ; Size of stack frame
movzx edi,word [word RealModeSSSP]
movzx ebx,word [word RealModeSSSP+2]
mov [word CallbackSP],di
sub edi,ecx ; Allocate space for stack frame
and edi,~3 ; Round
sub edi,4*3 ; Return pointer, return value, EFLAGS
mov [word RealModeSSSP],di
shl ebx,4
add edi,ebx ; Create linear address
mov eax,[esp+5*4] ; EFLAGS from entry
and eax,0x202 ; IF only
stosd
mov eax,[esp+7*4] ; CS:IP
stosd ; Save to stack frame
mov eax,.rm_return ; Return seg:off
stosd
mov esi,[esp+8*4] ; Stack frame
mov eax,ecx ; Copy the stack frame
shr ecx,2
rep movsd
mov ecx,eax
and ecx,3
rep movsb
mov bx,.rm
jmp enter_rm
bits 16
section .text16
.rm:
popfd
retf
.rm_return:
mov sp,[cs:CallbackSP]
mov esi,eax
mov ebx,.pm_return
jmp enter_pm
bits 32
section .text
.pm_return:
mov eax,esi
; EDX already set up to be the RM return value
pop dword [CallbackSP]
dec dword [CallbackCtr]
jnz .skip
call [core_pm_hook]
.skip:
pop ebx
pop ebp
pop esi
pop edi
popfd
ret
section .bss16
alignb 4
global core_pm_hook
CallbackSP resd 1 ; SP saved during callback
CallbackCtr resd 1
bits 16
section .text16