[U-Boot] [PATCH 4/5] efi_loader: fix status management in network stack

Heinrich Schuchardt xypron.glpk at gmx.de
Sun Sep 1 16:06:06 UTC 2019


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 at gmx.de>
---
 lib/efi_loader/efi_net.c            | 69 ++++++++++++++++++++++++++---
 lib/efi_selftest/efi_selftest_snp.c | 48 +++++++++++++++++---
 2 files changed, 104 insertions(+), 13 deletions(-)

diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 646540ac08..970b5ab38e 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;
--
2.20.1



More information about the U-Boot mailing list