init_librm() and prot_call() are now real-mode far calls.
authorMichael Brown <mcb30@etherboot.org>
Thu, 25 May 2006 00:06:45 +0000 (00:06 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 25 May 2006 00:06:45 +0000 (00:06 +0000)
install() now calls relocate(), moves the protected-mode code to the new
location, and calls hide_etherboot().

src/arch/i386/interface/pcbios/int13.c
src/arch/i386/prefix/dskprefix.S
src/arch/i386/prefix/libprefix.S
src/arch/i386/transitions/librm.S

index 2683a71..e5f7eda 100644 (file)
@@ -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"
index fff0be4..9b1ebaa 100644 (file)
@@ -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 */
index 3b896ba..602d2dc 100644 (file)
@@ -21,6 +21,7 @@
 
        .arch i386
        .section ".prefix.lib", "awx", @progbits
+       .section ".data16", "aw", @progbits
 
 /****************************************************************************
  * install_block (real-mode near call)
@@ -164,6 +165,47 @@ install_basemem:
        ret
        .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
  *
@@ -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
index 7d59c46..5033a3a 100644 (file)
@@ -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)