source: bootcd/isolinux/syslinux-6.03/gpxe/src/arch/i386/transitions/libkir.S

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * libkir: a transition library for -DKEEP_IT_REAL
3 *
4 * Michael Brown <mbrown@fensystems.co.uk>
5 *
6 */
7
8FILE_LICENCE ( GPL2_OR_LATER )
9
10/****************************************************************************
11 * This file defines libkir: an interface between external and
12 * internal environments when -DKEEP_IT_REAL is used, so that both
13 * internal and external environments are in real mode.  It deals with
14 * switching data segments and the stack.  It provides the following
15 * functions:
16 *
17 * ext_to_kir &         switch between external and internal (kir)
18 * kir_to_ext           environments, preserving all non-segment
19 *                      registers
20 *
21 * kir_call             issue a call to an internal routine from external
22 *                      code
23 *
24 * libkir is written to avoid assuming that segments are anything
25 * other than opaque data types, and also avoids assuming that the
26 * stack pointer is 16-bit.  This should enable it to run just as well
27 * in 16:16 or 16:32 protected mode as in real mode.
28 ****************************************************************************
29 */
30
31/* Breakpoint for when debugging under bochs */
32#define BOCHSBP xchgw %bx, %bx
33
34        .text
35        .arch i386
36        .section ".text16", "awx", @progbits
37        .code16
38       
39/****************************************************************************
40 * init_libkir (real-mode or 16:xx protected-mode far call)
41 *
42 * Initialise libkir ready for transitions to the kir environment
43 *
44 * Parameters:
45 *   %cs : .text16 segment
46 *   %ds : .data16 segment
47 ****************************************************************************
48 */
49        .globl  init_libkir
50init_libkir:
51        /* Record segment registers */
52        pushw   %ds
53        popw    %cs:kir_ds
54        lret
55       
56/****************************************************************************
57 * ext_to_kir (real-mode or 16:xx protected-mode near call)
58 *
59 * Switch from external stack and segment registers to internal stack
60 * and segment registers.  %ss:sp is restored from the saved kir_ds
61 * and kir_sp.  %ds, %es, %fs and %gs are all restored from the saved
62 * kir_ds.  All other registers are preserved.
63 *
64 * %cs:0000 must point to the start of the runtime image code segment
65 * on entry.
66 *
67 * Parameters: none
68 ****************************************************************************
69 */
70
71        .globl  ext_to_kir
72ext_to_kir:
73        /* Record external segment registers */
74        movw    %ds, %cs:ext_ds
75        pushw   %cs
76        popw    %ds     /* Set %ds = %cs for easier access to variables */
77        movw    %es, %ds:ext_es
78        movw    %fs, %ds:ext_fs
79        movw    %gs, %ds:ext_fs
80
81        /* Preserve registers */
82        movw    %ax, %ds:save_ax
83
84        /* Extract near return address from stack */
85        popw    %ds:save_retaddr
86
87        /* Record external %ss:esp */
88        movw    %ss, %ds:ext_ss
89        movl    %esp, %ds:ext_esp
90
91        /* Load internal segment registers and stack pointer */
92        movw    %ds:kir_ds, %ax
93        movw    %ax, %ss
94        movzwl  %ds:kir_sp, %esp
95        movw    %ax, %ds
96        movw    %ax, %es
97        movw    %ax, %fs
98        movw    %ax, %gs
991:
100
101        /* Place return address on new stack */
102        pushw   %cs:save_retaddr
103       
104        /* Restore registers and return */
105        movw    %cs:save_ax, %ax
106        ret
107
108/****************************************************************************
109 * kir_to_ext (real-mode or 16:xx protected-mode near call)
110 *
111 * Switch from internal stack and segment registers to external stack
112 * and segment registers.  %ss:%esp is restored from the saved ext_ss
113 * and ext_esp.  Other segment registers are restored from the
114 * corresponding locations.  All other registers are preserved.
115 *
116 * Note that it is actually %ss that is recorded as kir_ds, on the
117 * assumption that %ss == %ds when kir_to_ext is called.
118 *
119 * Parameters: none
120 ****************************************************************************
121 */
122
123        .globl  kir_to_ext
124kir_to_ext:
125        /* Record near return address */
126        pushw   %cs
127        popw    %ds     /* Set %ds = %cs for easier access to variables */
128        popw    %ds:save_retaddr
129       
130        /* Record internal segment registers and %sp */
131        movw    %ss, %ds:kir_ds
132        movw    %sp, %ds:kir_sp
133
134        /* Load external segment registers and stack pointer */
135        movw    %ds:ext_ss, %ss
136        movl    %ds:ext_esp, %esp
137        movw    %ds:ext_gs, %gs
138        movw    %ds:ext_fs, %fs
139        movw    %ds:ext_es, %es
140        movw    %ds:ext_ds, %ds
141
142        /* Return */
143        pushw   %cs:save_retaddr
144        ret
145       
146/****************************************************************************
147 * kir_call (real-mode or 16:xx protected-mode far call)
148 *
149 * Call a specific C function in the internal code.  The prototype of
150 * the C function must be
151 *   void function ( struct i386_all_resg *ix86 );
152 * ix86 will point to a struct containing the real-mode registers
153 * at entry to kir_call.
154 *
155 * All registers will be preserved across kir_call(), unless the C
156 * function explicitly overwrites values in ix86.  Interrupt status
157 * will also be preserved.
158 *
159 * Parameters:
160 *   function : (32-bit) virtual address of C function to call
161 *
162 * Example usage:
163 *      pushl   $pxe_api_call
164 *      lcall   $UNDI_CS, $kir_call
165 *      addw    $4, %sp
166 * to call in to the C function
167 *      void pxe_api_call ( struct i386_all_regs *ix86 );
168 ****************************************************************************
169 */
170
171        .globl  kir_call
172kir_call:
173        /* Preserve flags.  Must do this before any operation that may
174         * affect flags.
175         */
176        pushfl
177        popl    %cs:save_flags
178
179        /* Disable interrupts.  We do funny things with the stack, and
180         * we're not re-entrant.
181         */
182        cli
183               
184        /* Extract address of internal routine from stack.  We must do
185         * this without using (%bp), because we may be called with
186         * either a 16-bit or a 32-bit stack segment.
187         */
188        popl    %cs:save_retaddr        /* Scratch location */
189        popl    %cs:save_function
190        subl    $8, %esp                /* Restore %esp */
191       
192        /* Switch to internal stack.  Note that the external stack is
193         * inaccessible once we're running internally (since we have
194         * no concept of 48-bit far pointers)
195         */
196        call    ext_to_kir
197       
198        /* Store external registers on internal stack */
199        pushl   %cs:save_flags
200        pushal
201        pushl   %cs:ext_fs_and_gs
202        pushl   %cs:ext_ds_and_es
203        pushl   %cs:ext_cs_and_ss
204
205        /* Push &ix86 on stack and call function */
206        sti
207        pushl   %esp
208        data32 call *%cs:save_function
209        popl    %eax /* discard */
210       
211        /* Restore external registers from internal stack */
212        popl    %cs:ext_cs_and_ss
213        popl    %cs:ext_ds_and_es
214        popl    %cs:ext_fs_and_gs
215        popal
216        popl    %cs:save_flags
217
218        /* Switch to external stack */
219        call    kir_to_ext
220
221        /* Restore flags */
222        pushl   %cs:save_flags
223        popfl
224
225        /* Return */
226        lret
227
228/****************************************************************************
229 * Stored internal and external stack and segment registers
230 ****************************************************************************
231 */
232       
233ext_cs_and_ss: 
234ext_cs:         .word 0
235ext_ss:         .word 0
236ext_ds_and_es: 
237ext_ds:         .word 0
238ext_es:         .word 0
239ext_fs_and_gs: 
240ext_fs:         .word 0
241ext_gs:         .word 0
242ext_esp:        .long 0
243
244                .globl kir_ds
245kir_ds:         .word 0
246                .globl kir_sp
247kir_sp:         .word _estack
248
249/****************************************************************************
250 * Temporary variables
251 ****************************************************************************
252 */
253save_ax:        .word 0
254save_retaddr:   .long 0
255save_flags:     .long 0
256save_function:  .long 0
Note: See TracBrowser for help on using the repository browser.