diff options
author | Michael Brown | 2018-02-20 12:08:25 +0100 |
---|---|---|
committer | Michael Brown | 2018-02-20 12:19:21 +0100 |
commit | a272b7ce5789ac9a467f37288c03f317d1a46517 (patch) | |
tree | 8e57964dfccb3f5d3273c5dfa9eb2ba64095a829 /src/interface/efi | |
parent | [efi] Run at TPL_CALLBACK to protect against UEFI timers (diff) | |
download | ipxe-a272b7ce5789ac9a467f37288c03f317d1a46517.tar.gz ipxe-a272b7ce5789ac9a467f37288c03f317d1a46517.tar.xz ipxe-a272b7ce5789ac9a467f37288c03f317d1a46517.zip |
[efi] Raise TPL within EFI_SIMPLE_NETWORK_PROTOCOL entry points
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi')
-rw-r--r-- | src/interface/efi/efi_snp.c | 93 |
1 files changed, 81 insertions, 12 deletions
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 88d999bf..3f95a896 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -233,8 +233,10 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { static EFI_STATUS EFIAPI efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); + EFI_TPL saved_tpl; int rc; DBGC ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n", @@ -242,17 +244,26 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, ( ( unsigned long ) extra_tx_bufsize ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; + if ( efi_snp_claimed ) { + rc = -EAGAIN; + goto err_claimed; + } + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + + /* Open network device */ if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); - return EFIRC ( rc ); + goto err_open; } efi_snp_set_state ( snpdev ); - return 0; + err_open: + bs->RestoreTPL ( saved_tpl ); + err_claimed: + return EFIRC ( rc ); } /** @@ -264,29 +275,41 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, */ static EFI_STATUS EFIAPI efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); + EFI_TPL saved_tpl; int rc; DBGC ( snpdev, "SNPDEV %p RESET (%s extended verification)\n", snpdev, ( ext_verify ? "with" : "without" ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; + if ( efi_snp_claimed ) { + rc = -EAGAIN; + goto err_claimed; + } + + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Close network device */ netdev_close ( snpdev->netdev ); efi_snp_set_state ( snpdev ); efi_snp_flush ( snpdev ); + /* Reopen network device */ if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); - return EFIRC ( rc ); + goto err_open; } efi_snp_set_state ( snpdev ); - return 0; + err_open: + bs->RestoreTPL ( saved_tpl ); + err_claimed: + return EFIRC ( rc ); } /** @@ -297,8 +320,10 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { */ static EFI_STATUS EFIAPI efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); + EFI_TPL saved_tpl; DBGC ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev ); @@ -306,10 +331,17 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) { if ( efi_snp_claimed ) return EFI_NOT_READY; + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + + /* Close network device */ netdev_close ( snpdev->netdev ); efi_snp_set_state ( snpdev ); efi_snp_flush ( snpdev ); + /* Restore TPL */ + bs->RestoreTPL ( saved_tpl ); + return 0; } @@ -512,8 +544,10 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read, static EFI_STATUS EFIAPI efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 *interrupts, VOID **txbuf ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); + EFI_TPL saved_tpl; DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev ); @@ -523,6 +557,9 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, return EFI_NOT_READY; } + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Poll the network device */ efi_snp_poll ( snpdev ); @@ -545,6 +582,9 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, DBGC2 ( snpdev, " TX:%p", *txbuf ); } + /* Restore TPL */ + bs->RestoreTPL ( saved_tpl ); + DBGC2 ( snpdev, "\n" ); return 0; } @@ -566,12 +606,14 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN ll_header_len, UINTN len, VOID *data, EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, UINT16 *net_proto ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; struct io_buffer *iobuf; size_t payload_len; unsigned int tx_fill; + EFI_TPL saved_tpl; int rc; DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data, @@ -592,8 +634,13 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, DBGC2 ( snpdev, "\n" ); /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; + if ( efi_snp_claimed ) { + rc = -EAGAIN; + goto err_claimed; + } + + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); /* Sanity checks */ if ( ll_header_len ) { @@ -677,6 +724,9 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, snpdev->tx[ snpdev->tx_prod++ % EFI_SNP_NUM_TX ] = data; snpdev->interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; + /* Restore TPL */ + bs->RestoreTPL ( saved_tpl ); + return 0; err_ring_full: @@ -685,6 +735,8 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, free_iob ( iobuf ); err_alloc_iob: err_sanity: + bs->RestoreTPL ( saved_tpl ); + err_claimed: return EFIRC ( rc ); } @@ -705,6 +757,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINTN *ll_header_len, UINTN *len, VOID *data, EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest, UINT16 *net_proto ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; @@ -714,14 +767,20 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, uint16_t iob_net_proto; unsigned int iob_flags; size_t copy_len; + EFI_TPL saved_tpl; int rc; DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data, ( ( unsigned long ) *len ) ); /* Fail if net device is currently claimed for use by iPXE */ - if ( efi_snp_claimed ) - return EFI_NOT_READY; + if ( efi_snp_claimed ) { + rc = -EAGAIN; + goto err_claimed; + } + + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); /* Poll the network device */ efi_snp_poll ( snpdev ); @@ -770,6 +829,8 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, out_bad_ll_header: free_iob ( iobuf ); out_no_packet: + bs->RestoreTPL ( saved_tpl ); + err_claimed: return EFIRC ( rc ); } @@ -781,7 +842,9 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, */ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event __unused, VOID *context ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_snp_device *snpdev = context; + EFI_TPL saved_tpl; DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev ); @@ -793,8 +856,14 @@ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event __unused, if ( efi_snp_claimed ) return; + /* Raise TPL */ + saved_tpl = bs->RaiseTPL ( TPL_CALLBACK ); + /* Poll the network device */ efi_snp_poll ( snpdev ); + + /* Restore TPL */ + bs->RestoreTPL ( saved_tpl ); } /** SNP interface */ |