summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown2009-04-30 05:42:21 +0200
committerMichael Brown2009-04-30 05:48:28 +0200
commit4188d517534d1350d48e68356cef99a5208787b4 (patch)
treeee108e8f3cf1439fc16e0a702b076d31ea34e480 /src/arch
parent[build] Add {PROVIDE,REQUIRE}_SYMBOL macros and tidy up compiler.h (diff)
downloadipxe-4188d517534d1350d48e68356cef99a5208787b4.tar.gz
ipxe-4188d517534d1350d48e68356cef99a5208787b4.tar.xz
ipxe-4188d517534d1350d48e68356cef99a5208787b4.zip
[pxeprefix] Work around bug in Etherboot 5.4 when loading undionly.kpxe
Etherboot 5.4 erroneously treats PXENV_UNLOAD_STACK as the "final shutdown" call, and unhooks INT15. When using gPXE's undionly.kpxe, this results in gPXE overwriting the portion of Etherboot located in high memory, because it is no longer hidden from the system memory map at the time that gPXE loads. Work around this by explicitly testing for Etherboot as the underlying PXE stack (as is already done in undinet.c) and skipping the call to PXENV_UNLOAD_STACK if necessary.
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/i386/prefix/pxeprefix.S60
1 files changed, 55 insertions, 5 deletions
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S
index 82b1da19..c6ae12c7 100644
--- a/src/arch/i386/prefix/pxeprefix.S
+++ b/src/arch/i386/prefix/pxeprefix.S
@@ -1,8 +1,11 @@
#define PXENV_UNDI_SHUTDOWN 0x0005
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
+#define PXENV_UNDI_GET_IFACE_INFO 0x0013
#define PXENV_STOP_UNDI 0x0015
#define PXENV_UNLOAD_STACK 0x0070
+#define PXE_HACK_EB54 0x0001
+
.text
.arch i386
.org 0
@@ -11,6 +14,8 @@
#include <undi.h>
#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
+#define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
+#define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
/*****************************************************************************
* Entry point: set operating context, print welcome message
@@ -307,8 +312,6 @@ pci_physical_device:
movw $10f, %si
call print_message
call print_pci_busdevfn
- movb $0x0a, %al
- call print_character
jmp 99f
.section ".prefix.data", "aw", @progbits
10: .asciz " UNDI device is PCI "
@@ -319,12 +322,47 @@ no_physical_device:
movw $10f, %si
call print_message
.section ".prefix.data", "aw", @progbits
-10: .asciz " Unable to determine UNDI physical device\n"
+10: .asciz " Unable to determine UNDI physical device"
.previous
99:
/*****************************************************************************
+ * Determine interface type
+ *****************************************************************************
+ */
+get_iface_type:
+ /* Issue PXENV_UNDI_GET_IFACE_INFO */
+ movw $PXENV_UNDI_GET_IFACE_INFO, %bx
+ call pxe_call
+ jnc 1f
+ call print_pxe_error
+ jmp 99f
+1: /* Print interface type */
+ movw $10f, %si
+ call print_message
+ leaw ( pxe_parameter_structure + 0x02 ), %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz ", type "
+ .previous
+ /* Check for "Etherboot" interface type */
+ cmpl $EB_MAGIC_1, ( pxe_parameter_structure + 0x02 )
+ jne 99f
+ cmpl $EB_MAGIC_2, ( pxe_parameter_structure + 0x06 )
+ jne 99f
+ movw $10f, %si
+ call print_message
+ .section ".prefix.data", "aw", @progbits
+10: .asciz " (workaround enabled)"
+ .previous
+ /* Flag Etherboot workarounds as required */
+ orw $PXE_HACK_EB54, pxe_hacks
+
+99: movb $0x0a, %al
+ call print_character
+
+/*****************************************************************************
* Leave NIC in a safe state
*****************************************************************************
*/
@@ -337,6 +375,14 @@ shutdown_nic:
call print_pxe_error
1:
unload_base_code:
+ /* Etherboot treats PXENV_UNLOAD_STACK as PXENV_STOP_UNDI, so
+ * we must not issue this call if the underlying stack is
+ * Etherboot and we were not intending to issue a PXENV_STOP_UNDI.
+ */
+#ifdef PXELOADER_KEEP_UNDI
+ testw $PXE_HACK_EB54, pxe_hacks
+ jnz 99f
+#endif /* PXELOADER_KEEP_UNDI */
/* Issue PXENV_UNLOAD_STACK */
movw $PXENV_UNLOAD_STACK, %bx
call pxe_call
@@ -549,7 +595,9 @@ pxe_call:
testw %ax, %ax
jz 1f
stc
-1: /* Restore registers and return */
+1: /* Clear direction flag, for the sake of sanity */
+ cld
+ /* Restore registers and return */
popw %es
popw %di
ret
@@ -593,7 +641,7 @@ print_pxe_error:
pxe_esp: .long 0
pxe_ss: .word 0
-pxe_parameter_structure: .fill 20
+pxe_parameter_structure: .fill 64
undi_code_segoff:
undi_code_size: .word 0
@@ -603,6 +651,8 @@ undi_data_segoff:
undi_data_size: .word 0
undi_data_segment: .word 0
+pxe_hacks: .word 0
+
/* The following fields are part of a struct undi_device */
undi_device: