diff options
Diffstat (limited to 'src/arch/i386/prefix/pxeprefix.S')
-rw-r--r-- | src/arch/i386/prefix/pxeprefix.S | 79 |
1 files changed, 62 insertions, 17 deletions
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S index 575f4784e..ee0f4d948 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 |