aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@etherboot.org>2006-05-02 20:51:07 +0000
committerMichael Brown <mcb30@etherboot.org>2006-05-02 20:51:07 +0000
commit10c28a51bdc801374eccec52d1e4d6677100f86d (patch)
tree52c80bddaa91c71b94890f6cfd1344505bb297a9
parent9e1dd6402dd2aab83e324db98971cd4af2279b58 (diff)
downloadipxe-10c28a51bdc801374eccec52d1e4d6677100f86d.zip
ipxe-10c28a51bdc801374eccec52d1e4d6677100f86d.tar.gz
ipxe-10c28a51bdc801374eccec52d1e4d6677100f86d.tar.bz2
Create two easy-to-use entry points in libprefix: install and
install_prealloc. I *think* these will suffice for all the 16-bit prefixes.
-rw-r--r--src/arch/i386/prefix/dskprefix.S9
-rw-r--r--src/arch/i386/prefix/libprefix.S109
-rw-r--r--src/arch/i386/scripts/i386.lds37
-rw-r--r--src/arch/i386/transitions/librm.S2
4 files changed, 122 insertions, 35 deletions
diff --git a/src/arch/i386/prefix/dskprefix.S b/src/arch/i386/prefix/dskprefix.S
index 05bf45b..a2f6219 100644
--- a/src/arch/i386/prefix/dskprefix.S
+++ b/src/arch/i386/prefix/dskprefix.S
@@ -348,13 +348,7 @@ msg1end:
.word 0xAA55
start_runtime:
- /* Install .text16 and .data16 to top of base memory */
- call alloc_basemem
- call install_basemem
-
- /* Install .text and .data to 2MB mark */
- movl $(2<<20), %edi
- call install_highmem
+ call install
/* Jump to .text16 segment */
pushw %ax
@@ -362,7 +356,6 @@ start_runtime:
lret
.section ".text16", "awx", @progbits
1:
- call init_gdt
pushl $initialise
data32 call prot_call
popl %eax /* discard */
diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S
index 0f7d8a1..e00388d 100644
--- a/src/arch/i386/prefix/libprefix.S
+++ b/src/arch/i386/prefix/libprefix.S
@@ -30,11 +30,12 @@
* Parameters:
* %esi : byte offset within loaded image (must be a multiple of 16)
* %es:edi : destination address
- * %ecx : length to install
+ * %ecx : length of (decompressed) data
+ * %edx : total length of block (including any uninitialised data portion)
* Returns:
* none
* Corrupts:
- * %esi, %edi, %ecx
+ * %esi, %edi, %ecx, %edx
****************************************************************************
*/
.section ".prefix.lib"
@@ -42,7 +43,7 @@
install_block:
/* Preserve registers */
pushw %ds
- pushw %ax
+ pushw %eax
/* Starting segment => %ds */
movw %cs, %ax
@@ -51,12 +52,22 @@ install_block:
movw %ax, %ds
xorl %esi, %esi
+ /* Calculate start and length of uninitialised data portion */
+ leal (%edi,%ecx), %eax
+ subl %ecx, %edx
+
/* Do the copy */
cld
- addr32 rep movsb /* or "call decompress16" */
+ rep addr32 movsb /* or "call decompress16" */
+
+ /* Zero remaining space */
+ movl %eax, %edi
+ movl %edx, %ecx
+ xorb %al, %al
+ rep addr32 stosb
/* Restore registers */
- popw %ax
+ popw %eax
popw %ds
ret
.size install_block, . - install_block
@@ -79,7 +90,6 @@ install_block:
*/
.section ".prefix.lib"
.code16
- .globl alloc_basemem
alloc_basemem:
/* FBMS => %ax as segment address */
movw $0x40, %ax
@@ -121,19 +131,20 @@ alloc_basemem:
*/
.section ".prefix.lib"
.code16
- .globl install_basemem
install_basemem:
/* Preserve registers */
pushw %es
pushl %esi
pushl %edi
pushl %ecx
+ pushl %edx
/* Install .text16 */
movw %ax, %es
xorl %edi, %edi
movl $_text16_load_offset, %esi
movl $_text16_size, %ecx
+ movl %ecx, %edx
call install_block
/* Install .data16 */
@@ -141,9 +152,11 @@ install_basemem:
xorl %edi, %edi
movl $_data16_load_offset, %esi
movl $_data16_progbits_size, %ecx
+ movl $_data16_size, %edx
call install_block
/* Restore registers */
+ popl %edx
popl %ecx
popl %edi
popl %esi
@@ -160,6 +173,9 @@ install_basemem:
* simpler.
****************************************************************************
*/
+
+#ifndef KEEP_IT_REAL
+
.section ".prefix.lib"
.align 16
gdt:
@@ -180,6 +196,8 @@ flat_ds: /* Flat real mode data segment */
gdt_end:
.equ gdt_length, gdt_end - gdt
.size gdt, . - gdt
+
+#endif /* KEEP_IT_REAL */
/****************************************************************************
* set_segment_limits (real-mode near call)
@@ -190,6 +208,9 @@ gdt_end:
* %cx : Segment limit ($REAL_DS or $FLAT_DS)
****************************************************************************
*/
+
+#ifndef KEEP_IT_REAL
+
.section ".prefix.lib"
.code16
set_segment_limits:
@@ -222,6 +243,8 @@ set_segment_limits:
ret
.size set_segment_limits, . - set_segment_limits
+#endif /* KEEP_IT_REAL */
+
/****************************************************************************
* install_highmem (real-mode near call)
*
@@ -235,15 +258,18 @@ set_segment_limits:
* none
****************************************************************************
*/
+
+#ifndef KEEP_IT_REAL
+
.section ".prefix.lib"
.code16
- .globl install_highmem
install_highmem:
/* Preserve registers and interrupt status */
pushfl
pushl %esi
pushl %edi
pushl %ecx
+ pushl %edx
/* Disable interrupts and flatten real mode */
cli
@@ -253,8 +279,9 @@ install_highmem:
/* Install .text and .data to specified address */
xorw %cx, %cx
movw %cx, %es
- movl $_text_load_offset, %esi
- movl $_text_progbits_size, %ecx
+ movl $_textdata_load_offset, %esi
+ movl $_textdata_progbits_size, %ecx
+ movl $_textdata_size, %edx
call install_block
/* Unflatten real mode */
@@ -262,9 +289,71 @@ install_highmem:
call set_segment_limits
/* Restore registers and interrupt status */
+ popl %edx
popl %ecx
popl %edi
popl %esi
popfl
ret
.size install_highmem, . - install_highmem
+
+#endif /* KEEP_IT_REAL */
+
+/****************************************************************************
+ * install (real-mode near call)
+ * install_prealloc (real-mode near call)
+ *
+ * Install all text and data segments.
+ *
+ * Parameters:
+ * %ax : .text16 segment address (install_prealloc only)
+ * %bx : .data16 segment address (install_prealloc only)
+ * Returns:
+ * %ax : .text16 segment address
+ * %bx : .data16 segment address
+ * %edi : .text physical address (if applicable)
+ * Corrupts:
+ * none
+ ****************************************************************************
+ */
+ .section ".prefix.lib"
+ .code16
+ .globl install
+install:
+ /* Allocate space for .text16 and .data16 */
+ call alloc_basemem
+ .size install, . - install
+ .globl install_prealloc
+install_prealloc:
+ /* Install .text16 and .data16 */
+ call install_basemem
+
+#ifndef KEEP_IT_REAL
+ /* Install .text and .data to 2MB mark. Use 2MB to avoid
+ * problems with A20.
+ */
+ movl $(2<<20), %edi
+ call install_highmem
+
+ /* Continue executing in .text16 segment */
+ 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_gdt
+ pushl $relocate
+ data32 call prot_call
+ addw $4, %sp
+ call init_gdt
+
+ /* Return to executing in .prefix section */
+ lret
+ .section ".prefix.lib"
+2:
+#endif
+ ret
+ .size install_prealloc, . - install_prealloc
diff --git a/src/arch/i386/scripts/i386.lds b/src/arch/i386/scripts/i386.lds
index 71a7f74..d43a68f 100644
--- a/src/arch/i386/scripts/i386.lds
+++ b/src/arch/i386/scripts/i386.lds
@@ -20,7 +20,7 @@ SECTIONS {
* will default to:
*
* _prefix_link_addr = 0
- * _text_link_addr = 0
+ * _textdata_link_addr = 0
* _load_addr = 0
* _max_align = 16
*
@@ -108,11 +108,14 @@ SECTIONS {
* The 32-bit sections
*/
- _text_link_addr = DEFINED ( _text_link_addr ) ? _text_link_addr : 0;
- . = _text_link_addr;
+ _textdata_link_addr = ( DEFINED ( _textdata_link_addr ) ?
+ _textdata_link_addr : 0 );
+ . = _textdata_link_addr;
+ _textdata = .;
+
_text = .;
- .text : AT ( _text_load_offset + __text ) {
+ .text : AT ( _textdata_load_offset + __text ) {
__text = .;
*(.text)
*(.text.*)
@@ -122,19 +125,19 @@ SECTIONS {
_data = .;
- .rodata : AT ( _text_load_offset + __rodata ) {
+ .rodata : AT ( _textdata_load_offset + __rodata ) {
__rodata = .;
*(.rodata)
*(.rodata.*)
}
- .data : AT ( _text_load_offset + __data ) {
+ .data : AT ( _textdata_load_offset + __data ) {
__data = .;
*(.data)
*(.data.*)
*(SORT(.tbl.*)) /* Various tables. See include/tables.h */
- _etext_progbits = .;
+ _etextdata_progbits = .;
}
- .bss : AT ( _text_load_offset + __bss ) {
+ .bss : AT ( _textdata_load_offset + __bss ) {
__bss = .;
_bss = .;
*(.bss)
@@ -142,7 +145,7 @@ SECTIONS {
*(COMMON)
_ebss = .;
}
- .stack : AT ( _text_load_offset + __stack ) {
+ .stack : AT ( _textdata_load_offset + __stack ) {
__stack = .;
*(.stack)
*(.stack.*)
@@ -150,6 +153,8 @@ SECTIONS {
_edata = .;
+ _etextdata = .;
+
_end = .;
/*
@@ -194,12 +199,12 @@ SECTIONS {
_data16_progbits_size = _edata16_progbits - _data16;
. = _data16_load_addr + _data16_progbits_size;
- . -= _text_link_addr;
- _text_load_offset = ALIGN ( _max_align );
- _text_load_addr = _text_link_addr + _text_load_offset;
- _text_size = _etext - _text;
- _text_progbits_size = _etext_progbits - _text;
- . = _text_load_addr + _text_progbits_size;
+ . -= _textdata_link_addr;
+ _textdata_load_offset = ALIGN ( _max_align );
+ _textdata_load_addr = _textdata_link_addr + _textdata_load_offset;
+ _textdata_size = _etextdata - _textdata;
+ _textdata_progbits_size = _etextdata_progbits - _textdata;
+ . = _textdata_load_addr + _textdata_progbits_size;
. = ALIGN ( _max_align );
@@ -223,7 +228,7 @@ SECTIONS {
_assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
"_data16 is badly aligned" );
- . = _text_load_addr - _text_link_addr;
+ . = _textdata_load_addr - _textdata_link_addr;
_assert = ASSERT ( ( . == ALIGN ( _max_align ) ),
"_text is badly aligned" );
diff --git a/src/arch/i386/transitions/librm.S b/src/arch/i386/transitions/librm.S
index 2fbffb9..ef94ed3 100644
--- a/src/arch/i386/transitions/librm.S
+++ b/src/arch/i386/transitions/librm.S
@@ -357,7 +357,7 @@ prot_call:
popw %gs
popal
popfl
- ret
+ data32 ret
/****************************************************************************
* real_call (protected-mode near call, 32-bit virtual return address)