1;; -----------------------------------------------------------------------
2;;
3;;   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
4;;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
5;;
6;;   This program is free software; you can redistribute it and/or modify
7;;   it under the terms of the GNU General Public License as published by
8;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9;;   Boston MA 02111-1307, USA; either version 2 of the License, or
10;;   (at your option) any later version; incorporated herein by reference.
11;;
12;; -----------------------------------------------------------------------
13
14;;
15;; callback.inc
16;;
17;; Callbacks from 32-bit mode to 16-bit mode
18;;
19
20;
21; 16-bit intcall/farcall handling code
22;
23
24;
25; 32-bit support code
26;
27		bits 32
28		section .text
29
30;
31; Intcall/farcall invocation.  We manifest a structure on the real-mode stack,
32; containing the com32sys_t structure from <com32.h> as well as
33; the following entries (from low to high address):
34; - Target offset
35; - Target segment
36; - Return offset
37; - Return segment (== real mode cs == 0)
38; - Return flags
39;
40		global core_farcall:function hidden
41core_farcall:
42		mov eax,[esp+1*4]		; CS:IP
43		jmp core_syscall
44
45		global core_intcall:function hidden
46core_intcall:
47		movzx eax,byte [esp+1*4]	; INT number
48		mov eax,[eax*4]			; Get CS:IP from low memory
49
50core_syscall:
51		pushfd				; Save IF among other things...
52		inc dword [CallbackCtr]
53		push ebx
54		push ebp
55		push esi
56		push edi
57		push dword [CallbackSP]
58
59		cld
60
61		movzx edi,word [word RealModeSSSP]
62		movzx ebx,word [word RealModeSSSP+2]
63		sub edi,54		; Allocate 54 bytes
64		mov [word RealModeSSSP],di
65		shl ebx,4
66		add edi,ebx		; Create linear address
67
68		mov esi,[esp+8*4]	; Source regs
69		xor ecx,ecx
70		mov cl,11		; 44 bytes to copy
71		rep movsd
72
73		; EAX is already set up to be CS:IP
74		stosd			; Save in stack frame
75		mov eax,.rm_return	; Return seg:offs
76		stosd			; Save in stack frame
77		mov eax,[edi-12]	; Return flags
78		and eax,0x200ed7	; Mask (potentially) unsafe flags
79		mov [edi-12],eax	; Primary flags entry
80		stosw			; Return flags
81
82		mov bx,.rm
83		jmp enter_rm	; Go to real mode
84
85		bits 16
86		section .text16
87.rm:
88		mov ax,sp
89		add ax,9*4+4*2
90		mov [CallbackSP],ax
91		pop gs
92		pop fs
93		pop es
94		pop ds
95		popad
96		popfd
97		retf				; Invoke routine
98
99.rm_return:
100		; We clean up SP here because we don't know if the
101		; routine returned with RET, RETF or IRET
102		mov sp,[cs:CallbackSP]
103		pushfd
104		pushad
105		push ds
106		push es
107		push fs
108		push gs
109		mov ebx,.pm_return
110		jmp enter_pm
111
112		; On return, the 44-byte return structure is on the
113		; real-mode stack, plus the 10 additional bytes used
114		; by the target address (see above.)
115		bits 32
116		section .text
117.pm_return:
118		movzx esi,word [word RealModeSSSP]
119		movzx eax,word [word RealModeSSSP+2]
120		mov edi,[esp+9*4]	; Dest regs
121		shl eax,4
122		add esi,eax		; Create linear address
123		and edi,edi		; NULL pointer?
124		jnz .do_copy
125.no_copy:	mov edi,esi		; Do a dummy copy-to-self
126.do_copy:	xor ecx,ecx
127		mov cl,11		; 44 bytes
128		rep movsd		; Copy register block
129
130		add dword [word RealModeSSSP],54
131					; Remove from stack
132
133		pop dword [CallbackSP]
134		dec dword [CallbackCtr]
135		jnz .skip
136		call [core_pm_hook]
137.skip:
138		pop edi
139		pop esi
140		pop ebp
141		pop ebx
142		popfd
143		ret			; Return to 32-bit program
144
145;
146; Cfarcall invocation.  We copy the stack frame to the real-mode stack,
147; followed by the return CS:IP and the CS:IP of the target function.
148; The value of IF is copied from the calling routine.
149;
150		global core_cfarcall:function hidden
151core_cfarcall:
152		pushfd				; Save IF among other things...
153		inc dword [CallbackCtr]
154		push ebx
155		push ebp
156		push esi
157		push edi
158		push dword [CallbackSP]
159
160		cld
161		mov ecx,[esp+9*4]		; Size of stack frame
162
163		movzx edi,word [word RealModeSSSP]
164		movzx ebx,word [word RealModeSSSP+2]
165		mov [word CallbackSP],di
166		sub edi,ecx		; Allocate space for stack frame
167		and edi,~3		; Round
168		sub edi,4*3		; Return pointer, return value, EFLAGS
169		mov [word RealModeSSSP],di
170		shl ebx,4
171		add edi,ebx		; Create linear address
172
173		mov eax,[esp+5*4]	; EFLAGS from entry
174		and eax,0x202		; IF only
175		stosd
176		mov eax,[esp+7*4]	; CS:IP
177		stosd			; Save to stack frame
178		mov eax,.rm_return	; Return seg:off
179		stosd
180		mov esi,[esp+8*4]	; Stack frame
181		mov eax,ecx		; Copy the stack frame
182		shr ecx,2
183		rep movsd
184		mov ecx,eax
185		and ecx,3
186		rep movsb
187
188		mov bx,.rm
189		jmp enter_rm
190
191		bits 16
192		section .text16
193.rm:
194		popfd
195		retf
196.rm_return:
197		mov sp,[cs:CallbackSP]
198		mov esi,eax
199		mov ebx,.pm_return
200		jmp enter_pm
201
202		bits 32
203		section .text
204.pm_return:
205		mov eax,esi
206		; EDX already set up to be the RM return value
207		pop dword [CallbackSP]
208		dec dword [CallbackCtr]
209		jnz .skip
210		call [core_pm_hook]
211.skip:
212		pop ebx
213		pop ebp
214		pop esi
215		pop edi
216		popfd
217		ret
218
219		section .bss16
220		alignb 4
221		global core_pm_hook
222CallbackSP	resd 1			; SP saved during callback
223CallbackCtr	resd 1
224
225		bits 16
226		section .text16
227