|
@@ -24,7 +24,7 @@
|
24
|
24
|
/****************************************************************************
|
25
|
25
|
* Global descriptor table
|
26
|
26
|
*
|
27
|
|
- * Call init_gdt to set up the GDT before attempting to use any
|
|
27
|
+ * Call init_librm to set up the GDT before attempting to use any
|
28
|
28
|
* protected-mode code.
|
29
|
29
|
*
|
30
|
30
|
* Define FLATTEN_REAL_MODE if you want to use so-called "flat real
|
|
@@ -45,7 +45,7 @@
|
45
|
45
|
#else
|
46
|
46
|
#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
|
47
|
47
|
#endif
|
48
|
|
- .section ".text16"
|
|
48
|
+ .section ".data16", "aw", @progbits
|
49
|
49
|
.align 16
|
50
|
50
|
gdt:
|
51
|
51
|
gdt_limit: .word gdt_length - 1
|
|
@@ -86,56 +86,71 @@ gdt_end:
|
86
|
86
|
.equ gdt_length, gdt_end - gdt
|
87
|
87
|
|
88
|
88
|
/****************************************************************************
|
89
|
|
- * init_gdt (real-mode near call, 16-bit real-mode return address)
|
|
89
|
+ * init_librm (real-mode near call, 16-bit real-mode return address)
|
90
|
90
|
*
|
91
|
91
|
* Initialise the GDT ready for transitions to protected mode.
|
92
|
92
|
*
|
93
|
|
- * Parameters:
|
94
|
|
- * %edi : Physical base of protected-mode code
|
|
93
|
+ * Parameters:
|
|
94
|
+ * %cs : .text16 segment
|
|
95
|
+ * %ds : .data16 segment
|
|
96
|
+ * %edi : Physical base of protected-mode code (virt_offset)
|
95
|
97
|
****************************************************************************
|
96
|
98
|
*/
|
97
|
99
|
.section ".text16"
|
98
|
100
|
.code16
|
99
|
|
- .globl init_gdt
|
100
|
|
-init_gdt:
|
|
101
|
+ .globl init_librm
|
|
102
|
+init_librm:
|
101
|
103
|
/* Preserve registers */
|
102
|
104
|
pushl %eax
|
103
|
|
- pushw %bx
|
104
|
|
-
|
105
|
|
- /* Record virt_offset */
|
106
|
|
- movl %edi, %cs:virt_offset_rm_copy
|
|
105
|
+ pushl %ebx
|
107
|
106
|
|
108
|
|
- /* Set virtual_cs and virtual_ds base */
|
|
107
|
+ /* Store _virt_offset and set up virtual_cs and virtual_ds segments */
|
109
|
108
|
movl %edi, %eax
|
110
|
109
|
movw $virtual_cs, %bx
|
111
|
110
|
call set_seg_base
|
112
|
|
-
|
113
|
|
- /* Set real_cs and real_ds base, and GDT base */
|
114
|
|
- movw $real_cs, %bx
|
|
111
|
+ movw $virtual_ds, %bx
|
|
112
|
+ call set_seg_base
|
|
113
|
+ movl %edi, _virt_offset
|
|
114
|
+
|
|
115
|
+ /* Negate virt_offset */
|
|
116
|
+ negl %edi
|
|
117
|
+
|
|
118
|
+ /* Store rm_cs and _text16, set up real_cs segment */
|
115
|
119
|
xorl %eax, %eax
|
116
|
120
|
movw %cs, %ax
|
|
121
|
+ movw %ax, rm_cs
|
117
|
122
|
shll $4, %eax
|
|
123
|
+ movw $real_cs, %bx
|
118
|
124
|
call set_seg_base
|
119
|
|
- addl $gdt, %eax
|
120
|
|
- movl %eax, %cs:gdt_base
|
|
125
|
+ leal (%eax, %edi), %ebx
|
|
126
|
+ movl %ebx, _text16
|
121
|
127
|
|
|
128
|
+ /* Store rm_ds and _data16, set up real_ds segment and set GDT base */
|
|
129
|
+ xorl %eax, %eax
|
|
130
|
+ movw %ds, %ax
|
|
131
|
+ movw %ax, %cs:rm_ds
|
|
132
|
+ shll $4, %eax
|
|
133
|
+ movw $real_ds, %bx
|
|
134
|
+ call set_seg_base
|
|
135
|
+ leal (%eax, %edi), %ebx
|
|
136
|
+ movl %ebx, _data16
|
|
137
|
+ addl $gdt, %eax
|
|
138
|
+ movl %eax, gdt_base
|
|
139
|
+
|
122
|
140
|
/* Restore registers */
|
123
|
|
- popw %bx
|
|
141
|
+ negl %edi
|
|
142
|
+ popl %ebx
|
124
|
143
|
popl %eax
|
125
|
144
|
ret
|
126
|
145
|
|
127
|
146
|
.section ".text16"
|
128
|
147
|
.code16
|
129
|
148
|
set_seg_base:
|
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
|
|
149
|
+1: movw %ax, 2(%bx)
|
|
150
|
+ rorl $16, %eax
|
|
151
|
+ movb %al, 4(%bx)
|
|
152
|
+ movb %ah, 7(%bx)
|
|
153
|
+ roll $16, %eax
|
139
|
154
|
ret
|
140
|
155
|
|
141
|
156
|
/****************************************************************************
|
|
@@ -157,19 +172,25 @@ set_seg_base:
|
157
|
172
|
.section ".text16"
|
158
|
173
|
.code16
|
159
|
174
|
real_to_prot:
|
160
|
|
- /* Protected-mode return address => %ebx */
|
161
|
|
- popl %ebx
|
162
|
|
-
|
163
|
|
- /* Real-mode %cs => %dx, %ss => %bp */
|
164
|
|
- movw %cs, %dx
|
|
175
|
+ /* Make sure we have our data segment available */
|
|
176
|
+ movw %cs:rm_ds, %ax
|
|
177
|
+ movw %ax, %ds
|
|
178
|
+
|
|
179
|
+ /* Add _virt_offset, _text16 and _data16 to stack to be
|
|
180
|
+ * copied, and also copy the return address.
|
|
181
|
+ */
|
|
182
|
+ pushl _virt_offset
|
|
183
|
+ pushl _text16
|
|
184
|
+ pushl _data16
|
|
185
|
+ addw $16, %cx /* %ecx must be less than 64kB anyway */
|
|
186
|
+
|
|
187
|
+ /* Real-mode %ss:%sp => %bp:%esi */
|
165
|
188
|
movw %ss, %bp
|
166
|
|
-
|
167
|
|
- /* virt_offset => %edi */
|
168
|
|
- movl %cs:virt_offset_rm_copy, %edi
|
|
189
|
+ movzwl %sp, %esi
|
169
|
190
|
|
170
|
191
|
/* Switch to protected mode */
|
171
|
192
|
cli
|
172
|
|
- data32 lgdt %cs:gdt
|
|
193
|
+ data32 lgdt gdt
|
173
|
194
|
movl %cr0, %eax
|
174
|
195
|
orb $CR0_PE, %al
|
175
|
196
|
movl %eax, %cr0
|
|
@@ -184,24 +205,24 @@ real_to_prot:
|
184
|
205
|
movw %ax, %fs
|
185
|
206
|
movw %ax, %gs
|
186
|
207
|
|
187
|
|
- /* Record virt_offset */
|
188
|
|
- movl %edi, virt_offset
|
189
|
|
-
|
190
|
208
|
/* Move data from RM stack to PM stack and set up PM stack */
|
191
|
|
- movzwl %sp, %esi
|
192
|
209
|
movl pm_esp, %esp
|
193
|
210
|
subl %ecx, %esp
|
194
|
211
|
movl %esp, %edi
|
195
|
212
|
rep ss movsb
|
196
|
213
|
movw %ax, %ss
|
197
|
214
|
|
198
|
|
- /* Record real-mode %cs and %ss:sp */
|
199
|
|
- movw %dx, rm_cs
|
|
215
|
+ /* Record real-mode %ss:sp (after removal of data) */
|
200
|
216
|
movw %bp, rm_ss
|
201
|
217
|
movw %si, rm_sp
|
202
|
218
|
|
|
219
|
+ /* Publish virt_offset, text16 and data16 for PM code to use */
|
|
220
|
+ popl data16
|
|
221
|
+ popl text16
|
|
222
|
+ popl virt_offset
|
|
223
|
+
|
203
|
224
|
/* Return to virtual address */
|
204
|
|
- jmp *%ebx
|
|
225
|
+ ret
|
205
|
226
|
|
206
|
227
|
/****************************************************************************
|
207
|
228
|
* prot_to_real (protected-mode near call, 32-bit real-mode return address)
|
|
@@ -209,9 +230,9 @@ real_to_prot:
|
209
|
230
|
* Switch from 32-bit protected mode with virtual addresses to 16-bit
|
210
|
231
|
* real mode. The protected-mode %esp is stored in pm_esp and the
|
211
|
232
|
* 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.
|
|
233
|
+ * real-mode data segment registers are loaded from the saved rm_ds.
|
|
234
|
+ * Interrupts are *not* enabled, since we want to be able to use
|
|
235
|
+ * prot_to_real in an ISR. All other registers may be destroyed.
|
215
|
236
|
*
|
216
|
237
|
* The return address for this function should be a 32-bit (sic)
|
217
|
238
|
* real-mode offset within .code16.
|
|
@@ -224,15 +245,15 @@ real_to_prot:
|
224
|
245
|
.section ".text"
|
225
|
246
|
.code32
|
226
|
247
|
prot_to_real:
|
227
|
|
- /* Real-mode return address => %ebx */
|
228
|
|
- popl %ebx
|
|
248
|
+ /* Add return address to data to be moved to RM stack */
|
|
249
|
+ addl $4, %ecx
|
229
|
250
|
|
230
|
251
|
/* Real-mode %ss:sp => %ebp:edx */
|
231
|
252
|
movzwl rm_ss, %ebp
|
232
|
253
|
movzwl rm_sp, %edx
|
233
|
254
|
subl %ecx, %edx
|
234
|
255
|
|
235
|
|
- /* Copy data from PM stack to RM stack */
|
|
256
|
+ /* Move data from PM stack to RM stack */
|
236
|
257
|
movl %ebp, %eax
|
237
|
258
|
shll $4, %eax
|
238
|
259
|
leal (%eax,%edx), %edi
|
|
@@ -240,12 +261,9 @@ prot_to_real:
|
240
|
261
|
movl %esp, %esi
|
241
|
262
|
rep movsb
|
242
|
263
|
|
243
|
|
- /* Record protected-mode %esp */
|
|
264
|
+ /* Record protected-mode %esp (after removal of data) */
|
244
|
265
|
movl %esi, pm_esp
|
245
|
266
|
|
246
|
|
- /* Real-mode %cs => %di */
|
247
|
|
- movw rm_cs, %di
|
248
|
|
-
|
249
|
267
|
/* Load real-mode segment limits */
|
250
|
268
|
movw $REAL_DS, %ax
|
251
|
269
|
movw %ax, %ds
|
|
@@ -257,27 +275,40 @@ prot_to_real:
|
257
|
275
|
.section ".text16"
|
258
|
276
|
.code16
|
259
|
277
|
1:
|
260
|
|
- /* Set up real-mode ljmp instruction */
|
261
|
|
- movw %di, %ds:(p2r_ljmp + 3)
|
262
|
|
-
|
263
|
278
|
/* Switch to real mode */
|
264
|
279
|
movl %cr0, %eax
|
265
|
280
|
andb $0!CR0_PE, %al
|
266
|
281
|
movl %eax, %cr0
|
|
282
|
+ ljmp *p2r_jump_vector
|
|
283
|
+p2r_jump_target:
|
267
|
284
|
|
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
|
|
285
|
+ /* Set up real-mode stack */
|
276
|
286
|
movw %bp, %ss
|
277
|
287
|
movw %dx, %sp
|
|
288
|
+
|
|
289
|
+ /* Set up real-mode data segments */
|
|
290
|
+ movw %cs:rm_ds, %ax
|
|
291
|
+ movw %ax, %ds
|
|
292
|
+ movw %ax, %es
|
|
293
|
+ movw %ax, %fs
|
|
294
|
+ movw %ax, %gs
|
278
|
295
|
|
279
|
296
|
/* Return to real-mode address */
|
280
|
|
- jmp *%bx
|
|
297
|
+ data32 ret
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+ /* Real-mode code and data segments. Assigned by the call to
|
|
301
|
+ * init_librm. rm_cs doubles as the segment part of the jump
|
|
302
|
+ * vector used by prot_to_real. rm_ds is located in .text16
|
|
303
|
+ * rather than .data16 because code needs to be able to locate
|
|
304
|
+ * the data segment.
|
|
305
|
+ */
|
|
306
|
+ .section ".data16"
|
|
307
|
+p2r_jump_vector:
|
|
308
|
+ .word p2r_jump_target
|
|
309
|
+rm_cs: .word 0
|
|
310
|
+ .section ".text16"
|
|
311
|
+rm_ds: .word 0
|
281
|
312
|
|
282
|
313
|
/****************************************************************************
|
283
|
314
|
* prot_call (real-mode near call, 32-bit real-mode return address)
|
|
@@ -406,11 +437,12 @@ real_call:
|
406
|
437
|
/* Construct call to real-mode function */
|
407
|
438
|
movw %sp, %bp
|
408
|
439
|
movw RC_OFFSET_FUNCTION(%bp), %ax
|
409
|
|
- movw %ax, %cs:rc_function
|
|
440
|
+ movw %ax, rc_function
|
410
|
441
|
|
411
|
442
|
/* Call real-mode function */
|
412
|
443
|
popal
|
413
|
|
- call *%cs:rc_function
|
|
444
|
+ call *RC_OFFSET_FUNCTION(%esp)
|
|
445
|
+ call *rc_function
|
414
|
446
|
pushal
|
415
|
447
|
|
416
|
448
|
/* Switch to protected mode and move register dump back to PM stack */
|
|
@@ -427,7 +459,9 @@ real_call:
|
427
|
459
|
popal
|
428
|
460
|
ret
|
429
|
461
|
|
430
|
|
- .section ".text16"
|
|
462
|
+
|
|
463
|
+ /* Function vector, used because */
|
|
464
|
+ .section ".data16"
|
431
|
465
|
rc_function: .word 0
|
432
|
466
|
|
433
|
467
|
/****************************************************************************
|
|
@@ -464,19 +498,33 @@ rc_function: .word 0
|
464
|
498
|
* to us.
|
465
|
499
|
****************************************************************************
|
466
|
500
|
*/
|
467
|
|
-
|
468
|
501
|
.section ".data"
|
469
|
502
|
.globl rm_sp
|
470
|
503
|
rm_sp: .word 0
|
471
|
504
|
.globl rm_ss
|
472
|
505
|
rm_ss: .word 0
|
473
|
|
- .globl rm_cs
|
474
|
|
-rm_cs: .word 0
|
475
|
506
|
.globl pm_esp
|
476
|
507
|
pm_esp: .long _estack
|
477
|
508
|
|
478
|
|
- .section ".text16"
|
479
|
|
-virt_offset_rm_copy: .long 0
|
|
509
|
+/****************************************************************************
|
|
510
|
+ * Virtual address offsets
|
|
511
|
+ *
|
|
512
|
+ * These are used by the protected-mode code to map between virtual
|
|
513
|
+ * and physical addresses, and to access variables in the .text16 or
|
|
514
|
+ * .data16 segments.
|
|
515
|
+ ****************************************************************************
|
|
516
|
+ */
|
|
517
|
+ /* Internal copies, created by init_librm (which runs in real mode) */
|
|
518
|
+ .section ".data16"
|
|
519
|
+_virt_offset: .long 0
|
|
520
|
+_text16: .long 0
|
|
521
|
+_data16: .long 0
|
|
522
|
+
|
|
523
|
+ /* Externally-visible copies, created by real_to_prot */
|
480
|
524
|
.section ".data"
|
481
|
525
|
.globl virt_offset
|
482
|
|
-virt_offset: .long 0
|
|
526
|
+virt_offset: .long 0
|
|
527
|
+ .globl text16
|
|
528
|
+text16: .long 0
|
|
529
|
+ .globl data16
|
|
530
|
+data16: .long 0
|