|
@@ -8,98 +8,6 @@
|
8
|
8
|
/* Drag in local definitions */
|
9
|
9
|
#include "librm.h"
|
10
|
10
|
|
11
|
|
-/* Drag in FREE_BASEMEM_HEADER_SIZE */
|
12
|
|
-#include "basemem.h"
|
13
|
|
-
|
14
|
|
-/****************************************************************************
|
15
|
|
- * This file defines librm: a block of code that is designed to reside
|
16
|
|
- * permanently in base memory and provide the interface between
|
17
|
|
- * real-mode code running in base memory and protected-mode code
|
18
|
|
- * running in high memory. It provides the following functions:
|
19
|
|
- *
|
20
|
|
- * real_to_prot & switch between real and protected mode
|
21
|
|
- * prot_to_real while running in base memory, preserving
|
22
|
|
- * all non-segment registers
|
23
|
|
- *
|
24
|
|
- * real_call issue a call to a real-mode routine from
|
25
|
|
- * protected-mode code running in high memory
|
26
|
|
- *
|
27
|
|
- * prot_call issue a call to a protected-mode routine from
|
28
|
|
- * real-mode code running in base memory
|
29
|
|
- *
|
30
|
|
- * librm requires the following functions to be present in the
|
31
|
|
- * protected-mode code:
|
32
|
|
- *
|
33
|
|
- * _phys_to_virt Switch from physical to virtual addressing. This
|
34
|
|
- * routine must be position-independent and must
|
35
|
|
- * *not* assume that it is genuinely running with
|
36
|
|
- * flat physical addresses
|
37
|
|
- *
|
38
|
|
- * _virt_to_phys Switch from virtual to physical addresses.
|
39
|
|
- *
|
40
|
|
- * gateA20_set Enable the A20 line to permit access to the odd
|
41
|
|
- * megabytes of RAM. (This function will be called
|
42
|
|
- * with virtual addresses set up).
|
43
|
|
- *
|
44
|
|
- * librm needs to be linked against the protected-mode binary so that
|
45
|
|
- * it can import the symbols for these functions.
|
46
|
|
- *
|
47
|
|
- * librm requires that the protected-mode code set up the following
|
48
|
|
- * segments:
|
49
|
|
- *
|
50
|
|
- * PHYSICAL_CS 32-bit pmode code and data segments with flat
|
51
|
|
- * PHYSICAL_DS physical addresses.
|
52
|
|
- *
|
53
|
|
- * VIRTUAL_CS 32-bit pmode code segment with virtual
|
54
|
|
- * addressing, such that a protected-mode routine
|
55
|
|
- * can always be found at $VIRTUAL_CS:routine.
|
56
|
|
- *
|
57
|
|
- * These segments must be set as #define constants when compiling
|
58
|
|
- * librm. Edit librm.h to change the values.
|
59
|
|
- *
|
60
|
|
- * librm does not know the location of the code executing in high
|
61
|
|
- * memory. It relies on the code running in high memory setting up a
|
62
|
|
- * GDT such that the high-memory code is accessible at virtual
|
63
|
|
- * addresses fixed at compile-time.
|
64
|
|
- *
|
65
|
|
- * librm symbols are exported as absolute values and represent offsets
|
66
|
|
- * into librm. This is the most useful form of the symbols, since
|
67
|
|
- * librm is basically a binary blob that you place somewhere in base
|
68
|
|
- * memory.
|
69
|
|
- *
|
70
|
|
- * librm.h provides convenient ways to use these symbols: you simply
|
71
|
|
- * set the pointer ( char * ) installed_librm to point to wherever
|
72
|
|
- * librm is installed, and can then use e.g. inst_rm_stack just like
|
73
|
|
- * any other variable and have it automatically refer to the value of
|
74
|
|
- * rm_stack in the installed librm. Macro trickery makes this
|
75
|
|
- * completely transparent, and the resulting assembler code is
|
76
|
|
- * amazingly efficient.
|
77
|
|
- *
|
78
|
|
- * Note that librm must be called in genuine real mode, not 16:16 or
|
79
|
|
- * 16:32 protected mode. It makes the assumption that
|
80
|
|
- * physical_address = 16*segment+offset, and also that it can use
|
81
|
|
- * OFFSET(%bp) to access stack variables. The former assumption will
|
82
|
|
- * break in either protected mode, the latter may break in 16:32
|
83
|
|
- * protected mode.
|
84
|
|
- ****************************************************************************
|
85
|
|
- */
|
86
|
|
-
|
87
|
|
-/*
|
88
|
|
- * Default values for pmode segments if not defined
|
89
|
|
- */
|
90
|
|
-#ifndef PHYSICAL_CS
|
91
|
|
-#warning "Assuming PHYSICAL_CS = 0x08"
|
92
|
|
-#define PHYSICAL_CS 0x08
|
93
|
|
-#endif
|
94
|
|
-#ifndef PHYSICAL_DS
|
95
|
|
-#warning "Assuming PHYSICAL_DS = 0x10"
|
96
|
|
-#define PHYSICAL_DS 0x10
|
97
|
|
-#endif
|
98
|
|
-#ifndef VIRTUAL_CS
|
99
|
|
-#warning "Assuming VIRTUAL_CS = 0x18"
|
100
|
|
-#define VIRTUAL_CS 0x18
|
101
|
|
-#endif
|
102
|
|
-
|
103
|
11
|
/* For switches to/from protected mode */
|
104
|
12
|
#define CR0_PE 1
|
105
|
13
|
|
|
@@ -109,101 +17,26 @@
|
109
|
17
|
#define SIZEOF_REAL_MODE_REGS ( SIZEOF_I386_SEG_REGS + SIZEOF_I386_REGS )
|
110
|
18
|
#define SIZEOF_I386_FLAGS 4
|
111
|
19
|
#define SIZEOF_I386_ALL_REGS ( SIZEOF_REAL_MODE_REGS + SIZEOF_I386_FLAGS )
|
112
|
|
-#define SIZEOF_SEGOFF_T 4
|
113
|
|
-#define SIZEOF_REAL_CALL_PARAMS ( SIZEOF_REAL_MODE_REGS + 2 * SIZEOF_SEGOFF_T )
|
114
|
20
|
|
115
|
|
- .text
|
116
|
21
|
.arch i386
|
117
|
|
- .section ".librm", "awx", @progbits
|
118
|
|
- .align 16
|
119
|
|
-
|
120
|
|
- .globl librm
|
121
|
|
-librm:
|
122
|
|
-
|
123
|
|
-_librm_start:
|
124
|
|
-
|
125
|
|
-#undef OFFSET
|
126
|
|
-#define OFFSET(sym) ( sym - _librm_start )
|
127
|
|
-
|
128
|
|
-#undef EXPORT
|
129
|
|
-#define EXPORT(sym) \
|
130
|
|
- .globl sym ; \
|
131
|
|
- .globl _ ## sym ; \
|
132
|
|
- .equ _ ## sym, OFFSET(sym) ; \
|
133
|
|
- sym
|
|
22
|
+ .section ".text16", "awx", @progbits
|
134
|
23
|
|
135
|
24
|
/****************************************************************************
|
136
|
|
- * Note that the first sizeof(struct free_base_memory_header) bytes of
|
137
|
|
- * librm will get vapourised by free_base_memory(). Since we need
|
138
|
|
- * librm to continue working even when this happens, we put some
|
139
|
|
- * padding here.
|
|
25
|
+ * Global descriptor table
|
140
|
26
|
*
|
141
|
|
- * We must also ensure that the total size of librm is <1kB, otherwise
|
142
|
|
- * free_base_memory() will stomp somewhere in the middle of us as
|
143
|
|
- * well...
|
144
|
|
- ****************************************************************************
|
145
|
|
- */
|
146
|
|
- .fill FREE_BASEMEM_HEADER_SIZE, 1, 0
|
147
|
|
-
|
148
|
|
-/****************************************************************************
|
149
|
|
- * Record of the current physical location of the installed copy.
|
150
|
|
- * Used by prot_call in order to return via the current installed copy
|
151
|
|
- * even if Etherboot has been relocated during the protected-mode
|
152
|
|
- * call.
|
153
|
|
- ****************************************************************************
|
154
|
|
- */
|
155
|
|
-EXPORT(librm_base):
|
156
|
|
-librm_base: .long 0
|
157
|
|
-
|
158
|
|
-/****************************************************************************
|
159
|
|
- * GDT for initial transition to protected mode
|
|
27
|
+ * Call init_gdt to set up the GDT before attempting to use any
|
|
28
|
+ * protected-mode code.
|
160
|
29
|
*
|
161
|
|
- * PHYSICAL_CS and PHYSICAL_DS are defined in an external header file.
|
162
|
|
- * We use only those selectors, and construct our GDT to match the
|
163
|
|
- * selector values we're asked to use. Use PHYSICAL_CS=0x08 and
|
164
|
|
- * PHYSICAL_DS=0x10 to minimise the space occupied by this GDT.
|
165
|
|
- *
|
166
|
|
- * Note: pm_gdt is also used to store the location of the
|
167
|
|
- * protected-mode GDT as recorded on entry to prot_to_real.
|
168
|
|
- ****************************************************************************
|
169
|
|
- */
|
170
|
|
- .align 16
|
171
|
|
-pm_gdt:
|
172
|
|
-pm_gdt_limit: .word pm_gdt_length - 1
|
173
|
|
-pm_gdt_addr: .long 0
|
174
|
|
- .word 0 /* padding */
|
175
|
|
-
|
176
|
|
- .org pm_gdt + PHYSICAL_CS
|
177
|
|
-pm_gdt_pm_cs:
|
178
|
|
- /* 32 bit protected mode code segment, physical addresses */
|
179
|
|
- .word 0xffff, 0
|
180
|
|
- .byte 0, 0x9f, 0xcf, 0
|
181
|
|
-
|
182
|
|
- .org pm_gdt + PHYSICAL_DS
|
183
|
|
-pm_gdt_pm_ds:
|
184
|
|
- /* 32 bit protected mode data segment, physical addresses */
|
185
|
|
- .word 0xffff,0
|
186
|
|
- .byte 0,0x93,0xcf,0
|
187
|
|
-
|
188
|
|
-pm_gdt_end:
|
189
|
|
- .equ pm_gdt_length, pm_gdt_end - pm_gdt
|
190
|
|
-
|
191
|
|
-/****************************************************************************
|
192
|
|
- * GDT for transition to real mode
|
193
|
|
- *
|
194
|
|
- * This is used primarily to set 64kB segment limits. Define
|
195
|
|
- * FLATTEN_REAL_MODE if you want to use so-called "flat real mode"
|
196
|
|
- * with 4GB limits instead. The base address of each of the segments
|
197
|
|
- * will be adjusted at run-time.
|
|
30
|
+ * Define FLATTEN_REAL_MODE if you want to use so-called "flat real
|
|
31
|
+ * mode" with 4GB limits instead.
|
198
|
32
|
*
|
199
|
33
|
* NOTE: This must be located before prot_to_real, otherwise gas
|
200
|
34
|
* throws a "can't handle non absolute segment in `ljmp'" error due to
|
201
|
|
- * not knowing the value of RM_CS when the ljmp is encountered.
|
|
35
|
+ * not knowing the value of REAL_CS when the ljmp is encountered.
|
202
|
36
|
*
|
203
|
|
- * Note also that putting ".word rm_gdt_end - rm_gdt - 1" directly
|
204
|
|
- * into rm_gdt_limit, rather than going via rm_gdt_length, will also
|
205
|
|
- * produce the "non absolute segment" error. This is most probably a
|
206
|
|
- * bug in gas.
|
|
37
|
+ * Note also that putting ".word gdt_end - gdt - 1" directly into
|
|
38
|
+ * gdt_limit, rather than going via gdt_length, will also produce the
|
|
39
|
+ * "non absolute segment" error. This is most probably a bug in gas.
|
207
|
40
|
****************************************************************************
|
208
|
41
|
*/
|
209
|
42
|
|
|
@@ -212,252 +45,242 @@ pm_gdt_end:
|
212
|
45
|
#else
|
213
|
46
|
#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
|
214
|
47
|
#endif
|
|
48
|
+ .section ".text16"
|
215
|
49
|
.align 16
|
216
|
|
-rm_gdt:
|
217
|
|
-rm_gdt_limit: .word rm_gdt_length - 1
|
218
|
|
-rm_gdt_base: .long 0
|
|
50
|
+gdt:
|
|
51
|
+gdt_limit: .word gdt_length - 1
|
|
52
|
+gdt_base: .long 0
|
219
|
53
|
.word 0 /* padding */
|
|
54
|
+
|
|
55
|
+ .org gdt + VIRTUAL_CS, 0
|
|
56
|
+virtual_cs: /* 32 bit protected mode code segment, virtual addresses */
|
|
57
|
+ .word 0xffff, 0
|
|
58
|
+ .byte 0, 0x9f, 0xcf, 0
|
|
59
|
+
|
|
60
|
+ .org gdt + VIRTUAL_DS, 0
|
|
61
|
+virtual_ds: /* 32 bit protected mode data segment, virtual addresses */
|
|
62
|
+ .word 0xffff, 0
|
|
63
|
+ .byte 0, 0x93, 0xcf, 0
|
220
|
64
|
|
221
|
|
-rm_gdt_rm_cs: /* 16 bit real mode code segment */
|
222
|
|
- .equ RM_CS, rm_gdt_rm_cs - rm_gdt
|
223
|
|
- .word 0xffff,(0&0xffff)
|
224
|
|
- .byte (0>>16),0x9b,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
|
225
|
|
-
|
226
|
|
-rm_gdt_rm_ds: /* 16 bit real mode data segment */
|
227
|
|
- .equ RM_DS, rm_gdt_rm_ds - rm_gdt
|
228
|
|
- .word 0xffff,(0&0xffff)
|
229
|
|
- .byte (0>>16),0x93,RM_LIMIT_16_19__AVL__SIZE__GRANULARITY,(0>>24)
|
|
65
|
+ .org gdt + PHYSICAL_CS, 0
|
|
66
|
+physical_cs: /* 32 bit protected mode code segment, physical addresses */
|
|
67
|
+ .word 0xffff, 0
|
|
68
|
+ .byte 0, 0x9f, 0xcf, 0
|
|
69
|
+
|
|
70
|
+ .org gdt + PHYSICAL_DS, 0
|
|
71
|
+physical_ds: /* 32 bit protected mode data segment, physical addresses */
|
|
72
|
+ .word 0xffff, 0
|
|
73
|
+ .byte 0, 0x93, 0xcf, 0
|
|
74
|
+
|
|
75
|
+ .org gdt + REAL_CS, 0
|
|
76
|
+real_cs: /* 16 bit real mode code segment */
|
|
77
|
+ .word 0xffff, 0
|
|
78
|
+ .byte 0, 0x9b, RM_LIMIT_16_19__AVL__SIZE__GRANULARITY, 0
|
|
79
|
+
|
|
80
|
+ .org gdt + REAL_DS
|
|
81
|
+real_ds: /* 16 bit real mode data segment */
|
|
82
|
+ .word 0xffff, 0
|
|
83
|
+ .byte 0, 0x93, RM_LIMIT_16_19__AVL__SIZE__GRANULARITY, 0
|
230
|
84
|
|
231
|
|
-rm_gdt_end:
|
232
|
|
- .equ rm_gdt_length, rm_gdt_end - rm_gdt
|
|
85
|
+gdt_end:
|
|
86
|
+ .equ gdt_length, gdt_end - gdt
|
233
|
87
|
|
234
|
88
|
/****************************************************************************
|
235
|
|
- * real_to_prot (real-mode far call)
|
236
|
|
- *
|
237
|
|
- * Switch from 16-bit real-mode to 32-bit protected mode with flat
|
238
|
|
- * physical addresses. %esp is restored from the saved pm_esp. All
|
239
|
|
- * segment registers are set to flat physical-mode values. All other
|
240
|
|
- * registers are preserved. Interrupts are disabled.
|
|
89
|
+ * init_gdt (real-mode near call, 16-bit real-mode return address)
|
241
|
90
|
*
|
242
|
|
- * Note that this routine can be called *without* having first set up
|
243
|
|
- * a stored pm_esp or stored GDT. If you do this, real_to_prot will
|
244
|
|
- * return with a temporary stack that is only *FOUR BYTES* in size.
|
245
|
|
- * This is just enough to enable you to do a "call 1f; popl %ebp"
|
246
|
|
- * sequence in order to find out your physical address and then load a
|
247
|
|
- * proper 32-bit protected-mode stack pointer. Do *NOT* use more than
|
248
|
|
- * four bytes since this will overwrite code in librm!
|
|
91
|
+ * Initialise the GDT ready for transitions to protected mode.
|
249
|
92
|
*
|
250
|
|
- * Parameters: none
|
|
93
|
+ * Parameters:
|
|
94
|
+ * %edi : Physical base of protected-mode code
|
251
|
95
|
****************************************************************************
|
252
|
96
|
*/
|
|
97
|
+ .section ".text16"
|
|
98
|
+ .code16
|
|
99
|
+ .globl init_gdt
|
|
100
|
+init_gdt:
|
|
101
|
+ /* Preserve registers */
|
|
102
|
+ pushl %eax
|
|
103
|
+ pushw %bx
|
253
|
104
|
|
254
|
|
- .code16
|
255
|
|
-EXPORT(real_to_prot):
|
256
|
|
- /* Disable interrupts */
|
257
|
|
- cli
|
|
105
|
+ /* Record virt_offset */
|
|
106
|
+ movl %edi, %cs:virt_offset_rm_copy
|
258
|
107
|
|
259
|
|
- /* Set %ds = %cs, for easier access to variables */
|
260
|
|
- pushw %cs
|
261
|
|
- popw %ds
|
262
|
|
-
|
263
|
|
- /* Preserve registers */
|
264
|
|
- movl %eax, %ds:OFFSET(save_eax)
|
265
|
|
- movl %ebx, %ds:OFFSET(save_ebx)
|
|
108
|
+ /* Set virtual_cs and virtual_ds base */
|
|
109
|
+ movl %edi, %eax
|
|
110
|
+ movw $virtual_cs, %bx
|
|
111
|
+ call set_seg_base
|
266
|
112
|
|
267
|
|
- /* Extract real-mode far return address from stack */
|
268
|
|
- popl %ds:OFFSET(save_retaddr)
|
|
113
|
+ /* Set real_cs and real_ds base, and GDT base */
|
|
114
|
+ movw $real_cs, %bx
|
|
115
|
+ xorl %eax, %eax
|
|
116
|
+ movw %cs, %ax
|
|
117
|
+ shll $4, %eax
|
|
118
|
+ call set_seg_base
|
|
119
|
+ addl $gdt, %eax
|
|
120
|
+ movl %eax, %cs:gdt_base
|
269
|
121
|
|
270
|
|
- /* Record real-mode stack pointer */
|
271
|
|
- movw %sp, %ds:OFFSET(rm_sp)
|
272
|
|
- pushw %ss
|
273
|
|
- popw %ds:OFFSET(rm_ss)
|
274
|
|
-
|
275
|
|
- /* Physical base address of librm to %ebx */
|
276
|
|
- xorl %ebx, %ebx
|
277
|
|
- movw %cs, %bx
|
278
|
|
- shll $4, %ebx
|
279
|
|
-
|
280
|
|
- /* Record physical base address of librm */
|
281
|
|
- movl %ebx, %ds:OFFSET(librm_base)
|
282
|
|
-
|
283
|
|
- /* Check base address of stored protected-mode GDT. If it's
|
284
|
|
- * zero, set it up to use our internal GDT (with physical
|
285
|
|
- * segments only).
|
286
|
|
- */
|
287
|
|
- movl %ds:OFFSET(pm_gdt_addr), %eax
|
288
|
|
- testl %eax, %eax
|
289
|
|
- jnz 1f
|
290
|
|
- /* Use internal GDT */
|
291
|
|
- movl %ebx, %eax
|
292
|
|
- addl $OFFSET(pm_gdt), %eax
|
293
|
|
- movl %eax, %ds:OFFSET(pm_gdt_addr)
|
294
|
|
-1:
|
295
|
|
-
|
296
|
|
- /* Set up protected-mode continuation address on real-mode stack */
|
297
|
|
- pushl $PHYSICAL_CS
|
298
|
|
- movl %ebx, %eax
|
299
|
|
- addl $OFFSET(1f), %eax
|
|
122
|
+ /* Restore registers */
|
|
123
|
+ popw %bx
|
|
124
|
+ popl %eax
|
|
125
|
+ ret
|
|
126
|
+
|
|
127
|
+ .section ".text16"
|
|
128
|
+ .code16
|
|
129
|
+set_seg_base:
|
300
|
130
|
pushl %eax
|
|
131
|
+ movw %ax, %cs:(0+2)(%bx)
|
|
132
|
+ movw %ax, %cs:(8+2)(%bx)
|
|
133
|
+ shrl $16, %eax
|
|
134
|
+ movb %al, %cs:(0+4)(%bx)
|
|
135
|
+ movb %al, %cs:(8+4)(%bx)
|
|
136
|
+ movb %ah, %cs:(0+7)(%bx)
|
|
137
|
+ movb %ah, %cs:(8+7)(%bx)
|
|
138
|
+ popl %eax
|
|
139
|
+ ret
|
301
|
140
|
|
302
|
|
- /* Restore protected-mode GDT */
|
303
|
|
- data32 lgdt %ds:OFFSET(pm_gdt)
|
|
141
|
+/****************************************************************************
|
|
142
|
+ * real_to_prot (real-mode near call, 32-bit virtual return address)
|
|
143
|
+ *
|
|
144
|
+ * Switch from 16-bit real-mode to 32-bit protected mode with virtual
|
|
145
|
+ * addresses. The real-mode %ss:sp is stored in rm_ss and rm_sp, and
|
|
146
|
+ * the protected-mode %esp is restored from the saved pm_esp.
|
|
147
|
+ * Interrupts are disabled. All other registers may be destroyed.
|
|
148
|
+ *
|
|
149
|
+ * The return address for this function should be a 32-bit virtual
|
|
150
|
+ * address.
|
|
151
|
+ *
|
|
152
|
+ * Parameters:
|
|
153
|
+ * %ecx : number of bytes to move from RM stack to PM stack
|
|
154
|
+ *
|
|
155
|
+ ****************************************************************************
|
|
156
|
+ */
|
|
157
|
+ .section ".text16"
|
|
158
|
+ .code16
|
|
159
|
+real_to_prot:
|
|
160
|
+ /* Protected-mode return address => %ebx */
|
|
161
|
+ popl %ebx
|
|
162
|
+
|
|
163
|
+ /* Real-mode %cs => %dx, %ss => %bp */
|
|
164
|
+ movw %cs, %dx
|
|
165
|
+ movw %ss, %bp
|
|
166
|
+
|
|
167
|
+ /* virt_offset => %edi */
|
|
168
|
+ movl %cs:virt_offset_rm_copy, %edi
|
304
|
169
|
|
305
|
170
|
/* Switch to protected mode */
|
|
171
|
+ cli
|
|
172
|
+ data32 lgdt %cs:gdt
|
306
|
173
|
movl %cr0, %eax
|
307
|
174
|
orb $CR0_PE, %al
|
308
|
175
|
movl %eax, %cr0
|
309
|
|
-
|
310
|
|
- /* Flush prefetch queue and reload %cs:eip */
|
311
|
|
- data32 lret
|
312
|
|
-1: .code32
|
313
|
|
-
|
314
|
|
- /* Set up protected-mode stack and data segments */
|
315
|
|
- movw $PHYSICAL_DS, %ax
|
|
176
|
+ data32 ljmp $VIRTUAL_CS, $1f
|
|
177
|
+ .section ".text"
|
|
178
|
+ .code32
|
|
179
|
+1:
|
|
180
|
+ /* Set up protected-mode data segments */
|
|
181
|
+ movw $VIRTUAL_DS, %ax
|
316
|
182
|
movw %ax, %ds
|
317
|
183
|
movw %ax, %es
|
318
|
184
|
movw %ax, %fs
|
319
|
185
|
movw %ax, %gs
|
|
186
|
+
|
|
187
|
+ /* Record virt_offset */
|
|
188
|
+ movl %edi, virt_offset
|
|
189
|
+
|
|
190
|
+ /* Move data from RM stack to PM stack and set up PM stack */
|
|
191
|
+ movzwl %sp, %esi
|
|
192
|
+ movl pm_esp, %esp
|
|
193
|
+ subl %ecx, %esp
|
|
194
|
+ movl %esp, %edi
|
|
195
|
+ rep ss movsb
|
320
|
196
|
movw %ax, %ss
|
321
|
197
|
|
322
|
|
- /* Switch to saved protected-mode stack. Note that there may
|
323
|
|
- * not actually *be* a saved protected-mode stack.
|
324
|
|
- */
|
325
|
|
- movl OFFSET(pm_esp)(%ebx), %esp
|
326
|
|
- testl %esp, %esp
|
327
|
|
- jnz 1f
|
328
|
|
- /* No stack - use save_retaddr as a 4-byte temporary stack */
|
329
|
|
- leal OFFSET(save_retaddr+4)(%ebx), %esp
|
330
|
|
-1:
|
331
|
|
-
|
332
|
|
- /* Convert real-mode far return address to physical address
|
333
|
|
- * and place on stack
|
334
|
|
- */
|
335
|
|
- pushl OFFSET(save_retaddr)(%ebx)
|
336
|
|
- xorl %eax, %eax
|
337
|
|
- xchgw 2(%esp), %ax
|
338
|
|
- shll $4, %eax
|
339
|
|
- addl %eax, 0(%esp)
|
|
198
|
+ /* Record real-mode %cs and %ss:sp */
|
|
199
|
+ movw %dx, rm_cs
|
|
200
|
+ movw %bp, rm_ss
|
|
201
|
+ movw %si, rm_sp
|
340
|
202
|
|
341
|
|
- /* Restore registers and return */
|
342
|
|
- movl OFFSET(save_eax)(%ebx), %eax
|
343
|
|
- movl OFFSET(save_ebx)(%ebx), %ebx
|
344
|
|
- ret
|
|
203
|
+ /* Return to virtual address */
|
|
204
|
+ jmp *%ebx
|
345
|
205
|
|
346
|
206
|
/****************************************************************************
|
347
|
|
- * prot_to_real (protected-mode near call, physical addresses)
|
|
207
|
+ * prot_to_real (protected-mode near call, 32-bit real-mode return address)
|
348
|
208
|
*
|
349
|
|
- * Switch from 32-bit protected mode with flat physical addresses to
|
350
|
|
- * 16-bit real mode. %ss:sp is restored from the saved rm_ss and
|
351
|
|
- * rm_sp. %cs is set such that %cs:0000 is the start of librm. All
|
352
|
|
- * other segment registers are set to %ss. All other registers are
|
353
|
|
- * preserved. Interrupts are *not* enabled, since we want to be able
|
354
|
|
- * to use this routine inside an ISR.
|
|
209
|
+ * Switch from 32-bit protected mode with virtual addresses to 16-bit
|
|
210
|
+ * real mode. The protected-mode %esp is stored in pm_esp and the
|
|
211
|
+ * real-mode %ss:sp is restored from the saved rm_ss and rm_sp. All
|
|
212
|
+ * real-mode data segment registers are set equal to %ss. Interrupts
|
|
213
|
+ * are *not* enabled, since we want to be able to use prot_to_real in
|
|
214
|
+ * an ISR. All other registers may be destroyed.
|
355
|
215
|
*
|
356
|
|
- * Note that since %cs:0000 points to the start of librm on exit, it
|
357
|
|
- * follows that the code calling prot_to_real must be located within
|
358
|
|
- * 64kB of the start of librm.
|
|
216
|
+ * The return address for this function should be a 32-bit (sic)
|
|
217
|
+ * real-mode offset within .code16.
|
|
218
|
+ *
|
|
219
|
+ * Parameters:
|
|
220
|
+ * %ecx : number of bytes to move from PM stack to RM stack
|
359
|
221
|
*
|
360
|
|
- * Parameters: none
|
361
|
222
|
****************************************************************************
|
362
|
223
|
*/
|
363
|
|
-
|
|
224
|
+ .section ".text"
|
364
|
225
|
.code32
|
365
|
|
-EXPORT(prot_to_real):
|
366
|
|
- /* Calculate physical base address of librm in %ebx, preserve
|
367
|
|
- * original %eax and %ebx in save_eax and save_ebx
|
368
|
|
- */
|
369
|
|
- pushl %ebx
|
370
|
|
- call 1f
|
371
|
|
-1: popl %ebx
|
372
|
|
- subl $OFFSET(1b), %ebx
|
373
|
|
- popl OFFSET(save_ebx)(%ebx)
|
374
|
|
- movl %eax, OFFSET(save_eax)(%ebx)
|
375
|
|
-
|
376
|
|
- /* Record physical base address of librm */
|
377
|
|
- movl %ebx, OFFSET(librm_base)(%ebx)
|
378
|
|
-
|
379
|
|
- /* Extract return address from the stack, convert to offset
|
380
|
|
- * within librm and save in save_retaddr
|
381
|
|
- */
|
382
|
|
- popl %eax
|
383
|
|
- subl %ebx, %eax
|
384
|
|
- movl %eax, OFFSET(save_retaddr)(%ebx)
|
385
|
|
-
|
386
|
|
- /* Record protected-mode stack pointer */
|
387
|
|
- movl %esp, OFFSET(pm_esp)(%ebx)
|
388
|
|
-
|
389
|
|
- /* Record protected-mode GDT */
|
390
|
|
- sgdt OFFSET(pm_gdt)(%ebx)
|
391
|
|
-
|
392
|
|
- /* Set up real-mode GDT */
|
393
|
|
- leal OFFSET(rm_gdt)(%ebx), %eax
|
394
|
|
- movl %eax, OFFSET(rm_gdt_base)(%ebx)
|
395
|
|
- movl %ebx, %eax
|
396
|
|
- rorl $16, %eax
|
397
|
|
- movw %bx, OFFSET(rm_gdt_rm_cs+2)(%ebx)
|
398
|
|
- movb %al, OFFSET(rm_gdt_rm_cs+4)(%ebx)
|
399
|
|
- movw %bx, OFFSET(rm_gdt_rm_ds+2)(%ebx)
|
400
|
|
- movb %al, OFFSET(rm_gdt_rm_ds+4)(%ebx)
|
|
226
|
+prot_to_real:
|
|
227
|
+ /* Real-mode return address => %ebx */
|
|
228
|
+ popl %ebx
|
401
|
229
|
|
402
|
|
- /* Switch to real-mode GDT and reload segment registers to get
|
403
|
|
- * 64kB limits. Stack is invalidated by this process.
|
404
|
|
- */
|
405
|
|
- lgdt OFFSET(rm_gdt)(%ebx)
|
406
|
|
- ljmp $RM_CS, $1f
|
407
|
|
-1: .code16
|
408
|
|
- movw $RM_DS, %ax
|
|
230
|
+ /* Real-mode %ss:sp => %ebp:edx */
|
|
231
|
+ movzwl rm_ss, %ebp
|
|
232
|
+ movzwl rm_sp, %edx
|
|
233
|
+ subl %ecx, %edx
|
|
234
|
+
|
|
235
|
+ /* Copy data from PM stack to RM stack */
|
|
236
|
+ movl %ebp, %eax
|
|
237
|
+ shll $4, %eax
|
|
238
|
+ leal (%eax,%edx), %edi
|
|
239
|
+ subl virt_offset, %edi
|
|
240
|
+ movl %esp, %esi
|
|
241
|
+ rep movsb
|
|
242
|
+
|
|
243
|
+ /* Record protected-mode %esp */
|
|
244
|
+ movl %esi, pm_esp
|
|
245
|
+
|
|
246
|
+ /* Real-mode %cs => %di */
|
|
247
|
+ movw rm_cs, %di
|
|
248
|
+
|
|
249
|
+ /* Load real-mode segment limits */
|
|
250
|
+ movw $REAL_DS, %ax
|
409
|
251
|
movw %ax, %ds
|
410
|
252
|
movw %ax, %es
|
411
|
253
|
movw %ax, %fs
|
412
|
254
|
movw %ax, %gs
|
413
|
255
|
movw %ax, %ss
|
414
|
|
-
|
415
|
|
- /* Calculate real-mode code segment in %ax and store in ljmp
|
416
|
|
- * instruction
|
417
|
|
- */
|
418
|
|
- movl %ebx, %eax
|
419
|
|
- shrl $4, %eax
|
420
|
|
- movw %ax, OFFSET(p2r_ljmp) + 3
|
421
|
|
-
|
|
256
|
+ ljmp $REAL_CS, $1f
|
|
257
|
+ .section ".text16"
|
|
258
|
+ .code16
|
|
259
|
+1:
|
|
260
|
+ /* Set up real-mode ljmp instruction */
|
|
261
|
+ movw %di, %ds:(p2r_ljmp + 3)
|
|
262
|
+
|
422
|
263
|
/* Switch to real mode */
|
423
|
|
- movl %cr0, %ebx
|
424
|
|
- andb $0!CR0_PE, %bl
|
425
|
|
- movl %ebx, %cr0
|
426
|
|
-
|
427
|
|
- /* Intersegment jump to flush prefetch queue and reload
|
428
|
|
- * %cs:eip. The segment gets filled in by the above code. We
|
429
|
|
- * can't just use lret to achieve this, because we have no
|
430
|
|
- * stack at the moment.
|
431
|
|
- */
|
432
|
|
-p2r_ljmp:
|
433
|
|
- ljmp $0, $OFFSET(1f)
|
434
|
|
-1:
|
435
|
|
-
|
436
|
|
- /* Set %ds to point to code segment for easier data access */
|
437
|
|
- movw %ax, %ds
|
438
|
|
-
|
439
|
|
- /* Restore registers */
|
440
|
|
- movl OFFSET(save_eax), %eax
|
441
|
|
- movl OFFSET(save_ebx), %ebx
|
442
|
|
-
|
443
|
|
- /* Set up real-mode data segments and stack */
|
444
|
|
- movw OFFSET(rm_ss), %ss
|
445
|
|
- movw OFFSET(rm_sp), %sp
|
446
|
|
- pushw %ss
|
447
|
|
- pushw %ss
|
448
|
|
- pushw %ss
|
449
|
|
- pushw %ss
|
450
|
|
- popw %ds
|
451
|
|
- popw %es
|
452
|
|
- popw %fs
|
453
|
|
- popw %gs
|
454
|
|
-
|
455
|
|
- /* Set up return address on stack and return */
|
456
|
|
- pushw %cs:OFFSET(save_retaddr)
|
457
|
|
- ret
|
|
264
|
+ movl %cr0, %eax
|
|
265
|
+ andb $0!CR0_PE, %al
|
|
266
|
+ movl %eax, %cr0
|
458
|
267
|
|
|
268
|
+p2r_ljmp:
|
|
269
|
+ ljmp $0, $1f /* Segment is filled in by above code */
|
|
270
|
+1:
|
|
271
|
+ /* Set up real-mode stack and data segments, and stack pointer */
|
|
272
|
+ movw %bp, %ds
|
|
273
|
+ movw %bp, %es
|
|
274
|
+ movw %bp, %fs
|
|
275
|
+ movw %bp, %gs
|
|
276
|
+ movw %bp, %ss
|
|
277
|
+ movw %dx, %sp
|
|
278
|
+
|
|
279
|
+ /* Return to real-mode address */
|
|
280
|
+ jmp *%bx
|
|
281
|
+
|
459
|
282
|
/****************************************************************************
|
460
|
|
- * prot_call (real-mode far call)
|
|
283
|
+ * prot_call (real-mode near call, 32-bit real-mode return address)
|
461
|
284
|
*
|
462
|
285
|
* Call a specific C function in the protected-mode code. The
|
463
|
286
|
* prototype of the C function must be
|
|
@@ -469,30 +292,12 @@ p2r_ljmp:
|
469
|
292
|
* function explicitly overwrites values in ix86. Interrupt status
|
470
|
293
|
* will also be preserved. Gate A20 will be enabled.
|
471
|
294
|
*
|
472
|
|
- * The protected-mode code may install librm to a new location. If it
|
473
|
|
- * does so, it must update librm_base in *this* copy of librm to point
|
474
|
|
- * to the new physical location. prot_call will then return via the
|
475
|
|
- * newly installed copy.
|
476
|
|
- *
|
477
|
|
- * Note that when Etherboot performs its initial relocation, "*this*"
|
478
|
|
- * copy in the above paragraph will refer to the "master" copy, since
|
479
|
|
- * that is the initial installed copy. Etherboot will return to
|
480
|
|
- * prot_call using a virtual address, so will return to the master
|
481
|
|
- * copy in high memory (rather than the original copy in base memory).
|
482
|
|
- * The master copy in high memory will have the physical address of
|
483
|
|
- * the newly installed copy in librm_base, since install_librm()
|
484
|
|
- * writes it there. Thus, Etherboot's initialise() function will
|
485
|
|
- * return to the master copy of prot_call(), which will then jump to
|
486
|
|
- * the installed copy.
|
487
|
|
- *
|
488
|
|
- * It works, trust me.
|
489
|
|
- *
|
490
|
295
|
* Parameters:
|
491
|
296
|
* function : virtual address of protected-mode function to call
|
492
|
297
|
*
|
493
|
298
|
* Example usage:
|
494
|
299
|
* pushl $pxe_api_call
|
495
|
|
- * lcall $LIBRM_SEGMENT, $prot_call
|
|
300
|
+ * call prot_call
|
496
|
301
|
* addw $4, %sp
|
497
|
302
|
* to call in to the C function
|
498
|
303
|
* void pxe_api_call ( struct i386_all_regs *ix86 );
|
|
@@ -502,10 +307,13 @@ p2r_ljmp:
|
502
|
307
|
#define PC_OFFSET_IX86 ( 0 )
|
503
|
308
|
#define PC_OFFSET_RETADDR ( PC_OFFSET_IX86 + SIZEOF_I386_ALL_REGS )
|
504
|
309
|
#define PC_OFFSET_FUNCTION ( PC_OFFSET_RETADDR + 4 )
|
505
|
|
-
|
|
310
|
+#define PC_OFFSET_END ( PC_OFFSET_FUNCTION + 4 )
|
|
311
|
+
|
|
312
|
+ .section ".text16"
|
506
|
313
|
.code16
|
507
|
|
-EXPORT(prot_call):
|
508
|
|
- /* Preserve registers and flags on RM stack */
|
|
314
|
+ .globl prot_call
|
|
315
|
+prot_call:
|
|
316
|
+ /* Preserve registers and flags on external RM stack */
|
509
|
317
|
pushfl
|
510
|
318
|
pushal
|
511
|
319
|
pushw %gs
|
|
@@ -513,101 +321,46 @@ EXPORT(prot_call):
|
513
|
321
|
pushw %es
|
514
|
322
|
pushw %ds
|
515
|
323
|
pushw %ss
|
516
|
|
- pushw %cs
|
517
|
|
-
|
518
|
|
- /* Record RM stack pointer */
|
519
|
|
- xorl %ebp, %ebp
|
520
|
|
- movw %sp, %bp
|
521
|
|
-
|
522
|
|
- /* Physical address of RM stack pointer to %esi */
|
523
|
|
- xorl %esi, %esi
|
524
|
|
- pushw %ss
|
525
|
|
- popw %si
|
526
|
|
- shll $4, %esi
|
527
|
|
- addl %ebp, %esi
|
528
|
|
-
|
529
|
|
- /* Address of pmode function to %ebx */
|
530
|
|
- movl %ss:(PC_OFFSET_FUNCTION)(%bp), %ebx
|
531
|
|
-
|
532
|
|
- /* Switch to protected mode */
|
533
|
324
|
pushw %cs
|
534
|
|
- call real_to_prot
|
535
|
|
- .code32
|
536
|
325
|
|
537
|
|
- /* Copy ix86 from RM stack to PM stack */
|
538
|
|
- movl $SIZEOF_I386_ALL_REGS, %ecx
|
539
|
|
- subl %ecx, %esp
|
540
|
|
- movl %esp, %edi
|
541
|
|
- pushl %esi
|
|
326
|
+ /* For sanity's sake, clear the direction flag as soon as possible */
|
542
|
327
|
cld
|
543
|
|
- rep movsb
|
544
|
|
- popl %edi /* %edi = phys addr of RM copy of ix86 */
|
545
|
|
-
|
546
|
|
- /* Switch to virtual addresses. */
|
547
|
|
- call 1f
|
548
|
|
- jmp 2f
|
549
|
|
-1: ljmp $VIRTUAL_CS, $_phys_to_virt
|
550
|
|
-2:
|
551
|
328
|
|
552
|
|
- /* Enable A20 line */
|
553
|
|
- pushal
|
554
|
|
- lcall $VIRTUAL_CS, $gateA20_set
|
555
|
|
- popl %eax /* discard */
|
556
|
|
- popal
|
|
329
|
+ /* Switch to protected mode and move register dump to PM stack */
|
|
330
|
+ movl $PC_OFFSET_END, %ecx
|
|
331
|
+ pushl $1f
|
|
332
|
+ jmp real_to_prot
|
|
333
|
+ .section ".text"
|
|
334
|
+ .code32
|
|
335
|
+1:
|
|
336
|
+ /* Set up environment expected by C code */
|
|
337
|
+ call gateA20_set
|
557
|
338
|
|
558
|
|
- /* Push &ix86 on the stack, and call function */
|
|
339
|
+ /* Call function */
|
559
|
340
|
pushl %esp
|
560
|
|
- call *%ebx
|
|
341
|
+ call *(PC_OFFSET_FUNCTION+4)(%esp)
|
561
|
342
|
popl %eax /* discard */
|
562
|
343
|
|
563
|
|
- /* Switch to physical addresses, discard PM register store */
|
564
|
|
- lcall $VIRTUAL_CS, $_virt_to_phys
|
565
|
|
- popl %eax /* discard */
|
566
|
|
-
|
567
|
|
- /* Copy ix86 from PM stack to RM stack, and remove ix86
|
568
|
|
- * from PM stack. (%edi still contains physical address of
|
569
|
|
- * ix86 on RM stack from earlier, since C code preserves
|
570
|
|
- * %edi).
|
571
|
|
- */
|
572
|
|
- movl %esp, %esi
|
573
|
|
- movl $SIZEOF_I386_ALL_REGS, %ecx
|
574
|
|
- cld
|
575
|
|
- rep movsb
|
576
|
|
- movl %esi, %esp /* remove ix86 from PM stack */
|
577
|
|
-
|
578
|
|
- /* Obtain physical base address of installed copy of librm in
|
579
|
|
- * %ebx. (It's possible that this *isn't* the physical base
|
580
|
|
- * address of the copy we're currently executing in, because
|
581
|
|
- * the protected-mode call could have moved librm. If it does
|
582
|
|
- * so, it must update librm_base in our copy to reflect the
|
583
|
|
- * new location.
|
584
|
|
- */
|
585
|
|
- call 1f
|
586
|
|
-1: popl %ebp
|
587
|
|
- movl (librm_base-1b)(%ebp), %ebx
|
588
|
|
-
|
589
|
|
- /* Jump to running in installed copy of librm */
|
590
|
|
- addl $OFFSET(1f), %ebx
|
591
|
|
- jmp *%ebx
|
592
|
|
-1:
|
593
|
|
-
|
594
|
|
- /* Switch to real mode */
|
595
|
|
- call prot_to_real
|
|
344
|
+ /* Switch to real mode and move register dump back to RM stack */
|
|
345
|
+ movl $PC_OFFSET_END, %ecx
|
|
346
|
+ pushl $1f
|
|
347
|
+ jmp prot_to_real
|
|
348
|
+ .section ".text16"
|
596
|
349
|
.code16
|
597
|
|
-
|
598
|
|
- /* Restore registers and flags, and return */
|
599
|
|
- popw %ax /* skip %cs */
|
600
|
|
- popw %ax /* skip %ss */
|
|
350
|
+1:
|
|
351
|
+ /* Restore registers and flags and return */
|
|
352
|
+ popw %ax /* skip %cs - it is already set */
|
|
353
|
+ popw %ax /* skip %ss - it is already set */
|
601
|
354
|
popw %ds
|
602
|
355
|
popw %es
|
603
|
356
|
popw %fs
|
604
|
357
|
popw %gs
|
605
|
358
|
popal
|
606
|
359
|
popfl
|
607
|
|
- lret
|
|
360
|
+ ret
|
608
|
361
|
|
609
|
362
|
/****************************************************************************
|
610
|
|
- * real_call (protected-mode near call, virtual addresses)
|
|
363
|
+ * real_call (protected-mode near call, 32-bit virtual return address)
|
611
|
364
|
*
|
612
|
365
|
* Call a real-mode function from protected-mode code.
|
613
|
366
|
*
|
|
@@ -625,80 +378,58 @@ EXPORT(prot_call):
|
625
|
378
|
* and examples.
|
626
|
379
|
*
|
627
|
380
|
* Parameters:
|
628
|
|
- * far pointer to real-mode function to call
|
|
381
|
+ * (32-bit) near pointer to real-mode function to call
|
629
|
382
|
*
|
630
|
383
|
* Returns: none
|
631
|
384
|
****************************************************************************
|
632
|
385
|
*/
|
633
|
386
|
|
634
|
387
|
#define RC_OFFSET_PRESERVE_REGS ( 0 )
|
635
|
|
-#define RC_OFFSET_RETADDR ( RC_OFFSET_PRESERVE_REGS + 8 )
|
636
|
|
-#define RC_OFFSET_RM_FUNCTION ( RC_OFFSET_RETADDR + 4 )
|
637
|
|
-
|
638
|
|
- .code32
|
639
|
|
-EXPORT(real_call):
|
640
|
|
- /* Preserve registers */
|
641
|
|
- pushl %ebp
|
642
|
|
- pushl %eax
|
643
|
|
-
|
644
|
|
- /* Switch to physical addresses */
|
645
|
|
- lcall $VIRTUAL_CS, $_virt_to_phys
|
646
|
|
- addl $4, %esp
|
647
|
|
-
|
648
|
|
- /* Extract real-mode function address and store in ljmp instruction */
|
649
|
|
- call 1f
|
650
|
|
-1: popl %ebp
|
651
|
|
- movl RC_OFFSET_RM_FUNCTION(%esp), %eax
|
652
|
|
- movl %eax, (rc_ljmp + 1 - 1b)(%ebp)
|
|
388
|
+#define RC_OFFSET_RETADDR ( RC_OFFSET_PRESERVE_REGS + SIZEOF_I386_REGS )
|
|
389
|
+#define RC_OFFSET_FUNCTION ( RC_OFFSET_RETADDR + 4 )
|
|
390
|
+#define RC_OFFSET_END ( RC_OFFSET_FUNCTION + 4 )
|
653
|
391
|
|
654
|
|
- /* Restore registers */
|
655
|
|
- popl %eax
|
656
|
|
- popl %ebp
|
|
392
|
+ .section ".text"
|
|
393
|
+ .code32
|
|
394
|
+ .globl real_call
|
|
395
|
+real_call:
|
|
396
|
+ /* Create register dump on PM stack */
|
|
397
|
+ pushal
|
657
|
398
|
|
658
|
|
- /* Switch to real mode, preserving non-segment registers */
|
659
|
|
- call prot_to_real
|
|
399
|
+ /* Switch to real mode and move register dump to RM stack */
|
|
400
|
+ movl $RC_OFFSET_END, %ecx
|
|
401
|
+ pushl $1f
|
|
402
|
+ jmp prot_to_real
|
|
403
|
+ .section ".text16"
|
660
|
404
|
.code16
|
|
405
|
+1:
|
|
406
|
+ /* Construct call to real-mode function */
|
|
407
|
+ movw %sp, %bp
|
|
408
|
+ movw RC_OFFSET_FUNCTION(%bp), %ax
|
|
409
|
+ movw %ax, %cs:rc_function
|
661
|
410
|
|
662
|
|
- /* Far call to real-mode routine */
|
663
|
|
- pushw %cs
|
664
|
|
- call rc_ljmp
|
665
|
|
- jmp 2f
|
666
|
|
-rc_ljmp:
|
667
|
|
- ljmp $0, $0 /* address filled in by above code */
|
668
|
|
-2:
|
669
|
|
-
|
670
|
|
- /* Switch to protected mode */
|
671
|
|
- pushw %cs
|
672
|
|
- call real_to_prot
|
673
|
|
- .code32
|
|
411
|
+ /* Call real-mode function */
|
|
412
|
+ popal
|
|
413
|
+ call *%cs:rc_function
|
|
414
|
+ pushal
|
674
|
415
|
|
675
|
|
- /* Switch to virtual addresses */
|
676
|
|
- call 1f
|
677
|
|
- jmp 2f
|
678
|
|
-1: ljmp $VIRTUAL_CS, $_phys_to_virt
|
679
|
|
-2:
|
|
416
|
+ /* Switch to protected mode and move register dump back to PM stack */
|
|
417
|
+ movl $RC_OFFSET_END, %ecx
|
|
418
|
+ pushl $1f
|
|
419
|
+ jmp real_to_prot
|
|
420
|
+ .section ".text"
|
|
421
|
+ .code32
|
|
422
|
+1:
|
|
423
|
+ /* Set up environment expected by C code */
|
|
424
|
+ call gateA20_set
|
680
|
425
|
|
681
|
|
- /* Enable A20 line */
|
682
|
|
- pushal
|
683
|
|
- lcall $VIRTUAL_CS, $gateA20_set
|
684
|
|
- popl %eax /* discard */
|
|
426
|
+ /* Restore registers and return */
|
685
|
427
|
popal
|
686
|
|
-
|
687
|
|
- /* Return */
|
688
|
428
|
ret
|
689
|
|
-
|
690
|
|
-/****************************************************************************
|
691
|
|
- * Relocation lock counter
|
692
|
|
- *
|
693
|
|
- * librm may be moved in base memory only when this counter is zero.
|
694
|
|
- * The counter gets incremented whenever a reference to librm is
|
695
|
|
- * generated (e.g. a real_call is made, resulting in a return address
|
696
|
|
- * pointing to librm being placed on the stack), and decremented when
|
697
|
|
- * the reference goes out of scope (e.g. the real_call returns).
|
698
|
|
- ****************************************************************************
|
699
|
|
- */
|
700
|
|
-EXPORT(librm_ref_count): .byte 0
|
701
|
429
|
|
|
430
|
+ .section ".text16"
|
|
431
|
+rc_function: .word 0
|
|
432
|
+
|
702
|
433
|
/****************************************************************************
|
703
|
434
|
* Stored real-mode and protected-mode stack pointers
|
704
|
435
|
*
|
|
@@ -734,25 +465,18 @@ EXPORT(librm_ref_count): .byte 0
|
734
|
465
|
****************************************************************************
|
735
|
466
|
*/
|
736
|
467
|
|
737
|
|
-EXPORT(rm_stack): /* comprises rm_ss and rm_sp */
|
738
|
|
-rm_sp: .word 0
|
739
|
|
-rm_ss: .word 0
|
740
|
|
-
|
741
|
|
-EXPORT(pm_stack):
|
742
|
|
-pm_esp: .long 0
|
743
|
|
-
|
744
|
|
-/****************************************************************************
|
745
|
|
- * Temporary variables
|
746
|
|
- ****************************************************************************
|
747
|
|
- */
|
748
|
|
-save_eax: .long 0
|
749
|
|
-save_ebx: .long 0
|
750
|
|
-save_retaddr: .long 0
|
751
|
|
-
|
752
|
|
-/****************************************************************************
|
753
|
|
- * End of librm
|
754
|
|
- ****************************************************************************
|
755
|
|
- */
|
756
|
|
-_librm_end:
|
757
|
|
- .globl _librm_size
|
758
|
|
- .equ _librm_size, _librm_end - _librm_start
|
|
468
|
+ .section ".data"
|
|
469
|
+ .globl rm_sp
|
|
470
|
+rm_sp: .word 0
|
|
471
|
+ .globl rm_ss
|
|
472
|
+rm_ss: .word 0
|
|
473
|
+ .globl rm_cs
|
|
474
|
+rm_cs: .word 0
|
|
475
|
+ .globl pm_esp
|
|
476
|
+pm_esp: .long _estack
|
|
477
|
+
|
|
478
|
+ .section ".text16"
|
|
479
|
+virt_offset_rm_copy: .long 0
|
|
480
|
+ .section ".data"
|
|
481
|
+ .globl virt_offset
|
|
482
|
+virt_offset: .long 0
|