aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-09-04 16:16:56 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-09-04 16:16:56 -0700
commit36b86591d37cfe120f63ae27218264506750da51 (patch)
tree6e1d6a485200c8e469c69a5930d1257837f78e78
parentc15b756c7e3dbc3dedb937b46ee582a23955e874 (diff)
parentebef1cd107b7034056309bf49f92a2b9e92b9fe0 (diff)
downloadlwip-36b86591d37cfe120f63ae27218264506750da51.tar.gz
lwip-36b86591d37cfe120f63ae27218264506750da51.tar.xz
lwip-36b86591d37cfe120f63ae27218264506750da51.zip
Merge branch 'fsc' into elflink
-rw-r--r--core/localboot.inc3
-rw-r--r--core/pxelinux.asm77
-rw-r--r--core/runkernel.inc2
3 files changed, 82 insertions, 0 deletions
diff --git a/core/localboot.inc b/core/localboot.inc
index 3fee7d62..78483463 100644
--- a/core/localboot.inc
+++ b/core/localboot.inc
@@ -31,6 +31,9 @@ local_boot:
mov gs,dx
mov si,localboot_msg
call writestr
+ push ax
+ call cleanup_hardware
+ pop ax
cmp ax,-1
je .int18
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 995de327..93ef8b4a 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -166,6 +166,82 @@ _start1:
call writestr_early
;
+; Look to see if we are on an EFI CSM system. Some EFI
+; CSM systems put the BEV stack in low memory, which means
+; a return to the PXE stack will crash the system. However,
+; INT 18h works reliably, so in that case hack the stack and
+; point the "return address" to an INT 18h instruction.
+;
+; Hack the stack instead of the much simpler "just invoke INT 18h
+; if we want to reset", so that chainloading other NBPs will work.
+;
+efi_csm_workaround:
+ push es
+ les bp,[InitStack] ; GS:SP -> original stack
+ les bx,[es:bp+44] ; Return address
+ cmp word [es:bx],18CDh ; Already pointing to INT 18h?
+ je .skip
+
+ ; Search memory from E0000 to FFFFF for a $EFI structure
+ mov bx,0E000h
+.scan_mem:
+ mov es,bx
+ cmp dword [es:0],'IFE$' ; $EFI is byte-reversed...
+ jne .not_here
+ ;
+ ; Verify the table. We don't check the checksum because
+ ; it seems some CSMs leave it at zero.
+ ;
+ movzx cx,byte [es:5] ; Table length
+ cmp cx,83 ; 83 bytes is the current length...
+ jae .found_it
+
+.not_here:
+ inc bx
+ jnz .scan_mem
+ jmp .skip ; No $EFI structure found
+
+ ;
+ ; Found a $EFI structure. Move down the original stack
+ ; and put an INT 18h instruction there instead.
+ ;
+.found_it:
+%if USE_PXE_PROVIDED_STACK
+ mov cx,efi_csm_hack_size
+ mov si,sp
+ sub sp,cx
+ mov di,sp
+ mov ax,ss
+ mov es,ax
+ sub [InitStack],cx
+ sub [BaseStack],cx
+%else
+ les si,[InitStack]
+ lea di,[si-efi_csm_hack_size]
+ mov [InitStack],di
+%endif
+ lea cx,[bp+52] ; End of the stack we care about
+ sub cx,si
+ es rep movsb
+ mov [es:di-8],di ; Clobber the return address
+ mov [es:di-6],es
+ mov si,efi_csm_hack
+ mov cx,efi_csm_hack_size
+ rep movsb
+
+.skip:
+ pop es ; Restore CS == DS == ES
+
+ section .data16
+ alignz 4
+efi_csm_hack:
+ int 18h
+ jmp 0F000h:0FFF0h
+ hlt
+efi_csm_hack_size equ $-efi_csm_hack
+
+ section .text16
+;
; do fs initialize
;
extern pxe_fs_ops
@@ -227,6 +303,7 @@ local_boot:
mov si,localboot_msg
call writestr_early
; Restore the environment we were called with
+ call cleanup_hardware
lss sp,[InitStack]
pop gs
pop fs
diff --git a/core/runkernel.inc b/core/runkernel.inc
index 68ab9fac..893c41c0 100644
--- a/core/runkernel.inc
+++ b/core/runkernel.inc
@@ -461,6 +461,8 @@ run_linux_kernel:
; Set up segment registers and the Linux real-mode stack
; Note: ds == the real mode segment
;
+ call cleanup_hardware
+
cli
mov ax,ds
mov ss,ax