summaryrefslogtreecommitdiffstats
path: root/src/arch/i386
diff options
context:
space:
mode:
authorMichael Brown2006-05-25 02:06:45 +0200
committerMichael Brown2006-05-25 02:06:45 +0200
commit89da833c5d75f4505e4e4fd6b83faf59853d1f9d (patch)
tree8b85f912c92ee95e6d1f3944985bbce43bfd7747 /src/arch/i386
parentHas been obsolete for a while. (diff)
downloadipxe-89da833c5d75f4505e4e4fd6b83faf59853d1f9d.tar.gz
ipxe-89da833c5d75f4505e4e4fd6b83faf59853d1f9d.tar.xz
ipxe-89da833c5d75f4505e4e4fd6b83faf59853d1f9d.zip
init_librm() and prot_call() are now real-mode far calls.
install() now calls relocate(), moves the protected-mode code to the new location, and calls hide_etherboot().
Diffstat (limited to 'src/arch/i386')
-rw-r--r--src/arch/i386/interface/pcbios/int13.c3
-rw-r--r--src/arch/i386/prefix/dskprefix.S3
-rw-r--r--src/arch/i386/prefix/libprefix.S196
-rw-r--r--src/arch/i386/transitions/librm.S8
4 files changed, 120 insertions, 90 deletions
diff --git a/src/arch/i386/interface/pcbios/int13.c b/src/arch/i386/interface/pcbios/int13.c
index 2683a718..e5f7edae 100644
--- a/src/arch/i386/interface/pcbios/int13.c
+++ b/src/arch/i386/interface/pcbios/int13.c
@@ -393,7 +393,8 @@ static void hook_int13 ( void ) {
"\nint13_wrapper:\n\t"
"orb $0, %%al\n\t" /* clear CF and OF */
"pushl %0\n\t" /* call int13() */
- "data32 call prot_call\n\t"
+ "pushw %%cs\n\t"
+ "call prot_call\n\t"
"jo 1f\n\t" /* chain if OF not set */
"pushfw\n\t"
"lcall *%%cs:int13_vector\n\t"
diff --git a/src/arch/i386/prefix/dskprefix.S b/src/arch/i386/prefix/dskprefix.S
index fff0be41..9b1ebaaf 100644
--- a/src/arch/i386/prefix/dskprefix.S
+++ b/src/arch/i386/prefix/dskprefix.S
@@ -357,7 +357,8 @@ start_runtime:
.section ".text16", "awx", @progbits
1:
pushl $main
- data32 call prot_call
+ pushw %cs
+ call prot_call
popl %eax /* discard */
/* Boot next device */
diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S
index 3b896ba1..602d2dc1 100644
--- a/src/arch/i386/prefix/libprefix.S
+++ b/src/arch/i386/prefix/libprefix.S
@@ -21,6 +21,7 @@
.arch i386
.section ".prefix.lib", "awx", @progbits
+ .section ".data16", "aw", @progbits
/****************************************************************************
* install_block (real-mode near call)
@@ -165,6 +166,47 @@ install_basemem:
.size install_basemem, . - install_basemem
/****************************************************************************
+ * install_highmem (flat real-mode near call)
+ *
+ * Install .text and .data into high memory
+ *
+ * Parameters:
+ * %es:edi : address in high memory
+ * Returns:
+ * none
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+
+#ifndef KEEP_IT_REAL
+
+ .section ".prefix.lib"
+ .code16
+install_highmem:
+ /* Preserve registers */
+ pushl %esi
+ pushl %edi
+ pushl %ecx
+ pushl %edx
+
+ /* Install .text and .data to specified address */
+ movl $_textdata_load_offset, %esi
+ movl $_textdata_progbits_size, %ecx
+ movl $_textdata_size, %edx
+ call install_block
+
+ /* Restore registers and interrupt status */
+ popl %edx
+ popl %ecx
+ popl %edi
+ popl %esi
+ ret
+ .size install_highmem, . - install_highmem
+
+#endif /* KEEP_IT_REAL */
+
+/****************************************************************************
* GDT for flat real mode
*
* We only ever use this GDT to set segment limits; the bases are
@@ -183,11 +225,6 @@ gdt_limit: .word gdt_length - 1
gdt_base: .long 0
.word 0 /* padding */
-real_ds: /* Genuine real mode data segment */
- .equ REAL_DS, real_ds - gdt
- .word 0xffff, 0
- .byte 0, 0x93, 0, 0
-
flat_ds: /* Flat real mode data segment */
.equ FLAT_DS, flat_ds - gdt
.word 0xffff, 0
@@ -200,12 +237,12 @@ gdt_end:
#endif /* KEEP_IT_REAL */
/****************************************************************************
- * set_segment_limits (real-mode near call)
+ * flatten_real_mode (real-mode near call)
*
- * Sets limits on the data segments %ds and %es.
+ * Sets 4GB limits on the data segments %ds and %es.
*
* Parameters:
- * %cx : Segment limit ($REAL_DS or $FLAT_DS)
+ * none
****************************************************************************
*/
@@ -213,7 +250,7 @@ gdt_end:
.section ".prefix.lib"
.code16
-set_segment_limits:
+flatten_real_mode:
/* Preserve real-mode segment values and temporary registers */
pushw %es
pushw %ds
@@ -227,12 +264,18 @@ set_segment_limits:
movl %eax, %cs:gdt_base
lgdt %cs:gdt
- /* Switch to protected mode, set segment limits, switch back */
+ /* Switch to protected mode */
movl %cr0, %eax
orb $CR0_PE, %al
movl %eax, %cr0
- movw %cx, %ds
- movw %cx, %es
+
+ /* Set flat segment limits */
+ movw $FLAT_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+
+ /* Switch back to real mode */
+ movl %cr0, %eax
andb $0!CR0_PE, %al
movl %eax, %cr0
@@ -241,61 +284,7 @@ set_segment_limits:
popw %ds
popw %es
ret
- .size set_segment_limits, . - set_segment_limits
-
-#endif /* KEEP_IT_REAL */
-
-/****************************************************************************
- * install_highmem (real-mode near call)
- *
- * Install .text and .data into high memory
- *
- * Parameters:
- * %edi : physical address in high memory
- * Returns:
- * none
- * Corrupts:
- * none
- ****************************************************************************
- */
-
-#ifndef KEEP_IT_REAL
-
- .section ".prefix.lib"
- .code16
-install_highmem:
- /* Preserve registers and interrupt status */
- pushfl
- pushl %esi
- pushl %edi
- pushl %ecx
- pushl %edx
-
- /* Disable interrupts and flatten real mode */
- cli
- movw $FLAT_DS, %cx
- call set_segment_limits
-
- /* Install .text and .data to specified address */
- xorw %cx, %cx
- movw %cx, %es
- movl $_textdata_load_offset, %esi
- movl $_textdata_progbits_size, %ecx
- movl $_textdata_size, %edx
- call install_block
-
- /* Unflatten real mode */
- movw $REAL_DS, %cx
- call set_segment_limits
-
- /* Restore registers and interrupt status */
- popl %edx
- popl %ecx
- popl %edi
- popl %esi
- popfl
- ret
- .size install_highmem, . - install_highmem
+ .size flatten_real_mode, . - flatten_real_mode
#endif /* KEEP_IT_REAL */
@@ -329,32 +318,71 @@ install_prealloc:
call install_basemem
#ifndef KEEP_IT_REAL
+ /* Preserve registers and interrupt status, and disable interrupts */
+ pushfw
+ pushw %ds
+ pushw %es
+ pushl %esi
+ pushl %ecx
+ cli
+
+ /* Load up %ds and %es, and set up vectors for far calls to .text16 */
+ movw %bx, %ds
+ xorw %si, %si
+ movw %si, %es
+ movw %ax, (init_librm_vector+2)
+ movw %ax, (prot_call_vector+2)
+
/* Install .text and .data to 2MB mark. Use 2MB to avoid
* problems with A20.
*/
+ call flatten_real_mode
movl $(2<<20), %edi
call install_highmem
- /* Continue executing in .text16 segment */
- movw %bx, %ds
- pushw %cs
- pushw $2f
- pushw %ax
- pushw $1f
- lret
- .section ".text16", "awx", @progbits
-1:
- /* Set up protected-mode GDT, call relocate(), reset GDT */
- call init_librm
+ /* Set up initial protected-mode GDT, call relocate().
+ * relocate() will return with %esi, %edi and %ecx set up
+ * ready for the copy to the new location.
+ */
+ lcall *init_librm_vector
pushl $relocate
- data32 call prot_call
+ lcall *prot_call_vector
addw $4, %sp
- call init_librm
- /* Return to executing in .prefix section */
- lret
- .section ".prefix.lib"
-2:
+ /* Move code to new location, set up new protected-mode GDT */
+ call flatten_real_mode
+ pushl %edi
+ es rep addr32 movsb
+ popl %edi
+ lcall *init_librm_vector
+
+ /* Hide Etherboot from BIOS memory map. Note that making this
+ * protected-mode call will also restore normal (non-flat)
+ * real mode, as part of the protected-to-real transition.
+ */
+ pushl $hide_etherboot
+ lcall *prot_call_vector
+ addw $4, %sp
+
+ /* Restore registers and interrupt status */
+ popl %ecx
+ popl %esi
+ popw %es
+ popw %ds
+ popfw
#endif
ret
.size install_prealloc, . - install_prealloc
+
+#ifndef KEEP_IT_REAL
+ /* Vectors for far calls to .text16 functions */
+ .section ".data16"
+init_librm_vector:
+ .word init_librm
+ .word 0
+ .size init_librm_vector, . - init_librm_vector
+prot_call_vector:
+ .word prot_call
+ .word 0
+ .size prot_call_vector, . - prot_call_vector
+#endif
diff --git a/src/arch/i386/transitions/librm.S b/src/arch/i386/transitions/librm.S
index 7d59c466..5033a3aa 100644
--- a/src/arch/i386/transitions/librm.S
+++ b/src/arch/i386/transitions/librm.S
@@ -88,7 +88,7 @@ gdt_end:
.equ gdt_length, gdt_end - gdt
/****************************************************************************
- * init_librm (real-mode near call, 16-bit real-mode return address)
+ * init_librm (real-mode far call, 16-bit real-mode far return address)
*
* Initialise the GDT ready for transitions to protected mode.
*
@@ -143,7 +143,7 @@ init_librm:
negl %edi
popl %ebx
popl %eax
- ret
+ lret
.section ".text16"
.code16
@@ -316,7 +316,7 @@ rm_cs: .word 0
rm_ds: .word 0
/****************************************************************************
- * prot_call (real-mode near call, 32-bit real-mode return address)
+ * prot_call (real-mode far call, 16-bit real-mode far return address)
*
* Call a specific C function in the protected-mode code. The
* prototype of the C function must be
@@ -405,7 +405,7 @@ prot_call:
* zeroes the high word of %esp, and interrupts
* are still disabled at this point. */
popfl
- data32 ret
+ lret
/****************************************************************************
* real_call (protected-mode near call, 32-bit virtual return address)