--- /dev/null
+/** @file\r
+ Data source for network testing.\r
+\r
+ Copyright (c) 2011, Intel Corporation\r
+ All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <errno.h>\r
+#include <Uefi.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <netinet/in.h>\r
+\r
+#include <Protocol/ServiceBinding.h>\r
+#include <Protocol/Tcp4.h>\r
+\r
+#include <sys/EfiSysCall.h>\r
+#include <sys/poll.h>\r
+#include <sys/socket.h>\r
+\r
+\r
+#define RANGE_SWITCH 2048 ///< Switch display ranges\r
+#define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates\r
+#define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average\r
+\r
+#define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL\r
+\r
+#define PACKET_SIZE 1448 ///< Size of data packets\r
+#define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes\r
+\r
+\r
+//\r
+// Socket Data\r
+//\r
+int Socket = -1;\r
+\r
+//\r
+// TCP V4 Data\r
+//\r
+BOOLEAN bTcp4; ///< TRUE if TCP4 is being used\r
+BOOLEAN bTcp4Connected; ///< TRUE if connected to remote system\r
+BOOLEAN bTcp4Connecting; ///< TRUE while connection in progress\r
+UINTN Tcp4Index; ///< Index into handle array\r
+EFI_HANDLE Tcp4Controller; ///< Network controller handle\r
+EFI_HANDLE Tcp4Handle; ///< TCP4 port handle\r
+EFI_TCP4_PROTOCOL * pTcp4Protocol; ///< TCP4 protocol pointer\r
+EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service; ///< TCP4 Service binding\r
+EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///< TCP4 configuration data\r
+EFI_TCP4_OPTION Tcp4Option; ///< TCP4 port options\r
+EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///< Close control\r
+EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///< Connection control\r
+EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken; ///< Listen control\r
+EFI_TCP4_IO_TOKEN Tcp4TxToken; ///< Normal data token\r
+\r
+//\r
+// Timer Data\r
+//\r
+volatile BOOLEAN bTick;\r
+BOOLEAN bTimerRunning;\r
+EFI_EVENT pTimer;\r
+\r
+//\r
+// Remote IP Address Data\r
+//\r
+struct sockaddr_in RemoteHostAddress;\r
+CHAR8 * pRemoteHost;\r
+\r
+//\r
+// Traffic Data\r
+//\r
+UINT64 TotalBytesSent;\r
+UINT64 PreviousBytes;\r
+UINT64 AverageBytes;\r
+UINT64 Samples;\r
+UINT8 Buffer [ DATA_BUFFER_SIZE ];\r
+\r
+\r
+//\r
+// Forward routine declarations\r
+//\r
+EFI_STATUS TimerStart ( UINTN Milliseconds );\r
+\r
+\r
+/**\r
+ Check for control C entered at console\r
+\r
+ @retval EFI_SUCCESS Control C not entered\r
+ @retval EFI_ABORTED Control C entered\r
+**/\r
+EFI_STATUS\r
+ControlCCheck (\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume no user intervention\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Display user stop request\r
+ //\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "User stop request!\r\n" ));\r
+ }\r
+\r
+ //\r
+ // Return the check status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Get a digit\r
+\r
+ @param [in] pDigit The address of the next digit\r
+ @param [out] pValue The address to receive the value\r
+\r
+ @returns Returns the address of the separator\r
+\r
+**/\r
+CHAR8 *\r
+GetDigit (\r
+ CHAR8 * pDigit,\r
+ UINT32 * pValue\r
+ )\r
+{\r
+ UINT32 Value;\r
+\r
+ //\r
+ // Walk the digits\r
+ //\r
+ Value = 0;\r
+ while (( '0' <= *pDigit ) && ( '9' >= *pDigit ))\r
+ {\r
+ //\r
+ // Make room for the new least significant digit\r
+ //\r
+ Value *= 10;\r
+\r
+ //\r
+ // Convert the digit from ASCII to binary\r
+ //\r
+ Value += *pDigit - '0';\r
+\r
+ //\r
+ // Set the next digit\r
+ //\r
+ pDigit += 1;\r
+ }\r
+\r
+ //\r
+ // Return the value\r
+ //\r
+ *pValue = Value;\r
+\r
+ //\r
+ // Return the next separator\r
+ //\r
+ return pDigit;\r
+}\r
+\r
+\r
+/**\r
+ Get the IP address\r
+\r
+ @retval EFI_SUCCESS The IP address is valid\r
+ @retval Other Failure to convert the IP address\r
+**/\r
+EFI_STATUS\r
+IpAddress (\r
+ )\r
+{\r
+ CHAR8 * pSeparator;\r
+ INT32 RemoteAddress;\r
+ EFI_STATUS Status;\r
+ UINT32 Value1;\r
+ UINT32 Value2;\r
+ UINT32 Value3;\r
+ UINT32 Value4;\r
+\r
+ //\r
+ // Assume failure\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+\r
+ //\r
+ // Convert the IP address from a string to a numeric value\r
+ //\r
+ pSeparator = GetDigit ( pRemoteHost, &Value1 );\r
+ if (( 255 >= Value1 ) && ( '.' == *pSeparator )) {\r
+ pSeparator = GetDigit ( ++pSeparator, &Value2 );\r
+ if (( 255 >= Value2 ) && ( '.' == *pSeparator )) {\r
+ pSeparator = GetDigit ( ++pSeparator, &Value3 );\r
+ if (( 255 >= Value3 ) && ( '.' == *pSeparator )) {\r
+ pSeparator = GetDigit ( ++pSeparator, &Value4 );\r
+ if (( 255 >= Value4 ) && ( 0 == *pSeparator )) {\r
+ RemoteAddress = Value1\r
+ | ( Value2 << 8 )\r
+ | ( Value3 << 16 )\r
+ | ( Value4 << 24 );\r
+ RemoteHostAddress.sin_addr.s_addr = (UINT32) RemoteAddress;\r
+ Status = EFI_SUCCESS;\r
+ DEBUG (( DEBUG_INFO,\r
+ "%d.%d.%d.%d: Remote host IP address\r\n",\r
+ Value1,\r
+ Value2,\r
+ Value3,\r
+ Value4 ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ Print ( L"Invalid digit detected: %d\r\n", *pSeparator );\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Close the socket\r
+\r
+ @retval EFI_SUCCESS The application is running normally\r
+ @retval Other The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketClose (\r
+ )\r
+{\r
+ int CloseStatus;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Determine if the socket is open\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+ if ( -1 != Socket ) {\r
+ //\r
+ // Attempt to close the socket\r
+ //\r
+ CloseStatus = close ( Socket );\r
+ if ( 0 == CloseStatus ) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Socket closed\r\n",\r
+ Socket ));\r
+ Socket = -1;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR: Failed to close socket, errno: %d\r\n",\r
+ errno ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Connect the socket\r
+\r
+ @retval EFI_SUCCESS The application is running normally\r
+ @retval Other The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketConnect (\r
+ )\r
+{\r
+ int ConnectStatus;\r
+ UINT32 RemoteAddress;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Display the connecting message\r
+ //\r
+ RemoteAddress = RemoteHostAddress.sin_addr.s_addr;\r
+ Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",\r
+ RemoteAddress & 0xff,\r
+ ( RemoteAddress >> 8 ) & 0xff,\r
+ ( RemoteAddress >> 16 ) & 0xff,\r
+ ( RemoteAddress >> 24 ) & 0xff,\r
+ htons ( RemoteHostAddress.sin_port ));\r
+\r
+ //\r
+ // Connect to the remote system\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ do {\r
+ //\r
+ // Check for user stop request\r
+ //\r
+ while ( ! bTick ) {\r
+ Status = ControlCCheck ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ bTick = FALSE;\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Connect to the remote system\r
+ //\r
+ ConnectStatus = connect ( Socket,\r
+ (struct sockaddr *) &RemoteHostAddress,\r
+ RemoteHostAddress.sin_len );\r
+ if ( -1 != ConnectStatus ) {\r
+ Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
+ RemoteAddress & 0xff,\r
+ ( RemoteAddress >> 8 ) & 0xff,\r
+ ( RemoteAddress >> 16 ) & 0xff,\r
+ ( RemoteAddress >> 24 ) & 0xff,\r
+ htons ( RemoteHostAddress.sin_port ));\r
+ }\r
+ else {\r
+ //\r
+ // Close the socket and try again\r
+ //\r
+ if ( EAGAIN != errno ) {\r
+ Status = EFI_NOT_STARTED;\r
+ break;\r
+ }\r
+ }\r
+ } while ( -1 == ConnectStatus );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Create the socket\r
+\r
+ @retval EFI_SUCCESS The application is running normally\r
+ @retval Other The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketNew (\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Loop creating the socket\r
+ //\r
+ DEBUG (( DEBUG_INFO,\r
+ "Creating the socket\r\n" ));\r
+ do {\r
+ //\r
+ // Check for user stop request\r
+ //\r
+ Status = ControlCCheck ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Attempt to create the socket\r
+ //\r
+ Socket = socket ( AF_INET,\r
+ SOCK_STREAM,\r
+ IPPROTO_TCP );\r
+ if ( -1 != Socket ) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Socket created\r\n",\r
+ Socket ));\r
+ break;\r
+ }\r
+ } while ( -1 == Socket );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send data over the socket\r
+\r
+ @retval EFI_SUCCESS The application is running normally\r
+ @retval Other The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketSend (\r
+ )\r
+{\r
+ size_t BytesSent;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+\r
+ //\r
+ // Restart the timer\r
+ //\r
+ TimerStart ( 1000 << DATA_RATE_UPDATE_SHIFT );\r
+\r
+ //\r
+ // Loop until the connection breaks or the user stops\r
+ //\r
+ do {\r
+ //\r
+ // Check for user stop request\r
+ //\r
+ Status = ControlCCheck ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send some bytes\r
+ //\r
+ BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));\r
+ if ( -1 == BytesSent ) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "ERROR: send failed, errno: %d\r\n",\r
+ errno ));\r
+\r
+ //\r
+ // Try again\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+//\r
+// Exit now\r
+//\r
+Status = EFI_NOT_STARTED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Synchronize with the TimerCallback routine\r
+ //\r
+ TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
+\r
+ //\r
+ // Account for the data sent\r
+ //\r
+ TotalBytesSent += BytesSent;\r
+\r
+ //\r
+ // Release the TimerCallback routine synchronization\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+ } while ( !EFI_ERROR ( Status ));\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Open the network connection and send the data.\r
+\r
+ @retval EFI_SUCCESS Continue looping\r
+ @retval other Stopped by user's Control-C input\r
+\r
+**/\r
+EFI_STATUS\r
+SocketOpen (\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use do/while and break instead of goto\r
+ //\r
+ do\r
+ {\r
+ //\r
+ // Wait for the network layer to initialize\r
+ //\r
+ Status = SocketNew ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Wait for the remote network application to start\r
+ //\r
+ Status = SocketConnect ( );\r
+ if ( EFI_NOT_STARTED == Status ) {\r
+ Status = SocketClose ( );\r
+ continue;\r
+ }\r
+ else if ( EFI_SUCCESS != Status ) {\r
+ //\r
+ // Control-C\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send data until the connection breaks\r
+ //\r
+ Status = SocketSend ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ } while ( FALSE );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Close the TCP connection\r
+\r
+ @retval EFI_SUCCESS The application is running normally\r
+ @retval Other The user stopped the application\r
+**/\r
+EFI_STATUS\r
+Tcp4Close (\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 * pIpAddress;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Close the port\r
+ //\r
+ if ( bTcp4Connected ) {\r
+ Tcp4CloseToken.AbortOnClose = TRUE;\r
+ Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
+ &Tcp4CloseToken );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to start the TCP port close, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ Status = gBS->WaitForEvent ( 1,\r
+ &Tcp4CloseToken.CompletionToken.Event,\r
+ &Index );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to wait for close event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ Status = Tcp4CloseToken.CompletionToken.Status;\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the TCP port, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TCP port closed\r\n",\r
+ pTcp4Protocol ));\r
+ bTcp4Connected = FALSE;\r
+\r
+ //\r
+ // Display the port closed message\r
+ //\r
+ pIpAddress = (UINT8 *)&RemoteHostAddress.sin_addr.s_addr;\r
+ Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",\r
+ pIpAddress[0],\r
+ pIpAddress[1],\r
+ pIpAddress[2],\r
+ pIpAddress[3],\r
+ htons ( RemoteHostAddress.sin_port ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Release the events\r
+ //\r
+ if ( NULL != Tcp4TxToken.CompletionToken.Event ) {\r
+ Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TX event closed\r\n",\r
+ Tcp4TxToken.CompletionToken.Event ));\r
+ Tcp4TxToken.CompletionToken.Event = NULL;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {\r
+ Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Listen event closed\r\n",\r
+ Tcp4ListenToken.CompletionToken.Event ));\r
+ Tcp4ListenToken.CompletionToken.Event = NULL;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {\r
+ Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Connect event closed\r\n",\r
+ Tcp4ConnectToken.CompletionToken.Event ));\r
+ Tcp4ConnectToken.CompletionToken.Event = NULL;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {\r
+ Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Close event closed\r\n",\r
+ Tcp4CloseToken.CompletionToken.Event ));\r
+ Tcp4CloseToken.CompletionToken.Event = NULL;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Close the TCP protocol\r
+ //\r
+ if ( NULL != pTcp4Protocol ) {\r
+ Status = gBS->CloseProtocol ( Tcp4Handle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ gImageHandle,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the TCP protocol, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TCP4 protocol closed\r\n",\r
+ pTcp4Protocol ));\r
+ pTcp4Protocol = NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Done with the TCP service\r
+ //\r
+ if ( NULL != Tcp4Handle ) {\r
+ Status = pTcp4Service->DestroyChild ( pTcp4Service,\r
+ Tcp4Handle );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to release TCP service handle, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_INFO,\r
+ "Ox%08x: TCP service closed\r\n",\r
+ Tcp4Handle ));\r
+ Tcp4Handle = NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Close the service protocol\r
+ //\r
+ if ( NULL != pTcp4Service ) {\r
+ Status = gBS->CloseProtocol ( Tcp4Controller,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ gImageHandle,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
+ Tcp4Controller ));\r
+ pTcp4Service = NULL;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+ Tcp4Controller = NULL;\r
+ bTcp4Connecting = TRUE;\r
+\r
+ //\r
+ // Mark the connection as closed\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Locate TCP protocol\r
+\r
+ @retval EFI_SUCCESS Protocol found\r
+ @retval other Protocl not found\r
+**/\r
+EFI_STATUS\r
+Tcp4Locate (\r
+ )\r
+{\r
+ UINTN HandleCount;\r
+ EFI_HANDLE * pHandles;\r
+ UINT8 * pIpAddress;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use do/while and break instead of goto\r
+ //\r
+ do {\r
+ //\r
+ // Attempt to locate the next TCP adapter in the system\r
+ //\r
+ Status = gBS->LocateHandleBuffer ( ByProtocol,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &pHandles );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_WARN,\r
+ "WARNING - No network controllers or TCP4 available, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Wrap the index if necessary\r
+ //\r
+ if ( HandleCount <= Tcp4Index ) {\r
+ Tcp4Index = 0;\r
+ \r
+ //\r
+ // Wait for the next timer tick\r
+ //\r
+ do {\r
+ } while ( !bTick );\r
+ bTick = FALSE;\r
+ }\r
+\r
+ //\r
+ // Display the connecting message\r
+ //\r
+ if ( bTcp4Connecting ) {\r
+ pIpAddress = (UINT8 *)&RemoteHostAddress.sin_addr.s_addr;\r
+ Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",\r
+ pIpAddress[0],\r
+ pIpAddress[1],\r
+ pIpAddress[2],\r
+ pIpAddress[3],\r
+ htons ( RemoteHostAddress.sin_port ));\r
+ bTcp4Connecting = FALSE;\r
+ }\r
+ \r
+ //\r
+ // Open the network controller's service protocol\r
+ //\r
+ Tcp4Controller = pHandles [ Tcp4Index++ ];\r
+ Status = gBS->OpenProtocol (\r
+ Tcp4Controller,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ (VOID **) &pTcp4Service,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",\r
+ Tcp4Controller ));\r
+ Tcp4Controller = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
+ Tcp4Controller ));\r
+\r
+ //\r
+ // Connect to the TCP service\r
+ //\r
+ Status = pTcp4Service->CreateChild ( pTcp4Service,\r
+ &Tcp4Handle );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to open TCP service, Status: %r\r\n",\r
+ Status ));\r
+ Tcp4Handle = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "Ox%08x: TCP service opened\r\n",\r
+ Tcp4Handle ));\r
+\r
+ //\r
+ // Locate the TCP protcol\r
+ //\r
+ Status = gBS->OpenProtocol ( Tcp4Handle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ (VOID **)&pTcp4Protocol,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to open the TCP protocol, Status: %r\r\n",\r
+ Status ));\r
+ pTcp4Protocol = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TCP4 protocol opened\r\n",\r
+ pTcp4Protocol ));\r
+ }while ( FALSE );\r
+\r
+ //\r
+ // Release the handle buffer\r
+ //\r
+ gBS->FreePool ( pHandles );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send data over the TCP4 connection\r
+\r
+ @retval EFI_SUCCESS The application is running normally\r
+ @retval Other The user stopped the application\r
+**/\r
+EFI_STATUS\r
+Tcp4Send (\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_TCP4_TRANSMIT_DATA Packet;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+\r
+ //\r
+ // Restart the timer\r
+ //\r
+ TimerStart ( 1000 << DATA_RATE_UPDATE_SHIFT );\r
+\r
+ //\r
+ // Initialize the packet\r
+ //\r
+ Packet.DataLength = sizeof ( Buffer );\r
+ Packet.FragmentCount = 1;\r
+ Packet.Push = FALSE;\r
+ Packet.Urgent = FALSE;\r
+ Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];\r
+ Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );\r
+ Tcp4TxToken.Packet.TxData = &Packet;\r
+\r
+ //\r
+ // Loop until the connection breaks or the user stops\r
+ //\r
+ do {\r
+ //\r
+ // Check for user stop request\r
+ //\r
+ Status = ControlCCheck ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send some bytes\r
+ //\r
+ Status = pTcp4Protocol->Transmit ( pTcp4Protocol,\r
+ &Tcp4TxToken );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to start the transmit, Status: %r\r\n",\r
+ Status ));\r
+\r
+ //\r
+ // Try again\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Wait for the transmit to complete\r
+ //\r
+ Status = gBS->WaitForEvent ( 1,\r
+ &Tcp4TxToken.CompletionToken.Event,\r
+ &Index );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to wait for transmit completion, Status: %r\r\n",\r
+ Status ));\r
+\r
+ //\r
+ // Try again\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the transmit status\r
+ //\r
+ Status = Tcp4TxToken.CompletionToken.Status;\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_WARN,\r
+ "WARNING - Failed the transmission, Status: %r\r\n",\r
+ Status ));\r
+\r
+ //\r
+ // Try again\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+//\r
+// Exit now\r
+//\r
+Status = EFI_NOT_STARTED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Synchronize with the TimerCallback routine\r
+ //\r
+ TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
+\r
+ //\r
+ // Account for the data sent\r
+ //\r
+ TotalBytesSent += Packet.DataLength;\r
+\r
+ //\r
+ // Release the TimerCallback routine synchronization\r
+ //\r
+ gBS->RestoreTPL ( TplPrevious );\r
+ } while ( !EFI_ERROR ( Status ));\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Open the network connection and send the data.\r
+\r
+ @retval EFI_SUCCESS Continue looping\r
+ @retval other Stopped by user's Control-C input\r
+\r
+**/\r
+EFI_STATUS\r
+Tcp4Open (\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 * pIpAddress;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use do/while and break instead of goto\r
+ //\r
+ do {\r
+ //\r
+ // Locate the TCP protocol\r
+ //\r
+ Status = Tcp4Locate ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Create the necessary events\r
+ //\r
+ Status = gBS->CreateEvent ( 0,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &Tcp4CloseToken.CompletionToken.Event );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to create the close event, Status: %r\r\n",\r
+ Status ));\r
+ Tcp4CloseToken.CompletionToken.Event = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Close event open\r\n",\r
+ Tcp4CloseToken.CompletionToken.Event ));\r
+\r
+ Status = gBS->CreateEvent ( 0,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &Tcp4ConnectToken.CompletionToken.Event );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to create the connect event, Status: %r\r\n",\r
+ Status ));\r
+ Tcp4ConnectToken.CompletionToken.Event = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Connect event open\r\n",\r
+ Tcp4ConnectToken.CompletionToken.Event ));\r
+\r
+ Status = gBS->CreateEvent ( 0,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &Tcp4ListenToken.CompletionToken.Event );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to create the listen event, Status: %r\r\n",\r
+ Status ));\r
+ Tcp4ListenToken.CompletionToken.Event = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Listen event open\r\n",\r
+ Tcp4ListenToken.CompletionToken.Event ));\r
+\r
+ Status = gBS->CreateEvent ( 0,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &Tcp4TxToken.CompletionToken.Event );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to create the TX event, Status: %r\r\n",\r
+ Status ));\r
+ Tcp4TxToken.CompletionToken.Event = NULL;\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TX event open\r\n",\r
+ Tcp4TxToken.CompletionToken.Event ));\r
+\r
+ //\r
+ // Configure the local TCP port\r
+ //\r
+ Tcp4ConfigData.TimeToLive = 255;\r
+ Tcp4ConfigData.TypeOfService = 0;\r
+ Tcp4ConfigData.ControlOption = NULL;\r
+ Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;\r
+ Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;\r
+ Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;\r
+ Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;\r
+ Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;\r
+ Tcp4ConfigData.AccessPoint.StationPort = 0;\r
+ Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) RemoteHostAddress.sin_addr.s_addr;\r
+ Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 8 );\r
+ Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 16 );\r
+ Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 24 );\r
+ Tcp4ConfigData.AccessPoint.RemotePort = RemoteHostAddress.sin_port;\r
+ Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;\r
+ Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
+ Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
+ Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;\r
+ Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;\r
+ Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
+ &Tcp4ConfigData );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR, \r
+ "ERROR - Failed to configure TCP port, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TCP4 port configured\r\n",\r
+ pTcp4Protocol ));\r
+\r
+ //\r
+ // Connect to the remote TCP port\r
+ //\r
+ Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
+ &Tcp4ConnectToken );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+ Status = gBS->WaitForEvent ( 1,\r
+ &Tcp4ConnectToken.CompletionToken.Event,\r
+ &Index );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to wait for the connection, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+ Status = Tcp4ConnectToken.CompletionToken.Status;\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_WARN,\r
+ "WARNING - Failed to connect to the remote system, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: TCP4 port connected\r\n",\r
+ pTcp4Protocol ));\r
+ bTcp4Connected = TRUE;\r
+\r
+ //\r
+ // Display the connection\r
+ //\r
+ pIpAddress = (UINT8 *)&RemoteHostAddress.sin_addr.s_addr;\r
+ Print ( L"Connected to %d.%d.%d.%d:%d\r\n",\r
+ pIpAddress[0],\r
+ pIpAddress[1],\r
+ pIpAddress[2],\r
+ pIpAddress[3],\r
+ htons ( RemoteHostAddress.sin_port ));\r
+ } while ( 0 );\r
+\r
+ if ( EFI_ERROR ( Status )) {\r
+ //\r
+ // Try again\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ else {\r
+ //\r
+ // Semd data until the connection breaks\r
+ //\r
+ Status = Tcp4Send ( );\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Handle the timer callback\r
+\r
+ @param [in] Event Event that caused this callback\r
+ @param [in] pContext Context for this routine\r
+**/\r
+VOID\r
+TimerCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID * pContext\r
+ )\r
+{\r
+ UINT64 BytesSent;\r
+ UINT64 DeltaBytes;\r
+ UINT32 Delta;\r
+ UINT64 Average;\r
+\r
+ //\r
+ // Notify the other code of the timer tick\r
+ //\r
+ bTick = TRUE;\r
+\r
+ //\r
+ // Update the average bytes per second\r
+ //\r
+ BytesSent = TotalBytesSent;\r
+ if ( 0 != BytesSent ) {\r
+ DeltaBytes = AverageBytes >> AVERAGE_SHIFT_COUNT;\r
+ AverageBytes -= DeltaBytes;\r
+ DeltaBytes = BytesSent - PreviousBytes;\r
+ PreviousBytes = BytesSent;\r
+ AverageBytes += DeltaBytes;\r
+\r
+ //\r
+ // Separate the samples\r
+ //\r
+ if (( 2 << AVERAGE_SHIFT_COUNT ) == Samples ) {\r
+ Print ( L"---------- Stable average ----------\r\n" );\r
+ }\r
+ Samples += 1;\r
+\r
+ //\r
+ // Display the data rate\r
+ //\r
+ Delta = (UINT32)( DeltaBytes >> DATA_RATE_UPDATE_SHIFT );\r
+ Average = AverageBytes >> ( AVERAGE_SHIFT_COUNT + DATA_RATE_UPDATE_SHIFT );\r
+ if ( Average < RANGE_SWITCH ) {\r
+ Print ( L"%d Bytes/sec, Ave: %d Bytes/Sec\r\n",\r
+ Delta,\r
+ (UINT32) Average );\r
+ }\r
+ else {\r
+ Average >>= 10;\r
+ if ( Average < RANGE_SWITCH ) {\r
+ Print ( L"%d Bytes/sec, Ave: %d KiBytes/Sec\r\n",\r
+ Delta,\r
+ (UINT32) Average );\r
+ }\r
+ else {\r
+ Average >>= 10;\r
+ if ( Average < RANGE_SWITCH ) {\r
+ Print ( L"%d Bytes/sec, Ave: %d MiBytes/Sec\r\n",\r
+ Delta,\r
+ (UINT32) Average );\r
+ }\r
+ else {\r
+ Average >>= 10;\r
+ if ( Average < RANGE_SWITCH ) {\r
+ Print ( L"%d Bytes/sec, Ave: %d GiBytes/Sec\r\n",\r
+ Delta,\r
+ (UINT32) Average );\r
+ }\r
+ else {\r
+ Average >>= 10;\r
+ if ( Average < RANGE_SWITCH ) {\r
+ Print ( L"%d Bytes/sec, Ave: %d TiBytes/Sec\r\n",\r
+ Delta,\r
+ Average );\r
+ }\r
+ else {\r
+ Average >>= 10;\r
+ Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",\r
+ Delta,\r
+ (UINT32) Average );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Create the timer\r
+\r
+ @retval EFI_SUCCESS The timer was successfully created\r
+ @retval Other Timer initialization failed\r
+**/\r
+EFI_STATUS\r
+TimerCreate (\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Create the timer\r
+ //\r
+ Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_DATASOURCE,\r
+ TimerCallback,\r
+ NULL,\r
+ &pTimer );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to allocate the timer event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Timer created\r\n",\r
+ pTimer ));\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop the timer\r
+\r
+ @retval EFI_SUCCESS The timer was stopped successfully\r
+ @retval Other The timer failed to stop\r
+**/\r
+EFI_STATUS\r
+TimerStop (\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Determine if the timer is running\r
+ //\r
+ if ( bTimerRunning ) {\r
+ //\r
+ // Stop the timer\r
+ //\r
+ Status = gBS->SetTimer ( pTimer,\r
+ TimerCancel,\r
+ 0 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to stop the timer, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ //\r
+ // Timer timer is now stopped\r
+ //\r
+ bTimerRunning = FALSE;\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Timer stopped\r\n",\r
+ pTimer ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Start the timer\r
+\r
+ @param [in] Milliseconds The number of milliseconds between timer callbacks\r
+\r
+ @retval EFI_SUCCESS The timer was successfully created\r
+ @retval Other Timer initialization failed\r
+**/\r
+EFI_STATUS\r
+TimerStart (\r
+ UINTN Milliseconds\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 TimeDelay;\r
+\r
+ //\r
+ // Stop the timer if necessary\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ if ( bTimerRunning ) {\r
+ Status = TimerStop ( );\r
+ }\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Compute the new delay\r
+ //\r
+ TimeDelay = Milliseconds;\r
+ TimeDelay *= 1000 * 10;\r
+\r
+ //\r
+ // Start the timer\r
+ //\r
+ Status = gBS->SetTimer ( pTimer,\r
+ TimerPeriodic,\r
+ TimeDelay );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to start the timer, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ //\r
+ // The timer is now running\r
+ //\r
+ bTimerRunning = TRUE;\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Timer running\r\n",\r
+ pTimer ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Destroy the timer\r
+\r
+ @retval EFI_SUCCESS The timer was destroyed successfully\r
+ @retval Other Failed to destroy the timer\r
+**/\r
+EFI_STATUS\r
+TimerDestroy (\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Determine if the timer is running\r
+ //\r
+ if ( bTimerRunning ) {\r
+ //\r
+ // Stop the timer\r
+ //\r
+ Status = TimerStop ( );\r
+ }\r
+ if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {\r
+ //\r
+ // Done with this timer\r
+ //\r
+ Status = gBS->CloseEvent ( pTimer );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to free the timer event, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_INFO,\r
+ "0x%08x: Timer Destroyed\r\n",\r
+ pTimer ));\r
+ pTimer = NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send data to the DataSink program to test a network's bandwidth.\r
+\r
+ @param [in] Argc The number of arguments\r
+ @param [in] Argv The argument value array\r
+\r
+ @retval 0 The application exited normally.\r
+ @retval Other An error occurred.\r
+**/\r
+int\r
+main (\r
+ IN int Argc,\r
+ IN char **Argv\r
+ )\r
+{\r
+ EFI_STATUS (* pClose) ();\r
+ EFI_STATUS (* pOpen) ();\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG (( DEBUG_INFO,\r
+ "DataSource starting\r\n" ));\r
+\r
+ //\r
+ // Validate the command line\r
+ //\r
+ if ( 2 != Argc ) {\r
+ Print ( L"%s <remote IP address>\r\n", Argv[0] );\r
+ return -1;\r
+ }\r
+\r
+bTcp4 = TRUE;\r
+\r
+ //\r
+ // Determine the support routines\r
+ //\r
+ if ( bTcp4 ) {\r
+ pOpen = Tcp4Open;\r
+ pClose = Tcp4Close;\r
+ bTcp4Connecting = TRUE;\r
+ }\r
+ else {\r
+ pOpen = SocketOpen;\r
+ pClose = SocketClose;\r
+ }\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; )\r
+ {\r
+ //\r
+ // No bytes sent so far\r
+ //\r
+ TotalBytesSent = 0;\r
+ AverageBytes = 0;\r
+ PreviousBytes = 0;\r
+ Samples = 0;\r
+\r
+ //\r
+ // Get the port number\r
+ //\r
+ ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));\r
+ RemoteHostAddress.sin_len = sizeof ( RemoteHostAddress );\r
+ RemoteHostAddress.sin_family = AF_INET;\r
+ RemoteHostAddress.sin_port = htons ( PcdGet16 ( DataSource_Port ));\r
+\r
+Print ( L"Argc: %d\r\n", Argc);\r
+Print ( L"Argv[0]: %a\r\n", Argv[0]);\r
+Print ( L"Argv[1]: %a\r\n", Argv[1]);\r
+\r
+ //\r
+ // Get the IP address\r
+ //\r
+ pRemoteHost = Argv [1];\r
+ Status = IpAddress ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Create the timer\r
+ //\r
+ bTick = TRUE;\r
+ Status = TimerCreate ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Loop forever abusing the specified system\r
+ //\r
+ do {\r
+ //\r
+ // Start a timer to perform connection polling and display updates\r
+ //\r
+ Status = TimerStart ( 2 * 1000 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Open the network connection and send the data\r
+ //\r
+ Status = pOpen ( );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Done with the network connection\r
+ //\r
+ Status = pClose ( );\r
+ } while ( !EFI_ERROR ( Status ));\r
+\r
+ //\r
+ // Close the network connection if necessary\r
+ //\r
+ pClose ( );\r
+\r
+ //\r
+ // All done\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Stop the timer if necessary\r
+ //\r
+ TimerStop ( );\r
+ TimerDestroy ( );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DEBUG (( DEBUG_INFO,\r
+ "DataSource exiting, Status: %r\r\n",\r
+ Status ));\r
+ return Status;\r
+}\r