[pxeprefix] Ensure that UNDI IRQ is disabled before starting iPXE

When using the undionly.kkpxe binary (which is never recommended), the
UNDI interrupt may still be enabled when iPXE starts up.  If the PXE
base code interrupt handler is not well-behaved, this can result in
undefined behaviour when interrupts are first enabled (e.g. for
entropy gathering, or for allowing the timer tick to occur).

Fix by detecting and disabling the UNDI interrupt during the prefix
code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/1417/merge
Michael Brown 2025-03-26 14:49:08 +00:00
parent e8365f7a51
commit 4134280bcd
2 changed files with 58 additions and 0 deletions

View File

@ -972,6 +972,10 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
}
DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
if ( undinic->irq ) {
/* Sanity check - prefix should have disabled the IRQ */
assert ( ! irq_enabled ( undinic->irq ) );
}
/* Get interface information */
memset ( &undi_iface, 0, sizeof ( undi_iface ) );

View File

@ -1,6 +1,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXENV_UNDI_SHUTDOWN 0x0005
#define PXENV_UNDI_GET_INFORMATION 0x000c
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
#define PXENV_UNDI_GET_IFACE_INFO 0x0013
#define PXENV_STOP_UNDI 0x0015
@ -380,6 +381,33 @@ no_physical_device:
99:
/*****************************************************************************
* Get IRQ number
*****************************************************************************
*/
get_irq:
/* Issue PXENV_UNDI_GET_INFORMATION */
movw $PXENV_UNDI_GET_INFORMATION, %bx
call pxe_call
jnc 1f
call print_pxe_error
jmp 99f
1: /* Check for a valid IRQ number */
movw ( pxe_parameter_structure + 0x04 ), %ax
testw %ax, %ax
jz 99f
cmpw $15, %ax
ja 99f
/* Store IRQ number */
movw %ax, undi_irq
movw $10f, %si
call print_message
call print_word
.section ".prefix.data", "aw", @progbits
10: .asciz ", IRQ "
.previous
99:
/*****************************************************************************
* Determine interface type
*****************************************************************************
@ -470,6 +498,30 @@ pxe_cmdline:
.long 0
.previous
/*****************************************************************************
* Ensure NIC interrupt is disabled
*****************************************************************************
*/
disable_irq:
/* Check for a recorded IRQ number */
movw undi_irq, %cx
testw %cx, %cx
jz 99f
/* Calculate IMR */
movw %cx, %dx
shlw $4, %dx
andb $0x80, %dl
orb $0x21, %dl
/* Calculate mask value */
movb $0x01, %bl
andb $0x07, %cl
shlb %cl, %bl
/* Mask interrupt */
inb %dx, %al
orb %bl, %al
outb %al, %dx
99:
/*****************************************************************************
* Leave NIC in a safe state
*****************************************************************************
@ -759,6 +811,8 @@ undi_data_segoff:
undi_data_size: .word 0
undi_data_segment: .word 0
undi_irq: .word 0
pxe_hacks: .word 0
/* The following fields are part of a struct undi_device */