Update relocate() to work with get_memmap().
[people/xl0/gpxe.git] / src / arch / i386 / core / setup.S
1 /****************************************************************************
2  * This file provides the setup() and setup16() functions.  The
3  * purpose of these functions is to set up the internal environment so
4  * that C code can execute.  This includes setting up the internal
5  * stack and (where applicable) setting up a GDT for virtual
6  * addressing.
7  *
8  * These functions are designed to be called by the prefix.
9  *
10  * The same basic assembly code is used to compile both setup()
11  * and setup16().
12  ****************************************************************************
13  */
14
15         .text
16         .arch i386
17
18 #ifdef CODE16
19 /****************************************************************************
20  * setup16 (real-mode far call)
21  *
22  * This function can be called by a 16-bit prefix in order to set up
23  * the internal (either 16-bit or 32-bit) environment.
24  *
25  * Parameters: none
26  *
27  * %cs:0000, %ds:0000 and %es:0000 must point to the start of the
28  * (decompressed) runtime image.
29  *
30  * If KEEP_IT_REAL is defined, then %ds:0000 may instead point to the
31  * start of the (decompressed) data segment portion of the runtime
32  * image.  If %ds==%cs, then it will be assumed that the data segment
33  * follows immediately after the code segment.
34  ****************************************************************************
35  */
36
37 #ifdef KEEP_IT_REAL
38
39 #define ENTER_FROM_EXTERNAL call ext_to_kir
40 #define RETURN_TO_EXTERNAL call kir_to_ext
41 #define ENTRY_POINT kir_call
42 #define ENTRY_POINT_REGISTER di  
43 #define INIT_FUNC initialise
44
45 #else /* KEEP_IT_REAL */
46
47 #define ENTER_FROM_EXTERNAL \
48         pushw %cs ; \
49         call real_to_prot ; \
50         .code32
51 #define RETURN_TO_EXTERNAL \
52         call prot_to_real ; \
53         .code16
54 #define ENTRY_POINT _prot_call /* _prot_call = OFFSET ( prot_call ) in librm */
55 #define ENTRY_POINT_REGISTER di  
56 #define INIT_FUNC initialise_via_librm
57
58 #endif /* KEEP_IT_REAL */
59         
60         .section ".text16"
61         .code16
62         .globl setup16
63 setup16:
64         
65 #else /* CODE16 */
66
67 /****************************************************************************
68  * setup (32-bit protected-mode near call)
69  *
70  * This function can be called by a 32-bit prefix in order to set up
71  * the internal 32-bit environment.
72  *
73  * Parameters: none
74  ****************************************************************************
75  */
76
77 #define ENTER_FROM_EXTERNAL call ext_to_int
78 #define RETURN_TO_EXTERNAL call int_to_ext
79 #define ENTRY_POINT int_call
80 #define ENTRY_POINT_REGISTER edi
81 #define INIT_FUNC initialise
82                 
83         .section ".text"
84         .code32
85         .globl setup
86 setup:
87         
88 #endif /* CODE16 */
89         
90         /* Preserve flags (including interrupt status) and registers */
91         pushfl
92         pushl   %ebp
93
94         /* Switch to (uninitialised) internal environment.  This will
95          * preserve the external environment for when we call
96          * RETURN_TO_EXTERNAL.
97          */
98         ENTER_FROM_EXTERNAL
99         /* NOTE: We may have only four bytes of stack at this point */
100
101 #if defined(CODE16) && defined(KEEP_IT_REAL)
102         
103         /* If %ds == %cs, then the data segment is located immediately
104          * after the code segment.
105          */
106         pushw   %ax
107         movw    %cs, %ax
108         movw    %ds, %bp
109         cmpw    %ax, %bp
110         jne     1f
111         addw    $_text_load_size_pgh, %ax
112         movw    %ax, %ds
113 1:      popw    %ax
114                 
115         /* Switch to internal stack */
116         pushw   %ds
117         popw    %ss
118         movl    $_estack, %esp
119
120 #else /* CODE16 && KEEP_IT_REAL */
121
122         /* Work out where we're running and switch to internal pmode
123          * stack
124          */
125         call    1f
126 1:      popl    %ebp
127         leal    (_estack-1b)(%ebp), %esp
128
129         /* Set up GDT for virtual addressing */
130         call    run_here
131
132 #endif /* CODE16 && KEEP_IT_REAL */
133         
134         /* Switch back to external environment.  This will preserve
135          * the internal environment ready for the next call.
136          */
137         RETURN_TO_EXTERNAL
138
139         /* Set %es:[e]di to point to entry-point function.
140          */
141         push    %cs
142         pop     %es
143         mov     $ENTRY_POINT, %ENTRY_POINT_REGISTER
144
145         /* Far call to initialise via the entry-point function.
146          * initialise() (or the entry-point function itself) may
147          * update %es:[e]di to point to a new entry-point function for
148          * subsequent calls.  librm will use this facility, since
149          * initialise() causes librm to be relocated.
150          */
151         pushl   $INIT_FUNC
152         push    %cs             /* lcall %es:[x]di == %cs:[x]di */
153         call    *%ENTRY_POINT_REGISTER
154         popl    %ebp /* discard */
155         
156         /* Restore flags (including interrupt status) and return */
157         popl    %ebp
158         popfl
159         lret
160