Magellan Linux

Contents of /trunk/mkinitrd-magellan/isolinux/com32.inc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File size: 8204 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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