Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide 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 niro 532 ;; $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