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().
pull/1/head
Michael Brown 2006-05-25 00:06:45 +00:00
parent 4d81b48504
commit 89da833c5d
4 changed files with 120 additions and 90 deletions

View 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"

View 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 */

View 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

View 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)