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