core: make the intcall/farcall/cfarcall routines reentrant
[profile/ivi/syslinux.git] / core / com32.inc
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 ;; com32.inc
16 ;;
17 ;; Common code for running a COM32 image
18 ;;
19
20 ;
21 ; Load a COM32 image.  A COM32 image is the 32-bit analogue to a DOS
22 ; .com file.  A COM32 image is loaded at address 0x101000, with %esp
23 ; set to the high end of usable memory.
24 ;
25 ; A COM32 image should begin with the magic bytes:
26 ; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and
27 ; "mov ax,0x4cff; int 0x21" in 16-bit mode.  This will abort the
28 ; program with an error if run in 16-bit mode.
29 ;
30
31 pm_entry        equ 101000h
32
33                 section .text16
34 is_com32_image:
35                 push si                 ; Save file handle
36                 push eax                ; Save file length
37
38                 call make_plain_cmdline
39                 ; Copy the command line into the low cmdline buffer
40                 mov ax,real_mode_seg
41                 mov fs,ax
42                 mov si,cmd_line_here
43                 mov di,command_line
44                 mov cx,[CmdLinePtr]
45                 inc cx                  ; Include final null
46                 sub cx,si
47                 fs rep movsb
48
49                 call comboot_setup_api  ; Set up the COMBOOT-style API
50
51                 mov edi,pm_entry        ; Load address
52                 pop eax                 ; File length
53                 pop si                  ; File handle
54                 xor dx,dx               ; No padding
55                 mov bx,abort_check      ; Don't print dots, but allow abort
56                 call load_high
57
58 com32_start:
59                 ;
60                 ; Point the stack to the end of (permitted) high memory
61                 ;
62                 mov eax,[HighMemRsvd]
63                 xor ax,ax                       ; Align to a 64K boundary
64                 mov [PMESP],eax
65                 mov bx,.pm                      ; Where to go in PM
66                 jmp enter_pm
67
68 ;
69 ; This is invoked right before the actually starting the COM32
70 ; progam, in 32-bit mode...
71 ;
72                 bits 32
73 .pm:
74                 ; Set up the calling stack frame
75
76                 push dword [HighMemSize]        ; Memory managed by Syslinux
77                 push dword core_cfarcall        ; Cfarcall entry point
78                 push dword core_farcall         ; Farcall entry point
79                 push dword (1 << 16)            ; 64K bounce buffer
80                 push dword (xfer_buf_seg << 4)  ; Bounce buffer address
81                 push dword core_intcall         ; Intcall entry point
82                 push dword command_line         ; Command line pointer
83                 push dword 7                    ; Argument count
84                 sti                             ; Interrupts OK now
85                 call pm_entry                   ; Run the program...
86                 ; ... on return, fall through to com32_exit ...
87
88 com32_exit:
89                 mov bx,.rm
90                 jmp enter_rm
91
92                 bits 16
93 .rm:
94                 mov dword [PMESP],__stack_end   ; Stop use of COM32 stack
95                 sti
96                 jmp enter_command
97
98 ;
99 ; 16-bit intcall/farcall handling code
100 ;
101                 bits 16
102
103 com32_sys_rm:
104                 pop gs
105                 pop fs
106                 pop es
107                 pop ds
108                 popad
109                 popfd
110                 mov [cs:Com32SysSP],sp
111                 retf                            ; Invoke routine
112 .return:
113                 ; We clean up SP here because we don't know if the
114                 ; routine returned with RET, RETF or IRET
115                 mov sp,[cs:Com32SysSP]
116                 pushfd
117                 pushad
118                 push ds
119                 push es
120                 push fs
121                 push gs
122                 mov bx,com32_syscall.resume
123                 jmp enter_pm
124
125 ;
126 ; 16-bit cfarcall handing code
127 ;
128 com32_cfar_rm:
129                 retf
130 .return:
131                 mov sp,[cs:Com32SysSP]
132                 mov esi,eax
133                 mov bx,core_cfarcall.resume
134                 jmp enter_pm
135
136 ;
137 ; 32-bit support code
138 ;
139                 bits 32
140
141 ;
142 ; Intcall/farcall invocation.  We manifest a structure on the real-mode stack,
143 ; containing the com32sys_t structure from <com32.h> as well as
144 ; the following entries (from low to high address):
145 ; - Target offset
146 ; - Target segment
147 ; - Return offset
148 ; - Return segment (== real mode cs == 0)
149 ; - Return flags
150 ;
151                 global core_farcall
152 core_farcall:
153                 mov eax,[esp+1*4]               ; CS:IP
154                 jmp com32_syscall
155
156                 global core_intcall
157 core_intcall:
158                 movzx eax,byte [esp+1*4]        ; INT number
159                 mov eax,[eax*4]                 ; Get CS:IP from low memory
160
161 com32_syscall:
162                 pushfd                          ; Save IF among other things...
163                 push ebx
164                 push ebp
165                 push esi
166                 push edi
167                 push dword [Com32SysSP]
168
169                 cld
170
171                 movzx edi,word [word RealModeSSSP]
172                 movzx ebx,word [word RealModeSSSP+2]
173                 sub edi,54              ; Allocate 54 bytes
174                 mov [word RealModeSSSP],di
175                 shl ebx,4
176                 add edi,ebx             ; Create linear address
177
178                 mov esi,[esp+8*4]       ; Source regs
179                 xor ecx,ecx
180                 mov cl,11               ; 44 bytes to copy
181                 rep movsd
182
183                 ; EAX is already set up to be CS:IP
184                 stosd                   ; Save in stack frame
185                 mov eax,com32_sys_rm.return     ; Return seg:offs
186                 stosd                   ; Save in stack frame
187                 mov eax,[edi-12]        ; Return flags
188                 and eax,0x200cd7        ; Mask (potentially) unsafe flags
189                 mov [edi-12],eax        ; Primary flags entry
190                 stosw                   ; Return flags
191
192                 mov bx,com32_sys_rm
193                 jmp enter_rm    ; Go to real mode
194
195                 ; On return, the 44-byte return structure is on the
196                 ; real-mode stack, plus the 10 additional bytes used
197                 ; by the target address (see above.)
198 .resume:
199                 movzx esi,word [word RealModeSSSP]
200                 movzx eax,word [word RealModeSSSP+2]
201                 mov edi,[esp+9*4]       ; Dest regs
202                 shl eax,4
203                 add esi,eax             ; Create linear address
204                 and edi,edi             ; NULL pointer?
205                 jnz .do_copy
206 .no_copy:       mov edi,esi             ; Do a dummy copy-to-self
207 .do_copy:       xor ecx,ecx
208                 mov cl,11               ; 44 bytes
209                 rep movsd               ; Copy register block
210
211                 add dword [word RealModeSSSP],54
212                                         ; Remove from stack
213
214                 pop dword [Com32SysSP]
215                 pop edi
216                 pop esi
217                 pop ebp
218                 pop ebx
219                 popfd
220                 ret                     ; Return to 32-bit program
221
222 ;
223 ; Cfarcall invocation.  We copy the stack frame to the real-mode stack,
224 ; followed by the return CS:IP and the CS:IP of the target function.
225 ;
226                 global core_cfarcall
227 core_cfarcall:
228                 pushfd                          ; Save IF among other things...
229                 push ebx
230                 push ebp
231                 push esi
232                 push edi
233                 push dword [Com32SysSP]
234
235                 cld
236                 mov ecx,[esp+9*4]               ; Size of stack frame
237
238                 movzx edi,word [word RealModeSSSP]
239                 movzx ebx,word [word RealModeSSSP+2]
240                 mov [word Com32SysSP],di
241                 sub edi,ecx             ; Allocate space for stack frame
242                 and edi,~3              ; Round
243                 sub edi,4*2             ; Return pointer, return value
244                 mov [word RealModeSSSP],di
245                 shl ebx,4
246                 add edi,ebx             ; Create linear address
247
248                 mov eax,[esp+7*4]       ; CS:IP
249                 stosd                   ; Save to stack frame
250                 mov eax,com32_cfar_rm.return    ; Return seg:off
251                 stosd
252                 mov esi,[esp+8*4]       ; Stack frame
253                 mov eax,ecx             ; Copy the stack frame
254                 shr ecx,2
255                 rep movsd
256                 mov ecx,eax
257                 and ecx,3
258                 rep movsb
259
260                 mov bx,com32_cfar_rm
261                 jmp enter_rm
262
263 .resume:
264                 mov eax,esi
265                 ; EDX already set up to be the RM return value
266                 pop dword [Com32SysSP]
267                 pop ebx
268                 pop ebp
269                 pop esi
270                 pop edi
271                 popfd
272                 ret
273
274                 bits 16
275
276                 section .bss16
277                 alignb 4
278 Com32SysSP      resd 1                  ; SP saved during COM32 syscall
279
280                 section .text16