david/ipxe
Archived
1
0

[prefix] Use flat real mode for access to high memory

Use flat real mode rather than 16-bit protected mode for access to
high memory during installation.  This simplifies the code by reducing
the number of CPU modes we need to think about, and also increases the
amount of code in common between the normal and (somewhat
hypothetical) KEEP_IT_REAL methods of operation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2010-04-19 22:22:11 +01:00
parent cb43056809
commit 6c35a525da

View File

@ -233,156 +233,128 @@ print_kill_line:
.size print_kill_line, . - print_kill_line .size print_kill_line, . - print_kill_line
/**************************************************************************** /****************************************************************************
* pm_call (real-mode near call) * flatten_real_mode
* *
* Call routine in 16-bit protected mode for access to extended memory * Set up 4GB segment limits
* *
* Parameters: * Parameters:
* %ax : address of routine to call in 16-bit protected mode * none
* Returns: * Returns:
* none * none
* Corrupts: * Corrupts:
* %ax * none
*
* The specified routine is called in 16-bit protected mode, with:
*
* %cs : 16-bit code segment with base matching real-mode %cs
* %ss : 16-bit data segment with base matching real-mode %ss
* %ds,%es,%fs,%gs : 32-bit data segment with zero base and 4GB limit
*
**************************************************************************** ****************************************************************************
*/ */
#ifndef KEEP_IT_REAL #ifndef KEEP_IT_REAL
/* GDT for protected-mode calls */ /* GDT for protected-mode calls */
.section ".prefix.lib", "awx", @progbits .section ".prefix.lib", "awx", @progbits
.align 16 .align 16
pm_call_vars: flatten_vars:
gdt: flatten_gdt:
gdt_limit: .word gdt_length - 1 flatten_gdt_limit: .word flatten_gdt_length - 1
gdt_base: .long 0 flatten_gdt_base: .long 0
.word 0 /* padding */ .word 0 /* padding */
pm_cs: /* 16-bit protected-mode flat code segment */ flatten_cs: /* 16-bit protected-mode flat code segment */
.equ PM_CS, pm_cs - gdt .equ FLAT_CS, flatten_cs - flatten_gdt
.word 0xffff, 0 .word 0xffff, 0
.byte 0, 0x9b, 0x8f, 0 .byte 0, 0x9b, 0x8f, 0
pm_ss: /* 16-bit protected-mode flat stack segment */ flatten_ss: /* 16-bit protected-mode flat stack segment */
.equ PM_SS, pm_ss - gdt .equ FLAT_SS, flatten_ss - flatten_gdt
.word 0xffff, 0 .word 0xffff, 0
.byte 0, 0x93, 0x8f, 0 .byte 0, 0x93, 0x8f, 0
pm_ds: /* 32-bit protected-mode flat data segment */ flatten_gdt_end:
.equ PM_DS, pm_ds - gdt .equ flatten_gdt_length, . - flatten_gdt
.word 0xffff, 0 .size flatten_gdt, . - flatten_gdt
.byte 0, 0x93, 0xcf, 0
gdt_end:
.equ gdt_length, . - gdt
.size gdt, . - gdt
.section ".prefix.lib", "awx", @progbits .section ".prefix.lib", "awx", @progbits
.align 16 .align 16
pm_saved_gdt: flatten_saved_gdt:
.long 0, 0 .long 0, 0
.size pm_saved_gdt, . - pm_saved_gdt .size flatten_saved_gdt, . - flatten_saved_gdt
.equ pm_call_vars_size, . - pm_call_vars .equ flatten_vars_size, . - flatten_vars
#define PM_CALL_VAR(x) ( -pm_call_vars_size + ( (x) - pm_call_vars ) ) #define FLATTEN_VAR(x) ( -flatten_vars_size + ( (x) - flatten_vars ) )
.section ".prefix.lib", "awx", @progbits .section ".prefix.lib", "awx", @progbits
.code16 .code16
pm_call: flatten_real_mode:
/* Preserve registers, flags, and RM return point */ /* Preserve registers and flags, allocate local variable block */
pushw %bp pushw %bp
movw %sp, %bp movw %sp, %bp
subw $pm_call_vars_size, %sp subw $flatten_vars_size, %sp
andw $0xfff0, %sp andw $0xfff0, %sp
pushfl pushfl
pushl %eax
pushl %edi
pushw %si
pushw %cx
pushw %gs pushw %gs
pushw %fs pushw %fs
pushw %es pushw %es
pushw %ds pushw %ds
pushw %ss pushw %ss
pushw %cs
pushw $99f
/* Set up local variable block, and preserve GDT */ /* Fill local variable block and preserve GDT */
pushw %cx
pushw %si
pushw %di
pushw %ss pushw %ss
popw %es popw %es
movw $pm_call_vars, %si movw $flatten_vars, %si
leaw PM_CALL_VAR(pm_call_vars)(%bp), %di leaw FLATTEN_VAR(flatten_vars)(%bp), %di
movw $pm_call_vars_size, %cx movw $flatten_vars_size, %cx
cs rep movsb cs rep movsb
popw %di sgdt FLATTEN_VAR(flatten_saved_gdt)(%bp)
popw %si
popw %cx
sgdt PM_CALL_VAR(pm_saved_gdt)(%bp)
/* Set up GDT bases */ /* Set up GDT bases */
pushl %eax
pushl %edi
xorl %eax, %eax xorl %eax, %eax
movw %ss, %ax movw %ss, %ax
shll $4, %eax shll $4, %eax
movzwl %bp, %edi movzwl %bp, %edi
addr32 leal PM_CALL_VAR(gdt)(%eax, %edi), %eax addr32 leal FLATTEN_VAR(flatten_gdt)(%eax, %edi), %eax
movl %eax, PM_CALL_VAR(gdt_base)(%bp) movl %eax, FLATTEN_VAR(flatten_gdt_base)(%bp)
movw %cs, %ax movw %cs, %ax
movw $PM_CALL_VAR(pm_cs), %di movw $FLATTEN_VAR(flatten_cs), %di
call set_seg_base call set_seg_base
movw %ss, %ax movw %ss, %ax
movw $PM_CALL_VAR(pm_ss), %di movw $FLATTEN_VAR(flatten_ss), %di
call set_seg_base call set_seg_base
popl %edi
popl %eax
/* Switch CPU to protected mode and load up segment registers */ /* Switch temporarily to protected mode and set segment registers */
pushl %eax pushw %cs
pushw $2f
cli cli
data32 lgdt PM_CALL_VAR(gdt)(%bp) data32 lgdt FLATTEN_VAR(flatten_gdt)(%bp)
movl %cr0, %eax movl %cr0, %eax
orb $CR0_PE, %al orb $CR0_PE, %al
movl %eax, %cr0 movl %eax, %cr0
ljmp $PM_CS, $1f ljmp $FLAT_CS, $1f
1: movw $PM_SS, %ax 1: movw $FLAT_SS, %ax
movw %ax, %ss movw %ax, %ss
movw $PM_DS, %ax
movw %ax, %ds movw %ax, %ds
movw %ax, %es movw %ax, %es
movw %ax, %fs movw %ax, %fs
movw %ax, %gs movw %ax, %gs
popl %eax
/* Call PM routine */
call *%ax
/* Set real-mode segment limits on %ds, %es, %fs and %gs */
movw %ss, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
/* Return CPU to real mode */
movl %cr0, %eax movl %cr0, %eax
andb $0!CR0_PE, %al andb $0!CR0_PE, %al
movl %eax, %cr0 movl %eax, %cr0
lret
2: /* lret will ljmp to here */
/* Restore registers and flags */ /* Restore GDT, registers and flags */
lret /* will ljmp to 99f */ data32 lgdt FLATTEN_VAR(flatten_saved_gdt)(%bp)
99: popw %ss popw %ss
popw %ds popw %ds
popw %es popw %es
popw %fs popw %fs
popw %gs popw %gs
data32 lgdt PM_CALL_VAR(pm_saved_gdt)(%bp) popw %cx
popw %si
popl %edi
popl %eax
popfl popfl
movw %bp, %sp movw %bp, %sp
popw %bp popw %bp
ret ret
.size pm_call, . - pm_call .size flatten_real_mode, . - flatten_real_mode
set_seg_base: set_seg_base:
rolw $4, %ax rolw $4, %ax
@ -396,7 +368,7 @@ set_seg_base:
#endif /* KEEP_IT_REAL */ #endif /* KEEP_IT_REAL */
/**************************************************************************** /****************************************************************************
* copy_bytes (real-mode or 16-bit protected-mode near call) * copy_bytes
* *
* Copy bytes * Copy bytes
* *
@ -411,6 +383,7 @@ set_seg_base:
* None * None
**************************************************************************** ****************************************************************************
*/ */
#if ! COMPRESS
.section ".prefix.lib", "awx", @progbits .section ".prefix.lib", "awx", @progbits
.code16 .code16
copy_bytes: copy_bytes:
@ -419,9 +392,10 @@ copy_bytes:
popl %ecx popl %ecx
ret ret
.size copy_bytes, . - copy_bytes .size copy_bytes, . - copy_bytes
#endif /* COMPRESS */
/**************************************************************************** /****************************************************************************
* install_block (real-mode near call) * install_block
* *
* Install block to specified address * Install block to specified address
* *
@ -439,39 +413,22 @@ copy_bytes:
.section ".prefix.lib", "awx", @progbits .section ".prefix.lib", "awx", @progbits
.code16 .code16
install_block: install_block:
#ifdef KEEP_IT_REAL
/* Preserve registers */ /* Preserve registers */
pushw %ds pushw %ds
pushw %es pushw %es
pushl %ecx pushl %ecx
pushl %edi pushl %edi
/* Convert %esi and %edi to segment registers */ /* Convert %esi and %edi to %ds:esi and %es:edi */
shrl $4, %esi shrl $4, %esi
movw %si, %ds movw %si, %ds
xorw %si, %si xorw %si, %si
shll $4, %esi
shrl $4, %edi shrl $4, %edi
movw %di, %es movw %di, %es
xorw %di, %di xorw %di, %di
shll $4, %edi
#else /* KEEP_IT_REAL */
/* Call self in protected mode */
pushw %ax
movw $1f, %ax
call pm_call
popw %ax
ret
1:
/* Preserve registers */
pushl %ecx
pushl %edi
#endif /* KEEP_IT_REAL */
#if COMPRESS #if COMPRESS
/* Decompress source to destination */ /* Decompress source to destination */
call decompress16 call decompress16
@ -492,33 +449,22 @@ install_block:
addl $0xf, %esi addl $0xf, %esi
andl $~0xf, %esi andl $~0xf, %esi
#ifdef KEEP_IT_REAL
/* Convert %ds:esi back to a physical address */ /* Convert %ds:esi back to a physical address */
movzwl %ds, %cx xorl %ecx, %ecx
movw %ds, %cx
shll $4, %ecx shll $4, %ecx
addl %ecx, %esi addl %ecx, %esi
/* Restore registers */ /* Restore registers and return */
popl %edi popl %edi
popl %ecx popl %ecx
popw %es popw %es
popw %ds popw %ds
#else /* KEEP_IT_REAL */
/* Restore registers */
popl %edi
popl %ecx
#endif
ret ret
.size install_block, . - install_block .size install_block, . - install_block
/**************************************************************************** /****************************************************************************
* alloc_basemem (real-mode near call) * alloc_basemem
* *
* Allocate space for .text16 and .data16 from top of base memory. * Allocate space for .text16 and .data16 from top of base memory.
* Memory is allocated using the BIOS free base memory counter at * Memory is allocated using the BIOS free base memory counter at
@ -568,7 +514,7 @@ alloc_basemem:
.size alloc_basemem, . - alloc_basemem .size alloc_basemem, . - alloc_basemem
/**************************************************************************** /****************************************************************************
* free_basemem (real-mode near call) * free_basemem
* *
* Free space allocated with alloc_basemem. * Free space allocated with alloc_basemem.
* *
@ -620,7 +566,7 @@ hooked_bios_interrupts:
.size hooked_bios_interrupts, . - hooked_bios_interrupts .size hooked_bios_interrupts, . - hooked_bios_interrupts
/**************************************************************************** /****************************************************************************
* install (real-mode near call) * install
* *
* Install all text and data segments. * Install all text and data segments.
* *
@ -655,7 +601,7 @@ install:
.size install, . - install .size install, . - install
/**************************************************************************** /****************************************************************************
* install_prealloc (real-mode near call) * install_prealloc
* *
* Install all text and data segments. * Install all text and data segments.
* *
@ -680,6 +626,11 @@ install_prealloc:
/* Sanity: clear the direction flag asap */ /* Sanity: clear the direction flag asap */
cld cld
#ifndef KEEP_IT_REAL
/* Flatten real mode */
call flatten_real_mode
#endif
/* Calculate physical address of payload (i.e. first source) */ /* Calculate physical address of payload (i.e. first source) */
testl %esi, %esi testl %esi, %esi
jnz 1f jnz 1f
@ -732,16 +683,15 @@ install_prealloc:
/* Copy code to new location */ /* Copy code to new location */
pushl %edi pushl %edi
pushw %ax xorw %ax, %ax
movw $copy_bytes, %ax movw %ax, %es
call pm_call es rep addr32 movsb
popw %ax
popl %edi popl %edi
/* Initialise librm at new location */ /* Initialise librm at new location */
lcall *init_librm_vector lcall *init_librm_vector
#endif #endif
/* Restore registers */ /* Restore registers */
popw %es popw %es
popw %ds popw %ds
@ -749,7 +699,9 @@ install_prealloc:
ret ret
.size install_prealloc, . - install_prealloc .size install_prealloc, . - install_prealloc
/* Vectors for far calls to .text16 functions */ /* Vectors for far calls to .text16 functions. Must be in
* .data16, since .prefix may not be writable.
*/
.section ".data16", "aw", @progbits .section ".data16", "aw", @progbits
#ifdef KEEP_IT_REAL #ifdef KEEP_IT_REAL
init_libkir_vector: init_libkir_vector:
@ -768,7 +720,7 @@ prot_call_vector:
#endif #endif
/**************************************************************************** /****************************************************************************
* uninstall (real-mode near call) * uninstall
* *
* Uninstall all text and data segments. * Uninstall all text and data segments.
* *