summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/arch/i386/prefix/pxeprefix.S365
1 files changed, 179 insertions, 186 deletions
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S
index 0e0b6c00..dea0b199 100644
--- a/src/arch/i386/prefix/pxeprefix.S
+++ b/src/arch/i386/prefix/pxeprefix.S
@@ -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
@@ -22,21 +15,35 @@
* 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"