Updated to work with libprefix.
authorMichael Brown <mcb30@etherboot.org>
Thu, 25 May 2006 22:04:47 +0000 (22:04 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 25 May 2006 22:04:47 +0000 (22:04 +0000)
src/arch/i386/prefix/pxeprefix.S

index 0e0b6c0..dea0b19 100644 (file)
@@ -1,16 +1,9 @@
-/* Offsets of words containing ROM's CS and size (in 512 byte blocks)
- * from start of floppy boot block at 0x7c00
- * Offsets must match those in etherboot.h
- */
-#define FLOPPY_SEGMENT 0x7c0
-
 #define PXENV_UNDI_CLEANUP     0x02
 #define PXENV_UNDI_SHUTDOWN    0x05
 #define        PXENV_STOP_UNDI         0x15
 #define PXENV_UNLOAD_STACK     0x70
 #define PXENV_STOP_BASE                0x76
 
-#define PUSHA_SIZE             16
 #define PXE_STACK_MAGIC                0x57ac  /* 'STac' */
 
        .text
  * Entry point:        set cs, ds, bp, print welcome message
  *****************************************************************************
  */    
-_prefix:
-       jmp     $FLOPPY_SEGMENT, $code_start-_prefix
+       jmp     $0x7c0, $code_start
 10:    .asciz  "PXE->EB "
 code_start:
-       pusha                           /* Preserve all registers */
-       push    %ds
-       movw    %sp, %bp                /* %bp must be preserved, hence do
-                                        * this after the pusha */
-       push    $PXE_STACK_MAGIC        /* PXE stack magic marker */
-
-       push    %cs                     /* Set up data segment */
-       pop     %ds
-       mov     $0x40, %cx              /* Set up %fs for access to 40:13 */
-       mov     %cx, %fs
-       movw    $10b-_prefix, %si       /* Print welcome message */
+       /* Preserve registers for return to PXE stack */
+       pushfl
+       pushal
+       pushw   %gs
+       pushw   %fs
+       pushw   %es
+       pushw   %ds
+       pushw   %ss
+       pushw   %cs
+       pushw   $PXE_STACK_MAGIC        /* PXE stack magic marker */
+       /* Set up stack just below 0x7c00 */
+       pushw   %ss
+       popw    %es
+       movw    %sp, %di
+       xorw    %ax, %ax
+       movw    %ax, %ss
+       movw    $0x7c00, %sp
+       pushw   %es                     /* Save old PXE stack pointer */
+       pushw   %di
+       /* Set up our other segment registers */
+       pushw   %cs
+       popw    %ds
+       movw    $0x40, %ax              /* BIOS data segment access */
+       movw    %ax, %fs
+       /* Print welcome message */
+       movw    $10b, %si
        call    print_message
 
 /*****************************************************************************
@@ -44,12 +51,12 @@ code_start:
  *****************************************************************************
  */
 detect_pxe:
-       les     4+PUSHA_SIZE+2(%bp), %di /* !PXE structure */
+       les     %es:54(%di), %di /* !PXE structure */
        cmpl    $0x45585021, %es:(%di)  /* '!PXE' signature */
        je      detected_pxe
-       mov     $0x5650, %ax
+       movw    $0x5650, %ax
        int     $0x1a
-       cmp     $0x564e, %ax
+       cmpw    $0x564e, %ax
        jne     detected_nothing
        cmpl    $0x4e455850, %es:(%bx)  /* 'PXEN' signature */
        jne     detected_nothing
@@ -57,49 +64,45 @@ detect_pxe:
        je      detected_pxenv
 
 detected_nothing:
-       movw    $10f-_prefix, %si
+       movw    $10f, %si
        call    print_message
        jmp     finished_with_error
 10:    .asciz  "No PXE "
 
 detected_pxenv: /* es:bx points to PXENV+ structure */
-       push    %es
-       push    %bx
-       push    %es:0x24(%bx)           /* UNDI code segment */
-       push    %es:0x26(%bx)           /* UNDI code size */
-       push    %es:0x20(%bx)           /* UNDI data segment */
-       push    %es:0x22(%bx)           /* UNDI data size */
+       pushw   %es
+       pushw   %bx
+       pushw   %es:0x24(%bx)           /* UNDI code segment */
+       pushw   %es:0x26(%bx)           /* UNDI code size */
+       pushw   %es:0x20(%bx)           /* UNDI data segment */
+       pushw   %es:0x22(%bx)           /* UNDI data size */
        les     %es:0x0a(%bx), %di      /* Entry point to %es:%di */
-       movw    $10f-_prefix, %si
+       movw    $10f, %si
        jmp     pxe_setup_done
 10:    .asciz  "PXENV+ "
 
 detected_pxe:  /* es:di points to !PXE structure */
-       push    %es
-       push    %di
-       push    %es:0x30(%di)           /* UNDI code segment */
-       push    %es:0x36(%di)           /* UNDI code size */
-       push    %es:0x28(%di)           /* UNDI data segment */
-       push    %es:0x2e(%di)           /* UNDI data size */
+       pushw   %es
+       pushw   %di
+       pushw   %es:0x30(%di)           /* UNDI code segment */
+       pushw   %es:0x36(%di)           /* UNDI code size */
+       pushw   %es:0x28(%di)           /* UNDI data segment */
+       pushw   %es:0x2e(%di)           /* UNDI data size */
        les     %es:0x10(%di), %di      /* Entry point to %es:%di */
-       movw    $10f-_prefix, %si
+       movw    $10f, %si
        jmp     pxe_setup_done
 10:    .asciz  "!PXE "
 
 pxe_setup_done:
-       mov     %es, pxe_entry_segment - _prefix
-       mov     %di, pxe_entry_offset - _prefix
-       pop     %ax
-       mov     %ax, undi_data_size - _prefix
-       pop     %ax
-       mov     %ax, undi_data_segment - _prefix
-       pop     %ax
-       mov     %ax, undi_code_size - _prefix
-       pop     %ax
-       mov     %ax, undi_code_segment - _prefix
+       movw    %es, pxe_entry_segment
+       movw    %di, pxe_entry_offset
+       popw    undi_data_size
+       popw    undi_data_segment
+       popw    undi_code_size
+       popw    undi_code_segment
        call    print_message
-       pop     %di
-       pop     %es     /* Exit with %es:%di containing structure address */
+       popw    %di
+       popw    %es     /* Exit with %es:%di containing structure address */
 
 /*****************************************************************************
  * Print information about located structure
@@ -107,11 +110,11 @@ pxe_setup_done:
  */
 print_structure_information:
        call    print_segoff    /* %es:%di contains address of structure */
-       les     %ds:(pxe_entry_segoff - _prefix), %di
+       les     pxe_entry_segoff, %di
        call    print_segoff
-       les     %ds:(undi_code_segoff - _prefix), %di
+       les     undi_code_segoff, %di
        call    print_segoff
-       les     %ds:(undi_data_segoff - _prefix), %di
+       les     undi_data_segoff, %di
        call    print_segoff
 
 /*****************************************************************************
@@ -119,17 +122,17 @@ print_structure_information:
  *****************************************************************************
  */
 #ifdef PXELOADER_KEEP_ALL
-       xor     %ax, %ax                /* Force zero flag to show success */
+       xorw    %ax, %ax                /* Force zero flag to show success */
        jmp     do_not_free_base_mem    /* Skip the unloading */
 #endif /* PXELOADER_KEEP_ALL */
        
 unload_pxe:
-       mov     $PXENV_UNLOAD_STACK, %bx
+       movw    $PXENV_UNLOAD_STACK, %bx
        call    pxe_call
-       mov     $PXENV_STOP_UNDI, %bx
+       movw    $PXENV_STOP_UNDI, %bx
        call    pxe_call
        pushfw                          /* Ignore PXENV_UNDI_CLEANUP errors */
-       mov     $PXENV_UNDI_CLEANUP, %bx
+       movw    $PXENV_UNDI_CLEANUP, %bx
        call    pxe_call
        popfw
        /* On exit, zero flag is set iff all calls were successful */
@@ -141,45 +144,45 @@ unload_pxe:
 free_base_mem:
        jnz     do_not_free_base_mem    /* Using zero flag from unload_pxe */
 
-       mov     undi_code_segment - _prefix, %bx
-       mov     undi_data_segment - _prefix, %cx
-       mov     undi_code_size - _prefix, %ax
-       cmp     %bx, %cx
+       movw    undi_code_segment, %bx
+       movw    undi_data_segment, %cx
+       movw    undi_code_size, %ax
+       cmpw    %bx, %cx
        jb      1f
-       mov     %cx, %bx
-       mov     undi_data_size - _prefix, %ax
-1:     add     $0x0f, %ax              /* Round up to next segment */
-       shr     $4, %ax
-       add     %bx, %ax                /* Highest segment address into %ax */
-       add     $(1024 / 16 - 1), %ax   /* Round up to next kb */
-       shr     $6, %ax                 /* New free basemem size in %ax */
-       mov     %fs:(0x13), %bx         /* Old free base memory in %bx */
-       mov     %ax, %fs:(0x13)         /* Store new free base memory size */
+       movw    %cx, %bx
+       movw    undi_data_size, %ax
+1:     addw    $0x0f, %ax              /* Round up to next segment */
+       shrw    $4, %ax
+       addw    %bx, %ax                /* Highest segment address into %ax */
+       addw    $(1024 / 16 - 1), %ax   /* Round up to next kb */
+       shrw    $6, %ax                 /* New free basemem size in %ax */
+       movw    %fs:(0x13), %bx         /* Old free base memory in %bx */
+       movw    %ax, %fs:(0x13)         /* Store new free base memory size */
 
        /* Note that zero_mem_loop will also zero out our stack, so make
         * sure the stack is empty at this point.
         */
-       mov     %ax, %dx
-       sub     %bx, %dx                /* numberof kb to zero in %dx */
-       shl     $6, %bx                 /* Segment address into %bx */
+       movw    %ax, %dx
+       subw    %bx, %dx                /* numberof kb to zero in %dx */
+       shlw    $6, %bx                 /* Segment address into %bx */
 zero_mem_loop:
-       mov     %bx, %es                /* kB boundary into %es:00 */
-       xor     %ax, %ax
-       xor     %di, %di
-       mov     $0x400, %cx
+       movw    %bx, %es                /* kB boundary into %es:00 */
+       xorw    %ax, %ax
+       xorw    %di, %di
+       movw    $0x400, %cx
        rep     stosb                   /* fill kB with zeroes */
-       add     $(1024 / 16), %bx
-       dec     %dx
+       addw    $(1024 / 16), %bx
+       decw    %dx
        jnz     zero_mem_loop
        /* Will exit here with zero flag set, so no need to set it explicitly
         * in order to indicate success.
         */
        
 do_not_free_base_mem:
-       pushf                           /* Save success (zero) flag status */
-       mov     %fs:(0x13), %ax         /* Free base memory in %ax */
+       pushfw                          /* Save success (zero) flag status */
+       movw    %fs:(0x13), %ax         /* Free base memory in %ax */
        call    print_hex_word          /* Print free base memory */
-       popf                            /* Restore success (zero) flag */
+       popfw                           /* Restore success (zero) flag */
 
 /*****************************************************************************
  * Exit point
@@ -188,92 +191,16 @@ do_not_free_base_mem:
  *****************************************************************************
  */    
 finished:
-       movw    $10f-_prefix, %si
+       movw    $10f, %si
        jz      1f
 finished_with_error:
-       movw    $20f-_prefix, %si
+       movw    $20f, %si
 1:
        call    print_message
-       jmp     99f
+       jmp     run_etherboot
 10:    .asciz " ok\n"
 20:    .asciz " err\n"
 
-       
-       /* We place a stack here.  It doesn't get used until after all
-        * the above code is finished, so we can happily write all
-        * over it.  Putting the stack here ensures that it doesn't
-        * accidentally go over the 512 byte threshold, which would
-        * cause problems when returning via start32's prefix
-        * relocation mechanism.
-        */
-_estack:       
-99:
-
-/*****************************************************************************
- * Run Etherboot main code
- *****************************************************************************
- */    
-run_etherboot:
-       /* Very temporarily switch stacks to one internal to the
-        * prefix.  Do this because the stack provided by the PXE ROM
-        * could be absolutely anywhere, including in an area of
-        * memory that the call to prelocate will vapourise...
-        */
-       pushw   %ss                     /* PXE stack pointer to ES:DI */
-       popw    %es
-       movw    %sp, %di
-       pushw   %ds                     /* Set up stack in "safe" area */
-       popw    %ss
-       movw    $_estack-_prefix, %sp
-       pushw   %es                     /* Record PXE stack pointer */
-       pushw   %di
-       /* Relocate payload and stack to claimed base memory */
-       pushw   $4                      /* Preserve old PXE stack pointer */
-       call    prelocate
-       popw    %ax                     /* Remove parameter */
-       pushl   $4                      /* Preserve old PXE stack pointer */
-       pushw   $0                      /* Indicate prefix exit mechanism */
-       jmp     _start                  /* Run Etherboot */
-
-       .section ".text16", "ax", @progbits
-prefix_exit:
-       pushw   %cs                     /* Set %ds, %bp for access to text */
-       popw    %ds
-       call    1f
-1:     popw    %bp
-       popw    %di                     /* Old PXE stack to %es:di */
-       popw    %es
-       cmpw    $PXE_STACK_MAGIC, %es:0(%di)  /* See if PXE stack intact */
-       jne     exit_via_int18
-exit_via_pxe:                          /* Stack OK, return to PXE */
-       push    %es                     /* Restore PXE stack pointer */
-       pop     %ss
-       mov     %di, %sp
-       pop     %ax                     /* Discard PXE_STACK_MAGIC marker */
-       leaw    (10f-1b)(%bp), %si
-       call    print_exit_message
-       pop     %ds                     /* Restore PXE's DS */
-       popa                            /* Restore PXE's other registers */
-       movw    $0, %ax                 /* Return PXENV_STATUS_SUCCESS */
-       lret                            /* Return control to PXE ROM */
-10:    .asciz  "EB->PXE\r\n"
-exit_via_int18:                                /* Stack damaged, do int 18 */
-       leaw    (10f-1b)(%bp), %si
-       call    print_exit_message
-       int     $0x18
-10:    .asciz  "EB->BIOS\r\n"
-print_exit_message:    
-       movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
-       movb    $0x0e, %ah              /* write char, tty mode */
-1:     lodsb
-       testb   %al, %al
-       je      2f
-       int     $0x10
-       jmp     1b
-2:     ret
-prefix_exit_end:
-       .previous
-
 /*****************************************************************************
  * Subroutine: print character in %al (with LF -> LF,CR translation)
  *****************************************************************************
@@ -305,17 +232,17 @@ print_message:
  *****************************************************************************
  */
 print_hex_word:
-       mov     $4, %cx
+       movw    $4, %cx
 1:
-       push    %ax
-       shr     $12, %ax
+       pushw   %ax
+       shrw    $12, %ax
        /* Courtesy of Norbert Juffa <norbert.juffa@amd.com> */
-       cmp     $10, %al        
-       sbb     $0x69, %al
+       cmpb    $10, %al        
+       sbbb    $0x69, %al
        das
        call    print_character
-       pop     %ax
-       shl     $4, %ax
+       popw    %ax
+       shlw    $4, %ax
        loop    1b
        ret
        
@@ -324,15 +251,15 @@ print_hex_word:
  *****************************************************************************
  */
 print_segoff:
-       push    %di
-       push    %es
-       pop     %ax
+       pushw   %di
+       pushw   %es
+       popw    %ax
        call    print_hex_word
        movb    $0x3a,%al                       /* ':' */
        call    print_character
-       pop     %ax
+       popw    %ax
        call    print_hex_word
-       mov     $0x20, %al                      /* ' ' */
+       movb    $0x20, %al                      /* ' ' */
        call    print_character
        ret
        
@@ -346,24 +273,24 @@ print_segoff:
  */
 pxe_call:
        /* Set up registers for PXENV+ API.  %bx already set up */
-       push    %ds
-       pop     %es
-       mov     $pxe_parameter_structure - _prefix, %di
+       pushw   %ds
+       popw    %es
+       movw    $pxe_parameter_structure, %di
        /* Set up stack for !PXE API */
        pushw   %cs
        pushw   %di
        pushw   %bx
        /* Make the API call */
-       lcall   *(pxe_entry_segoff - _prefix)
+       lcall   *pxe_entry_segoff
        /* Reset the stack */
-       add     $6, %sp
-       mov     pxe_parameter_structure - _prefix, %ax
-       push    %ax
+       addw    $6, %sp
+       movw    pxe_parameter_structure, %ax
+       pushw   %ax
        call    print_hex_word
-       mov     $0x20, %ax              /* ' ' */
+       movw    $0x20, %ax              /* ' ' */
        call    print_character
-       pop     %bx
-       or      %bx, pxe_overall_status - _prefix
+       popw    %bx
+       orw     %bx, pxe_overall_status
        ret
 
 /*****************************************************************************
@@ -389,7 +316,73 @@ pxe_parameter_structure:
        .word   0
        .word   0,0,0,0,0
 
-end_of_pxeloader:
+/*****************************************************************************
+ * Run Etherboot main code
+ *****************************************************************************
+ */    
+run_etherboot:
+       /* Install Etherboot */
+       call    install
+
+       /* Jump to .text16 segment with %ds pointing to .data16*/
+       movw    %bx, %ds
+       pushw   %ax
+       pushw   $1f
+       lret
+       .section ".text16", "ax", @progbits
+1:
+       /* Original PXE stack pointer to es:di.  We must hold it in
+        * registers, because our current stack may be vapourised by
+        * the time main() returns.  (main() will still be able to
+        * return, because prot_call() transfers the return address to
+        * the internal stack and back again).
+        */
+       popw    %di
+       popw    %es
+
+       /* Run main program */
+       pushl   $main
+       pushw   %cs
+       call    prot_call
+       popl    %eax /* discard */
+
+       /* If original PXE stack is intact, return via PXE, else via INT 18 */
+       cmpw    $PXE_STACK_MAGIC, %es:0(%di)
+       jne     exit_via_int18
+exit_via_pxe:                          /* Stack OK, return to PXE */
+       movw    $exit_via_pxe_message, %si
+       call    print_exit_message
+       pushw   %es                     /* Restore original PXE stack */
+       popw    %ss
+       movw    %di, %sp
+       popw    %ax /* discard PXE_STACK_MAGIC */
+       popw    %ax /* discard %cs */
+       popw    %ax /* discard %ss */
+       popw    %ds
+       popw    %es
+       popw    %fs
+       popw    %gs
+       popal
+       popfl
+       xorw    %ax, %ax                /* Return PXENV_STATUS_SUCCESS */
+       lret
+exit_via_int18:                                /* Stack damaged, do int 18 */
+       movw    $exit_via_int18_message, %si
+       call    print_exit_message
+       int     $0x18
+
+print_exit_message:    
+       movw    $0x0007, %bx            /* page 0, attribute 7 (normal) */
+       movb    $0x0e, %ah              /* write char, tty mode */
+1:     lodsb
+       testb   %al, %al
+       je      2f
+       int     $0x10
+       jmp     1b
+2:     ret
 
-       .balign 16, 0
-payload:
+       .section ".data16", "aw", @progbits
+exit_via_pxe_message:
+       .asciz  "EB->PXE\r\n"
+exit_via_int18_message:
+       .asciz  "EB->BIOS\r\n"