summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2019-09-01 16:24:47 +0300
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2019-09-06 00:18:51 +0300
commit72a8f1685a3fece42b6dd31e41be613bf80352e4 (patch)
tree81fc1b521ff31c021a6c61ff91f9d4dd1925a953 /lib
parent5947b49b091c016a2031c9f8b476f249e31eb125 (diff)
downloadu-boot-72a8f1685a3fece42b6dd31e41be613bf80352e4.tar.xz
efi_loader: fix status management in network stack
The network should start in status EfiSimpleNetworkStopped. Add and correct status checks in the simple network protocol. Correct the unit test: * Shutdown() and Stop() during setup if needed * invoke Shutdown() before Stop() when tearing down Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/efi_loader/efi_net.c69
-rw-r--r--lib/efi_selftest/efi_selftest_snp.c48
2 files changed, 104 insertions, 13 deletions
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 950b6ed4b2..66c1898940 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -1,8 +1,18 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * EFI application network access support
+ * Simple network protocol
+ * PXE base code protocol
*
- * Copyright (c) 2016 Alexander Graf
+ * Copyright (c) 2016 Alexander Graf
+ *
+ * The simple network protocol has the following statuses and services
+ * to move between them:
+ *
+ * Start(): EfiSimpleNetworkStopped -> EfiSimpleNetworkStarted
+ * Initialize(): EfiSimpleNetworkStarted -> EfiSimpleNetworkInitialized
+ * Shutdown(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkStarted
+ * Stop(): EfiSimpleNetworkStarted -> EfiSimpleNetworkStopped
+ * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized
*/
#include <common.h>
@@ -99,10 +109,13 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
goto out;
}
- if (this->mode->state == EFI_NETWORK_STOPPED)
+ if (this->mode->state == EFI_NETWORK_STOPPED) {
ret = EFI_NOT_STARTED;
- else
+ } else {
+ /* Disable hardware and put it into the reset state */
+ eth_halt();
this->mode->state = EFI_NETWORK_STOPPED;
+ }
out:
return EFI_EXIT(ret);
}
@@ -133,6 +146,15 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
goto out;
}
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ case EFI_NETWORK_STARTED:
+ break;
+ default:
+ r = EFI_NOT_STARTED;
+ goto out;
+ }
+
/* Setup packet buffers */
net_init();
/* Disable hardware and put it into the reset state */
@@ -169,9 +191,31 @@ out:
static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this,
int extended_verification)
{
+ efi_status_t ret;
+
EFI_ENTRY("%p, %x", this, extended_verification);
- return EFI_EXIT(EFI_CALL(efi_net_initialize(this, 0, 0)));
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ break;
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ default:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+
+ this->mode->state = EFI_NETWORK_STARTED;
+ ret = EFI_CALL(efi_net_initialize(this, 0, 0));
+out:
+ return EFI_EXIT(ret);
}
/*
@@ -196,10 +240,21 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
goto out;
}
+ switch (this->mode->state) {
+ case EFI_NETWORK_INITIALIZED:
+ break;
+ case EFI_NETWORK_STOPPED:
+ ret = EFI_NOT_STARTED;
+ goto out;
+ default:
+ ret = EFI_DEVICE_ERROR;
+ goto out;
+ }
+
eth_halt();
this->int_status = 0;
wait_for_packet->is_signaled = false;
- this->mode->state = EFI_NETWORK_STOPPED;
+ this->mode->state = EFI_NETWORK_STARTED;
out:
return EFI_EXIT(ret);
@@ -779,7 +834,7 @@ efi_status_t efi_net_register(void)
netobj->net.transmit = efi_net_transmit;
netobj->net.receive = efi_net_receive;
netobj->net.mode = &netobj->net_mode;
- netobj->net_mode.state = EFI_NETWORK_STARTED;
+ netobj->net_mode.state = EFI_NETWORK_STOPPED;
memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
netobj->net_mode.hwaddr_size = ARP_HLEN;
netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c
index 807b8657b9..9797ecaf42 100644
--- a/lib/efi_selftest/efi_selftest_snp.c
+++ b/lib/efi_selftest/efi_selftest_snp.c
@@ -228,6 +228,26 @@ static int setup(const efi_handle_t handle,
efi_st_error("WaitForPacket event missing\n");
return EFI_ST_FAILURE;
}
+ if (net->mode->state == EFI_NETWORK_INITIALIZED) {
+ /*
+ * Shut down network adapter.
+ */
+ ret = net->shutdown(net);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to shut down network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ if (net->mode->state == EFI_NETWORK_STARTED) {
+ /*
+ * Stop network adapter.
+ */
+ ret = net->stop(net);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to stop network adapter\n");
+ return EFI_ST_FAILURE;
+ }
+ }
/*
* Start network adapter.
*/
@@ -236,6 +256,10 @@ static int setup(const efi_handle_t handle,
efi_st_error("Failed to start network adapter\n");
return EFI_ST_FAILURE;
}
+ if (net->mode->state != EFI_NETWORK_STARTED) {
+ efi_st_error("Failed to start network adapter\n");
+ return EFI_ST_FAILURE;
+ }
/*
* Initialize network adapter.
*/
@@ -244,6 +268,10 @@ static int setup(const efi_handle_t handle,
efi_st_error("Failed to initialize network adapter\n");
return EFI_ST_FAILURE;
}
+ if (net->mode->state != EFI_NETWORK_INITIALIZED) {
+ efi_st_error("Failed to initialize network adapter\n");
+ return EFI_ST_FAILURE;
+ }
return EFI_ST_SUCCESS;
}
@@ -412,21 +440,29 @@ static int teardown(void)
}
if (net) {
/*
- * Stop network adapter.
+ * Shut down network adapter.
*/
- ret = net->stop(net);
+ ret = net->shutdown(net);
if (ret != EFI_SUCCESS) {
- efi_st_error("Failed to stop network adapter\n");
+ efi_st_error("Failed to shut down network adapter\n");
exit_status = EFI_ST_FAILURE;
}
+ if (net->mode->state != EFI_NETWORK_STARTED) {
+ efi_st_error("Failed to shutdown network adapter\n");
+ return EFI_ST_FAILURE;
+ }
/*
- * Shut down network adapter.
+ * Stop network adapter.
*/
- ret = net->shutdown(net);
+ ret = net->stop(net);
if (ret != EFI_SUCCESS) {
- efi_st_error("Failed to shut down network adapter\n");
+ efi_st_error("Failed to stop network adapter\n");
exit_status = EFI_ST_FAILURE;
}
+ if (net->mode->state != EFI_NETWORK_STOPPED) {
+ efi_st_error("Failed to stop network adapter\n");
+ return EFI_ST_FAILURE;
+ }
}
return exit_status;