[pcbios] Don't use "lret $2" to return from an interrupt

Using "lret $2" to return from an interrupt causes interrupts to be
disabled in the calling program, since the INT instruction will have
disabled interrupts.  Instead, patch CF on the stack and use iret to
return.

Interestingly, the original PC BIOS had this bug in at least one
place.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Michael Brown <mcb30@etherboot.org>
pull/1/head
H. Peter Anvin 2009-04-11 18:30:22 -07:00 committed by Michael Brown
parent dc387547a3
commit f44205b9ea
3 changed files with 26 additions and 13 deletions

View File

@ -489,6 +489,18 @@ get_mangled_e820:
ret ret
.size get_mangled_e820, . - get_mangled_e820 .size get_mangled_e820, . - get_mangled_e820
/****************************************************************************
* Set/clear CF on the stack as appropriate, assumes stack is as it should
* be immediately before IRET
****************************************************************************
*/
patch_cf:
pushw %bp
movw %sp, %bp
setc 8(%bp) /* Set/reset CF; clears PF, AF, ZF, SF */
popw %bp
ret
/**************************************************************************** /****************************************************************************
* INT 15,e820 handler * INT 15,e820 handler
**************************************************************************** ****************************************************************************
@ -500,7 +512,8 @@ int15_e820:
popw %ds popw %ds
call get_mangled_e820 call get_mangled_e820
popw %ds popw %ds
lret $2 call patch_cf
iret
.size int15_e820, . - int15_e820 .size int15_e820, . - int15_e820
/**************************************************************************** /****************************************************************************
@ -512,7 +525,7 @@ int15_e801:
/* Call previous handler */ /* Call previous handler */
pushfw pushfw
lcall *%cs:int15_vector lcall *%cs:int15_vector
pushfw call patch_cf
/* Edit result */ /* Edit result */
pushw %ds pushw %ds
pushw %cs:rm_ds pushw %cs:rm_ds
@ -524,9 +537,7 @@ int15_e801:
xchgw %ax, %cx xchgw %ax, %cx
xchgw %bx, %dx xchgw %bx, %dx
popw %ds popw %ds
/* Restore flags returned by previous handler and return */ iret
popfw
lret $2
.size int15_e801, . - int15_e801 .size int15_e801, . - int15_e801
/**************************************************************************** /****************************************************************************
@ -538,16 +549,14 @@ int15_88:
/* Call previous handler */ /* Call previous handler */
pushfw pushfw
lcall *%cs:int15_vector lcall *%cs:int15_vector
pushfw call patch_cf
/* Edit result */ /* Edit result */
pushw %ds pushw %ds
pushw %cs:rm_ds pushw %cs:rm_ds
popw %ds popw %ds
call patch_1m call patch_1m
popw %ds popw %ds
/* Restore flags returned by previous handler and return */ iret
popfw
lret $2
.size int15_88, . - int15_88 .size int15_88, . - int15_88
/**************************************************************************** /****************************************************************************

View File

@ -63,6 +63,8 @@ void fake_e820 ( void ) {
"cmpl $0x534d4150, %%edx\n\t" "cmpl $0x534d4150, %%edx\n\t"
"jne 99f\n\t" "jne 99f\n\t"
"pushaw\n\t" "pushaw\n\t"
"movw %%sp, %%bp\n\t"
"andb $~0x01, 22(%%bp)\n\t" /* Clear return CF */
"leaw e820map(%%bx), %%si\n\t" "leaw e820map(%%bx), %%si\n\t"
"cs rep movsb\n\t" "cs rep movsb\n\t"
"popaw\n\t" "popaw\n\t"
@ -73,8 +75,7 @@ void fake_e820 ( void ) {
"xorl %%ebx,%%ebx\n\t" "xorl %%ebx,%%ebx\n\t"
"\n1:\n\t" "\n1:\n\t"
"popfw\n\t" "popfw\n\t"
"clc\n\t" "iret\n\t"
"lret $2\n\t"
"\n99:\n\t" "\n99:\n\t"
"popfw\n\t" "popfw\n\t"
"ljmp *%%cs:real_int15_vector\n\t" ) "ljmp *%%cs:real_int15_vector\n\t" )

View File

@ -199,9 +199,12 @@ pxe_int_1a:
shll $4, %edx shll $4, %edx
addl $pxenv, %edx addl $pxenv, %edx
movw $0x564e, %ax movw $0x564e, %ax
pushw %bp
movw %sp, %bp
andb $~0x01, 8(%bp) /* Clear CF on return */
popw %bp
popfw popfw
clc iret
lret $2
1: /* INT 1A,other - pass through */ 1: /* INT 1A,other - pass through */
popfw popfw
ljmp *%cs:pxe_int_1a_vector ljmp *%cs:pxe_int_1a_vector