diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-05-21 10:25:43 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-21 10:25:43 -0700 |
commit | 652070309f5d283efacaa8c5102368da20a92c4a (patch) | |
tree | fbd14207e9c3c4b92c19a177a9f52993a60c5603 /core | |
parent | 55092109e53ae43ceefb5f7c6314aff103931c9a (diff) | |
download | syslinux-652070309f5d283efacaa8c5102368da20a92c4a.tar.gz |
idle: handle PXE stacks which improperly disable interruptssyslinux-3.81-pre9
At least Etherboot (and all-but-super-recent versions of gPXE) PXE
ROMs improperly disable interrupts when calling an intercepted version
of INT 15h and 1Ah; this is due to the old trick of using "ret 2" to
return... this avoids resetting the flags for status, but it also
doesn't restore the value of the interrupt flag. Needless to say,
this causes serious issues.
Work around it by adding explicit pushf/popf or STI in places known to
have issues, but also add an STI in reset_idle, and add an error alert
in do_idle if we ever get called with interrupts disabled.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'core')
-rw-r--r-- | core/conio.inc | 2 | ||||
-rw-r--r-- | core/highmem.inc | 2 | ||||
-rw-r--r-- | core/idle.inc | 30 | ||||
-rw-r--r-- | core/pxelinux.asm | 3 | ||||
-rw-r--r-- | core/ui.inc | 1 |
5 files changed, 34 insertions, 4 deletions
diff --git a/core/conio.inc b/core/conio.inc index 2d8c61ad..4488c94a 100644 --- a/core/conio.inc +++ b/core/conio.inc @@ -286,8 +286,8 @@ write_serial_str: ; pollchar: check if we have an input character pending (ZF = 0) ; pollchar: - pushad call do_idle + pushad mov ah,11h ; Poll keyboard int 16h jnz .done ; Keyboard response diff --git a/core/highmem.inc b/core/highmem.inc index 5ae3abea..c7e602f8 100644 --- a/core/highmem.inc +++ b/core/highmem.inc @@ -25,6 +25,7 @@ ; highmemsize: push es + pushfd pushad push cs @@ -152,6 +153,7 @@ got_highmem: %endif mov [HighMemSize],eax popad + popfd pop es ret ; Done! diff --git a/core/idle.inc b/core/idle.inc index c2ce1348..67a5c3ed 100644 --- a/core/idle.inc +++ b/core/idle.inc @@ -19,6 +19,7 @@ reset_idle: mov ax,[cs:BIOS_timer] mov [cs:IdleTimer],ax pop ax + sti ; Guard against BIOS/PXE brokenness... ret do_idle: @@ -28,6 +29,31 @@ do_idle: mov ax,cs mov ds,ax mov es,ax + pushf + pop ax + test ah,2 + jnz .ok + push si + push cx + mov si,hlt_err + call writestr + mov si,sp + add si,10 + mov cx,16 +.errloop: + ss lodsw + call writehex4 + dec cx + jz .endloop + mov al,' ' + call writechr + jmp .errloop +.endloop: + call crlf + pop cx + pop si + sti +.ok: mov ax,[BIOS_timer] sub ax,[IdleTimer] cmp ax,TICKS_TO_IDLE @@ -43,8 +69,10 @@ do_idle: .ret: ret section .data -NoHalt dw 0 IdleHook dw do_idle.ret +NoHalt dw 1 + +hlt_err db 'ERROR: idle with IF=0', CR, LF, 0 section .bss IdleTimer resw 1 diff --git a/core/pxelinux.asm b/core/pxelinux.asm index ad1686c1..9d9d5b4d 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -308,10 +308,11 @@ _start1: %if USE_PXE_PROVIDED_STACK == 0 lss sp,[InitStack] %endif - int 1Ah ; May trash regs + int 1Ah ; May trash regs %if USE_PXE_PROVIDED_STACK == 0 lss esp,[BaseStack] %endif + sti ; Work around Etherboot bug jc no_int1a cmp ax,564Eh diff --git a/core/ui.inc b/core/ui.inc index a12233c2..1b40717a 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -532,7 +532,6 @@ getchar_timeout: pop ax cmp ax,[BIOS_timer] ; Has the timer advanced? je .loop - call do_idle dec dword [ThisKbdTo] jz .timeout |