From 24226472b2fa07d014bef62e308095a69de8a106 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 11 Nov 2011 23:20:28 +0000 Subject: [PATCH] [prefix] Allow prefix to specify an arbitrary maximum address for relocation Signed-off-by: Michael Brown --- src/arch/i386/core/relocate.c | 25 ++++++++++++++++--------- src/arch/i386/prefix/exeprefix.S | 2 +- src/arch/i386/prefix/libprefix.S | 18 +++++------------- src/arch/i386/prefix/romprefix.S | 22 ++++++++-------------- src/arch/i386/prefix/undiloader.S | 4 +++- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/arch/i386/core/relocate.c b/src/arch/i386/core/relocate.c index 47450e75..b9b02944 100644 --- a/src/arch/i386/core/relocate.c +++ b/src/arch/i386/core/relocate.c @@ -42,7 +42,7 @@ extern char _etextdata[]; */ __asmcall void relocate ( struct i386_all_regs *ix86 ) { struct memory_map memmap; - unsigned long start, end, size, padded_size; + unsigned long start, end, size, padded_size, max; unsigned long new_start, new_end; unsigned i; @@ -57,6 +57,13 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) { "...need %lx bytes for %d-byte alignment\n", start, end, padded_size, max_align ); + /* Determine maximum usable address */ + max = MAX_ADDR; + if ( ix86->regs.ebp && ( ix86->regs.ebp < max ) ) { + max = ix86->regs.ebp; + DBG ( "Limiting relocation to [0,%lx)\n", max ); + } + /* Walk through the memory map and find the highest address * below 4GB that iPXE will fit into. */ @@ -67,18 +74,18 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) { DBG ( "Considering [%llx,%llx)\n", region->start, region->end); - /* Truncate block to MAX_ADDR. This will be less than - * 4GB, which means that we can get away with using - * just 32-bit arithmetic after this stage. + /* Truncate block to maximum address. This will be + * less than 4GB, which means that we can get away + * with using just 32-bit arithmetic after this stage. */ - if ( region->start > MAX_ADDR ) { - DBG ( "...starts after MAX_ADDR=%lx\n", MAX_ADDR ); + if ( region->start > max ) { + DBG ( "...starts after max=%lx\n", max ); continue; } r_start = region->start; - if ( region->end > MAX_ADDR ) { - DBG ( "...end truncated to MAX_ADDR=%lx\n", MAX_ADDR ); - r_end = MAX_ADDR; + if ( region->end > max ) { + DBG ( "...end truncated to max=%lx\n", max ); + r_end = max; } else { r_end = region->end; } diff --git a/src/arch/i386/prefix/exeprefix.S b/src/arch/i386/prefix/exeprefix.S index c7e57cee..5ba0239a 100644 --- a/src/arch/i386/prefix/exeprefix.S +++ b/src/arch/i386/prefix/exeprefix.S @@ -113,7 +113,7 @@ _exe_start: call alloc_basemem xorl %esi, %esi movl $EXE_DECOMPRESS_ADDRESS, %edi - clc + xorl %ebp, %ebp call install_prealloc /* Set up real-mode stack */ diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index ae3db32a..fcf69bd3 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -326,7 +326,6 @@ process_bytes: #ifndef KEEP_IT_REAL /* Preserve registers */ - pushfw pushl %eax pushl %ebp @@ -397,7 +396,6 @@ process_bytes: /* Restore registers and return */ popl %ebp popl %eax - popfw ret #else /* KEEP_IT_REAL */ @@ -614,17 +612,19 @@ install: /* Preserve registers */ pushl %esi pushl %edi + pushl %ebp /* Allocate space for .text16 and .data16 */ call alloc_basemem /* Image source = %cs:0000 */ xorl %esi, %esi /* Image destination = default */ xorl %edi, %edi - /* Allow relocation */ - clc + /* Allow arbitrary relocation */ + xorl %ebp, %ebp /* Install text and data segments */ call install_prealloc /* Restore registers and return */ + popl %ebp popl %edi popl %esi ret @@ -640,7 +640,7 @@ install: * %bx : .data16 segment address * %esi : Image source physical address (or zero for %cs:0000) * %edi : Decompression temporary area physical address (or zero for default) - * CF set : Avoid relocating to top of memory + * %ebp : Maximum end address for relocation (or zero for no maximum) * Corrupts: * none **************************************************************************** @@ -655,7 +655,6 @@ install_prealloc: pushw %ds pushw %es cld /* Sanity: clear the direction flag asap */ - pushfw /* Set up %ds for (read-only) access to .prefix */ pushw %cs @@ -791,11 +790,6 @@ payload_death_message: movw %ax, (init_librm_vector+2) lcall *init_librm_vector - /* Skip relocation if CF was set on entry */ - popfw - pushfw - jc skip_relocate - /* Call relocate() to determine target address for relocation. * relocate() will return with %esi, %edi and %ecx set up * ready for the copy to the new location. @@ -818,7 +812,6 @@ payload_death_message: /* Initialise librm at new location */ progress " init_librm\n" lcall *init_librm_vector -skip_relocate: #endif /* Close access to payload */ @@ -827,7 +820,6 @@ skip_relocate: lcall *close_payload_vector /* Restore registers */ - popfw popw %es popw %ds popal diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index c85e563d..0f924153 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -414,7 +414,7 @@ no_pmm: * picked up by the initial shell prompt, and we will drop * into a shell. */ - stc /* Inhibit relocation */ + movl $0xa0000, %ebp /* Inhibit relocation during POST */ pushw %cs call exec 2: @@ -614,7 +614,7 @@ decompress_to: * Called by the PnP BIOS when it wants to boot us. */ bev_entry: - clc /* Allow relocation */ + xorl %ebp, %ebp /* Allow relocation */ pushw %cs call exec lret @@ -649,7 +649,7 @@ int19_entry: /* Leave keypress in buffer and start iPXE. The keypress will * cause the usual initial Ctrl-B prompt to be skipped. */ - clc /* Allow relocation */ + xorl %ebp, %ebp /* Allow relocation */ pushw %cs call exec 1: /* Try to call original INT 19 vector */ @@ -681,9 +681,6 @@ exec: /* Set %ds = %cs */ pushw %cs popw %ds - /* Preserve state of CF */ - lahf - /* Print message as soon as possible */ movw $prodstr, %si xorw %di, %di @@ -693,8 +690,8 @@ exec: /* Set %ds = %cs */ /* Store magic word on BIOS stack and remember BIOS %ss:sp */ pushl $STACK_MAGIC - movw %ss, %dx - movw %sp, %bp + movw %ss, %cx + movw %sp, %dx /* Obtain a reasonably-sized temporary stack */ xorw %bx, %bx @@ -702,10 +699,7 @@ exec: /* Set %ds = %cs */ movw $0x7c00, %sp /* Install iPXE */ - sahf - pushfw call alloc_basemem - popfw movl image_source, %esi movl decompress_to, %edi call install_prealloc @@ -728,14 +722,14 @@ exec: /* Set %ds = %cs */ pushl $main pushw %cs call prot_call - popl %ecx /* discard */ + popl %eax /* discard */ /* Uninstall iPXE */ call uninstall /* Restore BIOS stack */ - movw %dx, %ss - movw %bp, %sp + movw %cx, %ss + movw %dx, %sp /* Check magic word on BIOS stack */ popl %eax diff --git a/src/arch/i386/prefix/undiloader.S b/src/arch/i386/prefix/undiloader.S index 951b5c1c..bb3d469b 100644 --- a/src/arch/i386/prefix/undiloader.S +++ b/src/arch/i386/prefix/undiloader.S @@ -14,6 +14,7 @@ undiloader: /* Save registers */ pushl %esi pushl %edi + pushl %ebp pushw %ds pushw %es pushw %bx @@ -30,7 +31,7 @@ undiloader: movw %es:14(%di), %ax movl image_source, %esi movl decompress_to, %edi - clc /* Allow relocation */ + xorl %ebp, %ebp /* Allow relocation */ call install_prealloc popw %di /* Call UNDI loader C code */ @@ -46,6 +47,7 @@ undiloader: popw %bx popw %es popw %ds + popl %ebp popl %edi popl %esi lret