Contents of /tags/mkinitrd-6_1_1/isolinux/com32.inc
Parent Directory | Revision Log
Revision 841 -
(show annotations)
(download)
Mon May 4 16:31:54 2009 UTC (15 years, 4 months ago) by niro
File size: 8204 byte(s)
Mon May 4 16:31:54 2009 UTC (15 years, 4 months ago) by niro
File size: 8204 byte(s)
tagged 'mkinitrd-6_1_1'
1 | ;; $Id: com32.inc,v 1.1 2007-09-01 22:44:04 niro Exp $ |
2 | ;; ----------------------------------------------------------------------- |
3 | ;; |
4 | ;; Copyright 1994-2003 H. Peter Anvin - All Rights Reserved |
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 | pm_idt: equ 0x100000 |
31 | pm_entry: equ 0x101000 |
32 | |
33 | bits 16 |
34 | section .data |
35 | align 2, db 0 |
36 | com32_pmidt: |
37 | dw 8*256 ; Limit |
38 | dd pm_idt ; Address |
39 | |
40 | com32_rmidt: |
41 | dw 0ffffh ; Limit |
42 | dd 0 ; Address |
43 | |
44 | section .text |
45 | is_com32_image: |
46 | push si ; Save file handle |
47 | push dx ; File length held in DX:AX |
48 | push ax |
49 | |
50 | call make_plain_cmdline |
51 | ; Copy the command line into the low cmdline buffer |
52 | mov ax,real_mode_seg |
53 | mov fs,ax |
54 | mov si,cmd_line_here |
55 | mov di,command_line |
56 | mov cx,[CmdLinePtr] |
57 | inc cx ; Include final null |
58 | sub cx,si |
59 | fs rep movsb |
60 | |
61 | call highmemsize ; We need the high memory size... |
62 | call comboot_setup_api ; Set up the COMBOOT-style API |
63 | |
64 | mov edi,pm_entry ; Load address |
65 | pop eax ; File length |
66 | pop si ; File handle |
67 | xor dx,dx ; No padding |
68 | call load_high |
69 | call crlf |
70 | |
71 | com32_start: |
72 | mov ebx,com32_call_start ; Where to go in PM |
73 | |
74 | com32_enter_pm: |
75 | cli |
76 | mov ax,cs |
77 | mov ds,ax |
78 | mov [SavedSSSP],sp |
79 | mov [SavedSSSP+2],ss |
80 | cld |
81 | call a20_test |
82 | jnz .a20ok |
83 | call enable_a20 |
84 | |
85 | .a20ok: |
86 | lgdt [bcopy_gdt] ; We can use the same GDT just fine |
87 | lidt [com32_pmidt] ; Set up the IDT |
88 | mov eax,cr0 |
89 | or al,1 |
90 | mov cr0,eax ; Enter protected mode |
91 | jmp 20h:.in_pm |
92 | |
93 | bits 32 |
94 | .in_pm: |
95 | xor eax,eax ; Available for future use... |
96 | mov fs,eax |
97 | mov gs,eax |
98 | |
99 | mov al,28h ; Set up data segments |
100 | mov es,eax |
101 | mov ds,eax |
102 | mov ss,eax |
103 | |
104 | mov esp,[PMESP] ; Load protmode %esp if available |
105 | jmp ebx ; Go to where we need to go |
106 | |
107 | ; |
108 | ; This is invoked right before the actually starting the COM32 |
109 | ; progam, in 32-bit mode... |
110 | ; |
111 | com32_call_start: |
112 | ; |
113 | ; Point the stack to the end of high memory |
114 | ; |
115 | mov esp,[word HighMemSize] |
116 | |
117 | ; |
118 | ; Set up the protmode IDT and the interrupt jump buffers |
119 | ; We set these up in the system area at 0x100000, |
120 | ; but we could also put them beyond the stack. |
121 | ; |
122 | mov edi,pm_idt |
123 | |
124 | ; Form an interrupt gate descriptor |
125 | mov eax,0x00200000+((pm_idt+8*256)&0x0000ffff) |
126 | mov ebx,0x0000ee00+((pm_idt+8*256)&0xffff0000) |
127 | xor ecx,ecx |
128 | inc ch ; ecx <- 256 |
129 | |
130 | push ecx |
131 | .make_idt: |
132 | stosd |
133 | add eax,8 |
134 | xchg eax,ebx |
135 | stosd |
136 | xchg eax,ebx |
137 | loop .make_idt |
138 | |
139 | pop ecx |
140 | |
141 | ; Each entry in the interrupt jump buffer contains |
142 | ; the following instructions: |
143 | ; |
144 | ; 00000000 60 pushad |
145 | ; 00000001 B0xx mov al,<interrupt#> |
146 | ; 00000003 E9xxxxxxxx jmp com32_handle_interrupt |
147 | |
148 | mov eax,0e900b060h |
149 | mov ebx,com32_handle_interrupt-(pm_idt+8*256+8) |
150 | |
151 | .make_ijb: |
152 | stosd |
153 | sub [edi-2],cl ; Interrupt # |
154 | xchg eax,ebx |
155 | stosd |
156 | sub eax,8 |
157 | xchg eax,ebx |
158 | loop .make_ijb |
159 | |
160 | ; Now everything is set up for interrupts... |
161 | |
162 | push dword com32_farcall ; Farcall entry point |
163 | push dword (1 << 16) ; 64K bounce buffer |
164 | push dword (comboot_seg << 4) ; Bounce buffer address |
165 | push dword com32_intcall ; Intcall entry point |
166 | push dword command_line ; Command line pointer |
167 | push dword 5 ; Argument count |
168 | sti ; Interrupts OK now |
169 | call pm_entry ; Run the program... |
170 | ; ... on return, fall through to com32_exit ... |
171 | |
172 | com32_exit: |
173 | mov bx,com32_done ; Return to command loop |
174 | |
175 | com32_enter_rm: |
176 | cli |
177 | cld |
178 | mov [PMESP],esp ; Save exit %esp |
179 | xor esp,esp ; Make sure the high bits are zero |
180 | jmp 08h:.in_pm16 ; Return to 16-bit mode first |
181 | |
182 | bits 16 |
183 | .in_pm16: |
184 | mov ax,18h ; Real-mode-like segment |
185 | mov es,ax |
186 | mov ds,ax |
187 | mov ss,ax |
188 | mov fs,ax |
189 | mov gs,ax |
190 | |
191 | lidt [com32_rmidt] ; Real-mode IDT (rm needs no GDT) |
192 | mov eax,cr0 |
193 | and al,~1 |
194 | mov cr0,eax |
195 | jmp 0:.in_rm |
196 | |
197 | .in_rm: ; Back in real mode |
198 | mov ax,cs ; Set up sane segments |
199 | mov ds,ax |
200 | mov es,ax |
201 | mov fs,ax |
202 | mov gs,ax |
203 | lss sp,[SavedSSSP] ; Restore stack |
204 | jmp bx ; Go to whereever we need to go... |
205 | |
206 | com32_done: |
207 | call disable_a20 |
208 | sti |
209 | jmp enter_command |
210 | |
211 | ; |
212 | ; 16-bit support code |
213 | ; |
214 | bits 16 |
215 | |
216 | ; |
217 | ; 16-bit interrupt-handling code |
218 | ; |
219 | com32_int_rm: |
220 | pushf ; Flags on stack |
221 | push cs ; Return segment |
222 | push word .cont ; Return address |
223 | push dword edx ; Segment:offset of IVT entry |
224 | retf ; Invoke IVT routine |
225 | .cont: ; ... on resume ... |
226 | mov ebx,com32_int_resume |
227 | jmp com32_enter_pm ; Go back to PM |
228 | |
229 | ; |
230 | ; 16-bit system call handling code |
231 | ; |
232 | com32_sys_rm: |
233 | pop gs |
234 | pop fs |
235 | pop es |
236 | pop ds |
237 | popad |
238 | popfd |
239 | mov [cs:Com32SysSP],sp |
240 | retf ; Invoke routine |
241 | .return: |
242 | ; We clean up SP here because we don't know if the |
243 | ; routine returned with RET, RETF or IRET |
244 | mov sp,[cs:Com32SysSP] |
245 | pushfd |
246 | pushad |
247 | push ds |
248 | push es |
249 | push fs |
250 | push gs |
251 | mov ebx,com32_sys_resume |
252 | jmp com32_enter_pm |
253 | |
254 | ; |
255 | ; 32-bit support code |
256 | ; |
257 | bits 32 |
258 | |
259 | ; |
260 | ; This is invoked on getting an interrupt in protected mode. At |
261 | ; this point, we need to context-switch to real mode and invoke |
262 | ; the interrupt routine. |
263 | ; |
264 | ; When this gets invoked, the registers are saved on the stack and |
265 | ; AL contains the register number. |
266 | ; |
267 | com32_handle_interrupt: |
268 | movzx eax,al |
269 | xor ebx,ebx ; Actually makes the code smaller |
270 | mov edx,[ebx+eax*4] ; Get the segment:offset of the routine |
271 | mov bx,com32_int_rm |
272 | jmp com32_enter_rm ; Go to real mode |
273 | |
274 | com32_int_resume: |
275 | popad |
276 | iret |
277 | |
278 | ; |
279 | ; Intcall/farcall invocation. We manifest a structure on the real-mode stack, |
280 | ; containing the com32sys_t structure from <com32.h> as well as |
281 | ; the following entries (from low to high address): |
282 | ; - Target offset |
283 | ; - Target segment |
284 | ; - Return offset |
285 | ; - Return segment (== real mode cs == 0) |
286 | ; - Return flags |
287 | ; |
288 | com32_farcall: |
289 | pushfd ; Save IF among other things... |
290 | pushad ; We only need to save some, but... |
291 | |
292 | mov eax,[esp+10*4] ; CS:IP |
293 | jmp com32_syscall |
294 | |
295 | |
296 | com32_intcall: |
297 | pushfd ; Save IF among other things... |
298 | pushad ; We only need to save some, but... |
299 | |
300 | movzx eax,byte [esp+10*4] ; INT number |
301 | mov eax,[eax*4] ; Get CS:IP from low memory |
302 | |
303 | com32_syscall: |
304 | cld |
305 | |
306 | movzx edi,word [word SavedSSSP] |
307 | movzx ebx,word [word SavedSSSP+2] |
308 | sub edi,54 ; Allocate 54 bytes |
309 | mov [word SavedSSSP],di |
310 | shl ebx,4 |
311 | add edi,ebx ; Create linear address |
312 | |
313 | mov esi,[esp+11*4] ; Source regs |
314 | xor ecx,ecx |
315 | mov cl,11 ; 44 bytes to copy |
316 | rep movsd |
317 | |
318 | ; EAX is already set up to be CS:IP |
319 | stosd ; Save in stack frame |
320 | mov eax,com32_sys_rm.return ; Return seg:offs |
321 | stosd ; Save in stack frame |
322 | mov eax,[edi-12] ; Return flags |
323 | and eax,0x200cd7 ; Mask (potentially) unsafe flags |
324 | mov [edi-12],eax ; Primary flags entry |
325 | stosw ; Return flags |
326 | |
327 | mov bx,com32_sys_rm |
328 | jmp com32_enter_rm ; Go to real mode |
329 | |
330 | ; On return, the 44-byte return structure is on the |
331 | ; real-mode stack, plus the 10 additional bytes used |
332 | ; by the target address (see above.) |
333 | com32_sys_resume: |
334 | movzx esi,word [word SavedSSSP] |
335 | movzx eax,word [word SavedSSSP+2] |
336 | mov edi,[esp+12*4] ; Dest regs |
337 | shl eax,4 |
338 | add esi,eax ; Create linear address |
339 | and edi,edi ; NULL pointer? |
340 | jnz .do_copy |
341 | .no_copy: mov edi,esi ; Do a dummy copy-to-self |
342 | .do_copy: xor ecx,ecx |
343 | mov cl,11 ; 44 bytes |
344 | rep movsd ; Copy register block |
345 | |
346 | add dword [word SavedSSSP],54 ; Remove from stack |
347 | |
348 | popad |
349 | popfd |
350 | ret ; Return to 32-bit program |
351 | |
352 | bits 16 |
353 | |
354 | section .bss |
355 | alignb 4 |
356 | PMESP resd 1 ; Protected-mode ESP |
357 | Com32SysSP resw 1 ; SP saved during COM32 syscall |
358 | |
359 | section .text |