[pxeprefix] Add .kkpxe image type and ability to return via PXE stack
[people/lynusvaz/gpxe.git] / src / arch / i386 / prefix / pxeprefix.S
index 575f478..ee0f4d9 100644 (file)
 
 #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