summaryrefslogtreecommitdiff
path: root/core/callback.inc
blob: a33b5825f75e7d3e098be67375b652f3895edc9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
;; -----------------------------------------------------------------------
;;
;;   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
core_farcall:
		mov eax,[esp+1*4]		; CS:IP
		jmp core_syscall

		global core_intcall
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...
		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,0x200cd7	; 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:
		pop gs
		pop fs
		pop es
		pop ds
		popad
		popfd
		mov [cs:CallbackSP],sp
		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]
		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.
;
		global core_cfarcall
core_cfarcall:
		pushfd				; Save IF among other things...
		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*2		; Return pointer, return value
		mov [word RealModeSSSP],di
		shl ebx,4
		add edi,ebx		; Create linear address

		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:
		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]
		pop ebx
		pop ebp
		pop esi
		pop edi
		popfd
		ret

		bits 16
		section .bss16
		alignb 4
CallbackSP	resd 1			; SP saved during callback

		bits 16
		section .text16