summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/efi_api.h2
-rw-r--r--lib/efi_loader/efi_net.c40
2 files changed, 27 insertions, 15 deletions
diff --git a/include/efi_api.h b/include/efi_api.h
index 43778197af..7f7b67fa00 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -1281,6 +1281,8 @@ struct efi_simple_network {
struct efi_mac_address *dest_addr, u16 *protocol);
struct efi_event *wait_for_packet;
struct efi_simple_network_mode *mode;
+ /* private fields */
+ u32 int_status;
};
#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 825e064f9a..bf6d5ab0b3 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -66,10 +66,13 @@ static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
goto out;
}
- if (this->mode->state != EFI_NETWORK_STOPPED)
+ if (this->mode->state != EFI_NETWORK_STOPPED) {
ret = EFI_ALREADY_STARTED;
- else
+ } else {
+ this->int_status = 0;
+ wait_for_packet->is_signaled = false;
this->mode->state = EFI_NETWORK_STARTED;
+ }
out:
return EFI_EXIT(ret);
}
@@ -144,6 +147,8 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
r = EFI_DEVICE_ERROR;
goto out;
} else {
+ this->int_status = 0;
+ wait_for_packet->is_signaled = false;
this->mode->state = EFI_NETWORK_INITIALIZED;
}
out:
@@ -192,6 +197,8 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
}
eth_halt();
+ this->int_status = 0;
+ wait_for_packet->is_signaled = false;
this->mode->state = EFI_NETWORK_STOPPED;
out:
@@ -350,10 +357,8 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
}
if (int_status) {
- /* We send packets synchronously, so nothing is outstanding */
- *int_status = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
- if (new_rx_packet)
- *int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+ *int_status = this->int_status;
+ this->int_status = 0;
}
if (txbuf)
*txbuf = new_tx_packet;
@@ -429,7 +434,7 @@ static efi_status_t EFIAPI efi_net_transmit
net_send_packet(transmit_buffer, buffer_size);
new_tx_packet = buffer;
-
+ this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
out:
return EFI_EXIT(ret);
}
@@ -487,12 +492,6 @@ static efi_status_t EFIAPI efi_net_receive
ret = EFI_NOT_READY;
goto out;
}
- /* Check that we at least received an Ethernet header */
- if (net_rx_packet_len < sizeof(struct ethernet_hdr)) {
- new_rx_packet = false;
- ret = EFI_NOT_READY;
- goto out;
- }
/* Fill export parameters */
eth_hdr = (struct ethernet_hdr *)net_rx_packet;
protlen = ntohs(eth_hdr->et_protlen);
@@ -517,7 +516,8 @@ static efi_status_t EFIAPI efi_net_receive
/* Copy packet */
memcpy(buffer, net_rx_packet, net_rx_packet_len);
*buffer_size = net_rx_packet_len;
- new_rx_packet = false;
+ new_rx_packet = 0;
+ this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
out:
return EFI_EXIT(ret);
}
@@ -548,7 +548,6 @@ void efi_net_set_dhcp_ack(void *pkt, int len)
static void efi_net_push(void *pkt, int len)
{
new_rx_packet = true;
- wait_for_packet->is_signaled = true;
}
/**
@@ -577,6 +576,17 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event,
push_packet = efi_net_push;
eth_rx();
push_packet = NULL;
+ if (new_rx_packet) {
+ /* Check that we at least received an Ethernet header */
+ if (net_rx_packet_len >=
+ sizeof(struct ethernet_hdr)) {
+ this->int_status |=
+ EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+ wait_for_packet->is_signaled = true;
+ } else {
+ new_rx_packet = 0;
+ }
+ }
}
out:
EFI_EXIT(EFI_SUCCESS);