summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/prefix
diff options
context:
space:
mode:
authorMichael Brown2008-10-27 02:06:00 +0100
committerMichael Brown2009-02-18 19:12:32 +0100
commitb5577553e59391653f47b9edb12775c080665db0 (patch)
treed824146681cbb12132831358f494b9803bad1d48 /src/arch/i386/prefix
parent[i386] Kill off obsolete boot1a.s file (diff)
downloadipxe-b5577553e59391653f47b9edb12775c080665db0.tar.gz
ipxe-b5577553e59391653f47b9edb12775c080665db0.tar.xz
ipxe-b5577553e59391653f47b9edb12775c080665db0.zip
[pxeprefix] Add .kkpxe image type and ability to return via PXE stack
Certain combinations of PXE stack and BIOS result in a broken INT 18 call, which will leave the system displaying a "PRESS ANY KEY TO REBOOT" message instead of proceeding to the next boot device. On these systems, returning via the PXE stack is the only way to continue to the next boot device. Returning via the PXE stack works only if we haven't already blown away the PXE base code in pxeprefix.S. In most circumstances, we do want to blow away the PXE base code. Base memory is a limited resource, and it is desirable to reclaim as much as possible. When we perform an iSCSI boot, we need to place the iBFT above the 512kB mark, because otherwise it may not be detected by the loaded OS; this may not be possible if the PXE base code is still occupying that memory. Introduce a new prefix type .kkpxe which will preserve both the PXE base code and the UNDI driver (as compared to .kpxe, which preserves the UNDI driver but uninstalls the PXE base code). This prefix type can be used on systems that are known to experience the specific problem of INT 18 being broken, or in builds (such as gpxelinux.0) for which it is particularly important to know that returning to the BIOS will work. Written by H. Peter Anvin <hpa@zytor.com> and Stefan Hajnoczi <stefanha@gmail.com>, minor structural alterations by Michael Brown <mcb30@etherboot.org>.
Diffstat (limited to 'src/arch/i386/prefix')
-rw-r--r--src/arch/i386/prefix/kkpxeprefix.S8
-rw-r--r--src/arch/i386/prefix/pxeprefix.S79
2 files changed, 70 insertions, 17 deletions
diff --git a/src/arch/i386/prefix/kkpxeprefix.S b/src/arch/i386/prefix/kkpxeprefix.S
new file mode 100644
index 00000000..e0bea0cd
--- /dev/null
+++ b/src/arch/i386/prefix/kkpxeprefix.S
@@ -0,0 +1,8 @@
+/*****************************************************************************
+ * PXE prefix that keeps the whole PXE stack present
+ *****************************************************************************
+ */
+
+#define PXELOADER_KEEP_UNDI
+#define PXELOADER_KEEP_PXE
+#include "pxeprefix.S"
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S
index 575f4784..ee0f4d94 100644
--- a/src/arch/i386/prefix/pxeprefix.S
+++ b/src/arch/i386/prefix/pxeprefix.S
@@ -10,27 +10,45 @@
#include <undi.h>
+#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+
/*****************************************************************************
* Entry point: set operating context, print welcome message
*****************************************************************************
*/
.section ".prefix", "ax", @progbits
- /* Set up our non-stack segment registers */
jmp $0x7c0, $1f
-1: movw %cs, %ax
+1:
+ /* Preserve registers for possible return to PXE */
+ pushfl
+ pushal
+ pushw %gs
+ pushw %fs
+ pushw %es
+ pushw %ds
+
+ /* Store magic word on PXE stack and remember PXE %ss:esp */
+ pushl $STACK_MAGIC
+ movw %ss, %cs:pxe_ss
+ movl %esp, %cs:pxe_esp
+ movw %sp, %bp
+ movl (10*4+4*2+4)(%bp),%ebp /* !PXE address */
+
+ /* Set up %ds */
+ movw %cs, %ax
movw %ax, %ds
- movw $0x40, %ax /* BIOS data segment access */
- movw %ax, %fs
/* Record PXENV+ and !PXE nominal addresses */
- movw %es, %ax /* PXENV+ address */
- movw %ax, pxenv_segment
+ movw %es, pxenv_segment /* PXENV+ address */
movw %bx, pxenv_offset
- popl %eax /* Discard return address */
- popl ppxe_segoff /* !PXE address */
+ movl %ebp, ppxe_segoff /* !PXE address */
+ /* Set up %es and %fs */
+ movw %ax, %es
+ movw $0x40, %ax /* BIOS data segment access */
+ movw %ax, %fs
/* Set up stack just below 0x7c00 */
xorw %ax, %ax
movw %ax, %ss
- movw $0x7c00, %sp
+ movl $0x7c00, %esp
/* Clear direction flag, for the sake of sanity */
cld
/* Print welcome message */
@@ -249,6 +267,7 @@ no_physical_device:
* Leave NIC in a safe state
*****************************************************************************
*/
+#ifndef PXELOADER_KEEP_PXE
shutdown_nic:
/* Issue PXENV_UNDI_SHUTDOWN */
movw $PXENV_UNDI_SHUTDOWN, %bx
@@ -256,11 +275,6 @@ shutdown_nic:
jnc 1f
call print_pxe_error
1:
-
-/*****************************************************************************
- * Unload PXE base code
- *****************************************************************************
- */
unload_base_code:
/* Issue PXENV_UNLOAD_STACK */
movw $PXENV_UNLOAD_STACK, %bx
@@ -273,6 +287,8 @@ unload_base_code:
movw %fs:(0x13), %bx
call free_basemem
99:
+ andw $~( UNDI_FL_INITIALIZED | UNDI_FL_KEEP_ALL ), flags
+#endif /* PXELOADER_KEEP_PXE */
/*****************************************************************************
* Unload UNDI driver
@@ -511,6 +527,10 @@ print_pxe_error:
* PXE data structures
*****************************************************************************
*/
+ .section ".prefix.data"
+
+pxe_ss: .word 0
+pxe_esp: .long 0
pxe_parameter_structure: .fill 20
@@ -547,14 +567,16 @@ isapnp_read_port: .word UNDI_NO_ISAPNP_READ_PORT
pci_vendor: .word 0
pci_device: .word 0
-flags: .word UNDI_FL_STARTED
+flags:
+ .word ( UNDI_FL_INITIALIZED | UNDI_FL_STARTED | UNDI_FL_KEEP_ALL )
.equ undi_device_size, ( . - undi_device )
/*****************************************************************************
* Run gPXE main code
*****************************************************************************
- */
+ */
+ .section ".prefix"
run_gpxe:
/* Install gPXE */
call install
@@ -572,6 +594,10 @@ run_gpxe:
rep movsb
#endif
+ /* Retrieve PXE %ss:esp */
+ movw pxe_ss, %di
+ movl pxe_esp, %ebp
+
/* Jump to .text16 segment with %ds pointing to .data16 */
movw %bx, %ds
pushw %ax
@@ -588,6 +614,25 @@ run_gpxe:
/* Uninstall gPXE */
call uninstall
- /* Boot next device */
+ /* Restore PXE stack */
+ movw %di, %ss
+ movl %ebp, %esp
+
+ /* Check PXE stack magic */
+ popl %eax
+ cmpl $STACK_MAGIC, %eax
+ jne 1f
+
+ /* PXE stack OK: return to caller */
+ popw %ds
+ popw %es
+ popw %fs
+ popw %gs
+ popal
+ popfl
+ xorw %ax, %ax /* Return success */
+ lret
+
+1: /* PXE stack corrupt or removed: use INT 18 */
int $0x18
.previous