]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Raise TPL within EFI_SIMPLE_NETWORK_PROTOCOL entry points
authorMichael Brown <mcb30@ipxe.org>
Tue, 20 Feb 2018 11:08:25 +0000 (11:08 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 20 Feb 2018 11:19:21 +0000 (11:19 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/interface/efi/efi_snp.c

index 88d999bf0d445f2852e01896dcfca9344acc35c2..3f95a896199167feaeb2e6422ce524475ad2ccf3 100644 (file)
@@ -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 */