summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/prefix/pxeprefix.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/i386/prefix/pxeprefix.S')
-rw-r--r--src/arch/i386/prefix/pxeprefix.S79
1 files changed, 62 insertions, 17 deletions
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