14684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/** @file
24684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Data source for network testing.
34684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
49f7f5161cf2f6c1e29f4f11ff2a70454b223431alpleahy  Copyright (c) 2011-2012, Intel Corporation
54684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  All rights reserved. This program and the accompanying materials
64684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  are licensed and made available under the terms and conditions of the BSD License
74684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  which accompanies this distribution.  The full text of the license may be found at
84684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  http://opensource.org/licenses/bsd-license.php
94684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <errno.h>
164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Uefi.h>
174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Library/BaseMemoryLib.h>
194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Library/DebugLib.h>
204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Library/PcdLib.h>
214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Library/UefiBootServicesTableLib.h>
224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Library/UefiLib.h>
234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <netinet/in.h>
254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Protocol/ServiceBinding.h>
274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <Protocol/Tcp4.h>
284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <sys/EfiSysCall.h>
304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <sys/poll.h>
314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#include <sys/socket.h>
324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
33f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy#include <stdio.h>
34d3a595ceb902372504db27442bca278c67d41b10lpleahy#include <string.h>
354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
36f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy
37f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy#define DATA_SAMPLE_SHIFT           5       ///<  Shift for number of samples
38f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy#define RANGE_SWITCH        ( 1024 * 1024 ) ///<  Switch display ranges
39f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy#define DATA_RATE_UPDATE_SHIFT      2       ///<  2n seconds between updates
404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average
41f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy#define DATA_SAMPLES        ( 1 << DATA_SAMPLE_SHIFT )      ///<  Number of samples
424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#define TPL_DATASOURCE      TPL_CALLBACK  ///<  Synchronization TPL
444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#define PACKET_SIZE                 1448  ///<  Size of data packets
464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm#define DATA_BUFFER_SIZE    (( 65536 / PACKET_SIZE ) * PACKET_SIZE )  ///<  Buffer size in bytes
474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Socket Data
514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
524684b66f261ffb74fa7575ed10df43cc0645a42fdarylmint Socket = -1;
534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  TCP V4 Data
564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
574684b66f261ffb74fa7575ed10df43cc0645a42fdarylmBOOLEAN bTcp4;                      ///<  TRUE if TCP4 is being used
584684b66f261ffb74fa7575ed10df43cc0645a42fdarylmBOOLEAN bTcp4Connected;             ///<  TRUE if connected to remote system
594684b66f261ffb74fa7575ed10df43cc0645a42fdarylmBOOLEAN bTcp4Connecting;            ///<  TRUE while connection in progress
604684b66f261ffb74fa7575ed10df43cc0645a42fdarylmUINTN Tcp4Index;                    ///<  Index into handle array
614684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_HANDLE Tcp4Controller;          ///<  Network controller handle
624684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_HANDLE Tcp4Handle;              ///<  TCP4 port handle
634684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_PROTOCOL * pTcp4Protocol;  ///<  TCP4 protocol pointer
644684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;  ///<  TCP4 Service binding
654684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_CONFIG_DATA Tcp4ConfigData;///<  TCP4 configuration data
664684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_OPTION Tcp4Option;         ///<  TCP4 port options
674684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///<  Close control
684684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///<  Connection control
694684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_LISTEN_TOKEN Tcp4ListenToken;      ///<  Listen control
704684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_TCP4_IO_TOKEN Tcp4TxToken;      ///<  Normal data token
714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Timer Data
744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
754684b66f261ffb74fa7575ed10df43cc0645a42fdarylmvolatile BOOLEAN bTick;
764684b66f261ffb74fa7575ed10df43cc0645a42fdarylmBOOLEAN bTimerRunning;
774684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_EVENT pTimer;
784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Remote IP Address Data
814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
82f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahystruct sockaddr_in6 RemoteHostAddress;
834684b66f261ffb74fa7575ed10df43cc0645a42fdarylmCHAR8 * pRemoteHost;
844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Traffic Data
874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
884684b66f261ffb74fa7575ed10df43cc0645a42fdarylmUINT64 TotalBytesSent;
89f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahyUINT32 In;
90f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahyUINT32 Samples;
91f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahyUINT64 BytesSent[ DATA_SAMPLES ];
9259bc059327dd519619fa437c0d7c941e090cd8a3lpleahyUINT8 Buffer[ DATA_BUFFER_SIZE ];
934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Forward routine declarations
974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
984684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS TimerStart ( UINTN Milliseconds );
994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
1024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Check for control C entered at console
1034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  Control C not entered
1054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_ABORTED  Control C entered
1064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
1074684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
1084684b66f261ffb74fa7575ed10df43cc0645a42fdarylmControlCCheck (
1094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
1104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
1114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
1124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Assume no user intervention
1154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_SUCCESS;
1174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Display user stop request
1204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( EFI_ERROR ( Status )) {
1224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
1234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "User stop request!\r\n" ));
1244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
1254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the check status
1284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
1304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
1314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
1344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Get a digit
1354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [in] pDigit    The address of the next digit
1374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [out] pValue   The address to receive the value
1384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1397dc1329100c370992cdd430359512443bd1ee9f2darylm  @return   Returns the address of the separator
1404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
1424684b66f261ffb74fa7575ed10df43cc0645a42fdarylmCHAR8 *
1434684b66f261ffb74fa7575ed10df43cc0645a42fdarylmGetDigit (
1444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  CHAR8 * pDigit,
1454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT32 * pValue
1464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
1474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
1484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT32 Value;
1494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Walk the digits
1524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Value = 0;
15459bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  while (( '0' <= *pDigit ) && ( '9' >= *pDigit )) {
1554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Make room for the new least significant digit
1574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Value *= 10;
1594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Convert the digit from ASCII to binary
1624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Value += *pDigit - '0';
1644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Set the next digit
1674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    pDigit += 1;
1694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
1704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the value
1734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  *pValue = Value;
1754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the next separator
1784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return pDigit;
1804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
1814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
1844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Get the IP address
1854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
1864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The IP address is valid
1874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        Failure to convert the IP address
1884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
1894684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
1904684b66f261ffb74fa7575ed10df43cc0645a42fdarylmIpAddress (
1914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
1924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
193f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  struct sockaddr_in * pRemoteAddress4;
194f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  struct sockaddr_in6 * pRemoteAddress6;
195f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 RemoteAddress;
1964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
1974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT32 Value1;
1984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT32 Value2;
1994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT32 Value3;
2004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT32 Value4;
201f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 Value5;
202f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 Value6;
203f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 Value7;
204f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 Value8;
2054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
2064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
2074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Assume failure
2084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
2094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_INVALID_PARAMETER;
2104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
2114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
212f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  //  Get the port number
213f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  //
214f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));
215f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));
216f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;
217f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  pRemoteAddress6 = &RemoteHostAddress;
218f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy
219f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  //
2204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Convert the IP address from a string to a numeric value
2214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
222f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  if (( 4 == sscanf ( pRemoteHost,
223f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      "%d.%d.%d.%d",
224f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      &Value1,
225f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      &Value2,
226f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      &Value3,
227f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      &Value4 ))
228f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      && ( 255 >= Value1 )
229f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      && ( 255 >= Value2 )
230f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      && ( 255 >= Value3 )
231f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      && ( 255 >= Value4 )) {
232f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
233f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //  Build the IPv4 address
234f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
235f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );
236f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress4->sin_family = AF_INET;
237f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    RemoteAddress = Value1
238f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                  | ( Value2 << 8 )
239f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                  | ( Value3 << 16 )
240f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                  | ( Value4 << 24 );
241f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress4->sin_addr.s_addr = RemoteAddress;
242f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Status = EFI_SUCCESS;
243f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy
244f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
245f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //  Display the IP address
246f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
247f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    DEBUG (( DEBUG_INFO,
248f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              "%d.%d.%d.%d: Remote host IP address\r\n",
249f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value1,
250f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value2,
251f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value3,
252f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value4 ));
2534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
254f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  else if (( 8 == sscanf ( pRemoteHost,
255f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           "%x:%x:%x:%x:%x:%x:%x:%x",
256f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value1,
257f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value2,
258f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value3,
259f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value4,
260f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value5,
261f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value6,
262f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value7,
263f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                           &Value8 ))
264f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value1 )
265f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value2 )
266f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value3 )
267f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value4 )
268f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value5 )
269f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value6 )
270f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value7 )
271f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            && ( 0xffff >= Value8 )) {
272f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
273f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //  Build the IPv6 address
274f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
275f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_len = sizeof ( *pRemoteAddress6 );
276f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_family = AF_INET6;
277f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ] = (UINT8)( Value1 >> 8 );
278f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ] = (UINT8)Value1;
279f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ] = (UINT8)( Value2 >> 8 );
280f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ] = (UINT8)Value2;
281f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ] = (UINT8)( Value3 >> 8 );
282f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ] = (UINT8)Value3;
283f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ] = (UINT8)( Value4 >> 8 );
284f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ] = (UINT8)Value4;
285f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ] = (UINT8)( Value5 >> 8 );
286f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ] = (UINT8)Value5;
287f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ] = (UINT8)( Value6 >> 8 );
288f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ] = (UINT8)Value6;
289f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ] = (UINT8)( Value7 >> 8 );
290f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ] = (UINT8)Value7;
291f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ] = (UINT8)( Value8 >> 8 );
292f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ] = (UINT8)Value8;
293f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Status = EFI_SUCCESS;
294f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy
295f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
296f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //  Display the IP address
297f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
298f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    DEBUG (( DEBUG_INFO,
299f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
300f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value1,
301f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value2,
302f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value3,
303f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value4,
304f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value5,
305f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value6,
306f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value7,
307f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Value8 ));
308f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  }
309f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  else {
310f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Print ( L"ERROR - Invalid IP address!\r\n" );
3114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
3124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
3154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
3174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
3184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
3214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Close the socket
3224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The application is running normally
3244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The user stopped the application
3254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
3264684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
3274684b66f261ffb74fa7575ed10df43cc0645a42fdarylmSocketClose (
3284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
3294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
3304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  int CloseStatus;
3314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
3324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Determine if the socket is open
3354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_DEVICE_ERROR;
3374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( -1 != Socket ) {
3384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
3394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Attempt to close the socket
3404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
3414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    CloseStatus = close ( Socket );
3424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( 0 == CloseStatus ) {
3434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
3444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Socket closed\r\n",
3454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Socket ));
3464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Socket = -1;
3474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = EFI_SUCCESS;
3484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
3494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
3504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
3514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR: Failed to close socket, errno: %d\r\n",
3524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                errno ));
3534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
3544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
3554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
3584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
3604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
3614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
3644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Connect the socket
3654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The application is running normally
3674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The user stopped the application
3684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
3694684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
3704684b66f261ffb74fa7575ed10df43cc0645a42fdarylmSocketConnect (
3714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
3724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
3734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  int ConnectStatus;
374f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  struct sockaddr_in * pRemoteAddress4;
375f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  struct sockaddr_in6 * pRemoteAddress6;
3764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
3774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
3784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
3794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Display the connecting message
3804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
381f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;
382f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  pRemoteAddress6 = &RemoteHostAddress;
383f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  if ( AF_INET == pRemoteAddress6->sin6_family ) {
384f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",
385f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress4->sin_addr.s_addr & 0xff,
386f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
387f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
388f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
389b8a86b22291344499256f735c47c341d2a105986lpleahy            ntohs ( pRemoteAddress4->sin_port ));
390f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  }
391f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  else {
392f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
393f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
394f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
395f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
396f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
397f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
398f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
399f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
400f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
401f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
402f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
403f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
404f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
405f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
406f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
407f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
408f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
409b8a86b22291344499256f735c47c341d2a105986lpleahy            ntohs ( pRemoteAddress6->sin6_port ));
410f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  }
4114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
4124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
4134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Connect to the remote system
4144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
4154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_SUCCESS;
4164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  do {
4174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
4184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Check for user stop request
4194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
42059bc059327dd519619fa437c0d7c941e090cd8a3lpleahy    while ( !bTick ) {
4214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = ControlCCheck ( );
4224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      if ( EFI_ERROR ( Status )) {
4234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        break;
4244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
4254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
4264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    bTick = FALSE;
4274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
4284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
4294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
4304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
4314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
4324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Connect to the remote system
4334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
4344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    ConnectStatus = connect ( Socket,
435f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                              (struct sockaddr *)pRemoteAddress6,
436f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                              pRemoteAddress6->sin6_len );
4374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( -1 != ConnectStatus ) {
438f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      if ( AF_INET == pRemoteAddress6->sin6_family ) {
439f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy        Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
440f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress4->sin_addr.s_addr & 0xff,
441f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
442f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
443f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
444b8a86b22291344499256f735c47c341d2a105986lpleahy                ntohs ( pRemoteAddress4->sin_port ));
445f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      }
446f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      else {
447f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy        Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
448f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
449f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
450f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
451f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
452f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
453f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
454f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
455f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
456f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
457f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
458f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
459f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
460f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
461f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
462f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
463f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
464b8a86b22291344499256f735c47c341d2a105986lpleahy                ntohs ( pRemoteAddress6->sin6_port ));
465f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      }
466b8a86b22291344499256f735c47c341d2a105986lpleahyPrint ( L"ConnectStatus: %d, Status: %r\r\n", ConnectStatus, Status );
4674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
4684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
4694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
4704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Close the socket and try again
4714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
4724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      if ( EAGAIN != errno ) {
4734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        Status = EFI_NOT_STARTED;
4744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        break;
4754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
4764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
4774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  } while ( -1 == ConnectStatus );
4784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
4794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
4804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
4814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
482b8a86b22291344499256f735c47c341d2a105986lpleahyPrint ( L"SocketConnect returning Status: %r\r\n", Status );
4834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
4844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
4854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
4864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
4874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
4884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Create the socket
4894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
490f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  @param [in] Family    Network family, AF_INET or AF_INET6
491f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy
4924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The application is running normally
4934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The user stopped the application
4944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
4954684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
4964684b66f261ffb74fa7575ed10df43cc0645a42fdarylmSocketNew (
497f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  sa_family_t Family
4984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
4994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
5004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
5014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Loop creating the socket
5044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  DEBUG (( DEBUG_INFO,
5064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            "Creating the socket\r\n" ));
5074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  do {
5084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Check for user stop request
5104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = ControlCCheck ( );
5124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
5134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
5144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
5154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Attempt to create the socket
5184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
519f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Socket = socket ( Family,
5204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                      SOCK_STREAM,
5214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                      IPPROTO_TCP );
5224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( -1 != Socket ) {
5234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
5244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Socket created\r\n",
5254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Socket ));
5264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
5274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
5284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  } while ( -1 == Socket );
5294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
5324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
5344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
5354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
5384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Send data over the socket
5394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The application is running normally
5414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The user stopped the application
5424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
5434684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
5444684b66f261ffb74fa7575ed10df43cc0645a42fdarylmSocketSend (
5454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
5464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
5474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  size_t BytesSent;
5484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
5494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_TPL TplPrevious;
5504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Restart the timer
5534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
554f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  TimerStart ( 1 * 1000 );
5554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Loop until the connection breaks or the user stops
5584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
5594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  do {
5604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Check for user stop request
5624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = ControlCCheck ( );
5644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
5654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
5664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
5674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Send some bytes
5704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));
5724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( -1 == BytesSent ) {
5734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
5744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR: send failed, errno: %d\r\n",
5754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                errno ));
576b8a86b22291344499256f735c47c341d2a105986lpleahyPrint ( L"ERROR: send failed, errno: %d\r\n", errno );
5774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
5794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Try again
5804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
5814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = EFI_SUCCESS;
5824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
5844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Exit now
5854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
5864684b66f261ffb74fa7575ed10df43cc0645a42fdarylmStatus = EFI_NOT_STARTED;
5874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
5884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
5894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Synchronize with the TimerCallback routine
5924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
5944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
5954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Account for the data sent
5974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
5984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TotalBytesSent += BytesSent;
5994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Release the TimerCallback routine synchronization
6024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    gBS->RestoreTPL ( TplPrevious );
6044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  } while ( !EFI_ERROR ( Status ));
6054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
6074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
6084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
6094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
6104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
6114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
6144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Open the network connection and send the data.
6154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval EFI_SUCCESS   Continue looping
6174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval other         Stopped by user's Control-C input
6184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
6204684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
6214684b66f261ffb74fa7575ed10df43cc0645a42fdarylmSocketOpen (
6224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
6234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
6244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
6254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
6274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Use do/while and break instead of goto
6284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
62959bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  do {
6304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Wait for the network layer to initialize
6324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
633f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Status = SocketNew ( RemoteHostAddress.sin6_family );
6344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
6354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
6364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
6374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Wait for the remote network application to start
6404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = SocketConnect ( );
642b8a86b22291344499256f735c47c341d2a105986lpleahyPrint ( L"Status: %r\r\n", Status );
6434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_NOT_STARTED == Status ) {
6444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = SocketClose ( );
6454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      continue;
6464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
6474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else if ( EFI_SUCCESS != Status ) {
6484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
6494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Control-C
6504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
6514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
6524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
6534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Send data until the connection breaks
6564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
6574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = SocketSend ( );
6584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
6594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
6604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
6614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  } while ( FALSE );
6624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
6644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
6654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
666b8a86b22291344499256f735c47c341d2a105986lpleahyPrint ( L"Returning Status: %r\r\n", Status );
6674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
6684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
6694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
6724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Close the TCP connection
6734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The application is running normally
6754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The user stopped the application
6764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
6774684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
6784684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTcp4Close (
6794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
6804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
6814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINTN Index;
6824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT8 * pIpAddress;
6834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
6844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
6854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
6864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Close the port
6874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
6884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( bTcp4Connected ) {
6894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4CloseToken.AbortOnClose = TRUE;
6904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = pTcp4Protocol->Close ( pTcp4Protocol,
6914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                    &Tcp4CloseToken );
6924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
6934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
6944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to start the TCP port close, Status: %r\r\n",
6954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
6964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
6974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
6984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = gBS->WaitForEvent ( 1,
6994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                   &Tcp4CloseToken.CompletionToken.Event,
7004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                    &Index );
7014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      if ( EFI_ERROR ( Status )) {
7024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        DEBUG (( DEBUG_ERROR,
7034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                  "ERROR - Failed to wait for close event, Status: %r\r\n",
7044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                  Status ));
7054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
7064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      else {
7074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        Status = Tcp4CloseToken.CompletionToken.Status;
7084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        if ( EFI_ERROR ( Status )) {
7094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          DEBUG (( DEBUG_ERROR,
7104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    "ERROR - Failed to close the TCP port, Status: %r\r\n",
7114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    Status ));
7124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        }
7134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        else {
7144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          DEBUG (( DEBUG_INFO,
7154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    "0x%08x: TCP port closed\r\n",
7164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    pTcp4Protocol ));
7174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          bTcp4Connected = FALSE;
7184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
7194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          //
7204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          //  Display the port closed message
7214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          //
722f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy          pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
7234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",
7244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                  pIpAddress[0],
7254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                  pIpAddress[1],
7264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                  pIpAddress[2],
7274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                  pIpAddress[3],
728b8a86b22291344499256f735c47c341d2a105986lpleahy                  ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
7294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        }
7304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
7314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
7334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
7344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
7354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Release the events
7364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
7374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != Tcp4TxToken.CompletionToken.Event ) {
7384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );
7394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( !EFI_ERROR ( Status )) {
7404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
7414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: TX event closed\r\n",
7424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4TxToken.CompletionToken.Event ));
7434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4TxToken.CompletionToken.Event = NULL;
7444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
7464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
7474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
7484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
7494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
7514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
7524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {
7534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );
7544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( !EFI_ERROR ( Status )) {
7554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
7564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Listen event closed\r\n",
7574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4ListenToken.CompletionToken.Event ));
7584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4ListenToken.CompletionToken.Event = NULL;
7594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
7614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
7624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
7634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
7644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
7664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
7674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {
7684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );
7694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( !EFI_ERROR ( Status )) {
7704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
7714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Connect event closed\r\n",
7724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4ConnectToken.CompletionToken.Event ));
7734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4ConnectToken.CompletionToken.Event = NULL;
7744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
7764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
7774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
7784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
7794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
7814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
7824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {
7834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );
7844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( !EFI_ERROR ( Status )) {
7854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
7864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Close event closed\r\n",
7874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4CloseToken.CompletionToken.Event ));
7884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4CloseToken.CompletionToken.Event = NULL;
7894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
7914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
7924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
7934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
7944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
7954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
7964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
7974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
7984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Close the TCP protocol
7994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != pTcp4Protocol ) {
8014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseProtocol ( Tcp4Handle,
8024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                  &gEfiTcp4ProtocolGuid,
8034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                  gImageHandle,
8044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                  NULL );
8054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
8064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
8074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
8084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
8094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
8104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
8114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
8124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: TCP4 protocol closed\r\n",
8134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                pTcp4Protocol ));
8144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      pTcp4Protocol = NULL;
8154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
8164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
8174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Done with the TCP service
8204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != Tcp4Handle ) {
8224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = pTcp4Service->DestroyChild ( pTcp4Service,
8234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                          Tcp4Handle );
8244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
8254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
8264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to release TCP service handle, Status: %r\r\n",
8274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
8284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
8294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
8304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
8314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "Ox%08x: TCP service closed\r\n",
8324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4Handle ));
8334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4Handle = NULL;
8344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
8354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
8364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Close the service protocol
8394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( NULL != pTcp4Service ) {
8414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseProtocol ( Tcp4Controller,
8424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                  &gEfiTcp4ServiceBindingProtocolGuid,
8434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                  gImageHandle,
8444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                  NULL );
8454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( !EFI_ERROR ( Status )) {
8464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
8474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
8484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4Controller ));
8494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      pTcp4Service = NULL;
8504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
8514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
8524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
8534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
8544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
8554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
8564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
8574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Tcp4Controller = NULL;
8584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  bTcp4Connecting = TRUE;
8594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Mark the connection as closed
8624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_SUCCESS;
8644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
8674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
8694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
8704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
8734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Locate TCP protocol
8744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval EFI_SUCCESS   Protocol found
8764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval other         Protocl not found
8774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
8784684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
8794684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTcp4Locate (
8804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
8814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
8824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINTN HandleCount;
8834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_HANDLE * pHandles;
8844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT8 * pIpAddress;
8854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
8864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
8874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Use do/while and break instead of goto
8894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
8904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  do {
8914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
8924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Attempt to locate the next TCP adapter in the system
8934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
8944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->LocateHandleBuffer ( ByProtocol,
8954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                       &gEfiTcp4ServiceBindingProtocolGuid,
8964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                       NULL,
8974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                       &HandleCount,
8984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                       &pHandles );
8994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
9004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_WARN,
9014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
9024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
9034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
9044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
9054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
9064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Wrap the index if necessary
9084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( HandleCount <= Tcp4Index ) {
9104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4Index = 0;
9117dc1329100c370992cdd430359512443bd1ee9f2darylm
9124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
9134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Wait for the next timer tick
9144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
9154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      do {
9164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      } while ( !bTick );
9174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      bTick = FALSE;
9184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
9194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
9204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Display the connecting message
9224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( bTcp4Connecting ) {
924f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
9254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",
9264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pIpAddress[0],
9274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pIpAddress[1],
9284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pIpAddress[2],
9294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pIpAddress[3],
930b8a86b22291344499256f735c47c341d2a105986lpleahy              ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
9314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      bTcp4Connecting = FALSE;
9324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
9337dc1329100c370992cdd430359512443bd1ee9f2darylm
9344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Open the network controller's service protocol
9364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
93759bc059327dd519619fa437c0d7c941e090cd8a3lpleahy    Tcp4Controller = pHandles[ Tcp4Index++ ];
9384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->OpenProtocol (
9394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    Tcp4Controller,
9404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    &gEfiTcp4ServiceBindingProtocolGuid,
9414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    (VOID **) &pTcp4Service,
9424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    gImageHandle,
9434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    NULL,
9444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
9454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
9464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
9474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
9484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Tcp4Controller ));
9494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4Controller = NULL;
9504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
9514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
9524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
9534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
9544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Tcp4Controller ));
9554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
9564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Connect to the TCP service
9584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = pTcp4Service->CreateChild ( pTcp4Service,
9604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                         &Tcp4Handle );
9614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
9624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
9634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to open TCP service, Status: %r\r\n",
9644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
9654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4Handle = NULL;
9664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
9674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
9684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
9694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "Ox%08x: TCP service opened\r\n",
9704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Tcp4Handle ));
9714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
9724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Locate the TCP protcol
9744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
9754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->OpenProtocol ( Tcp4Handle,
9764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 &gEfiTcp4ProtocolGuid,
9774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 (VOID **)&pTcp4Protocol,
9784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 gImageHandle,
9794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 NULL,
9804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
9814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
9824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
9834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to open the TCP protocol, Status: %r\r\n",
9844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
9854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      pTcp4Protocol = NULL;
9864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
9874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
9884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
9894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: TCP4 protocol opened\r\n",
9904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pTcp4Protocol ));
9914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }while ( FALSE );
9924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
9934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
9944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Release the handle buffer
9954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
9964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  gBS->FreePool ( pHandles );
9974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
9984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
9994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
10004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
10014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
10024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
10034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
10064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Send data over the TCP4 connection
10074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The application is running normally
10094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The user stopped the application
10104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
10114684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
10124684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTcp4Send (
10134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
10144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
10154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINTN Index;
10164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_TCP4_TRANSMIT_DATA Packet;
10174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
10184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_TPL TplPrevious;
10194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
10214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Restart the timer
10224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1023f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  TimerStart ( 1 * 1000 );
10244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
10264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Initialize the packet
10274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
10284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Packet.DataLength = sizeof ( Buffer );
10294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Packet.FragmentCount = 1;
10304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Packet.Push = FALSE;
10314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Packet.Urgent = FALSE;
10324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];
10334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );
10344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Tcp4TxToken.Packet.TxData = &Packet;
10354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
10374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Loop until the connection breaks or the user stops
10384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
10394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  do {
10404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Check for user stop request
10424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = ControlCCheck ( );
10444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
10454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
10464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
10474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Send some bytes
10504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = pTcp4Protocol->Transmit ( pTcp4Protocol,
10524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                       &Tcp4TxToken );
10534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
10544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
10554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to start the transmit, Status: %r\r\n",
10564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
10574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
10594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Try again
10604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
10614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = EFI_SUCCESS;
10624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
10634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
10644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Wait for the transmit to complete
10674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->WaitForEvent ( 1,
10694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 &Tcp4TxToken.CompletionToken.Event,
10704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 &Index );
10714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
10724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
10734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
10744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
10754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
10774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Try again
10784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
10794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = EFI_SUCCESS;
10804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
10814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
10824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Get the transmit status
10854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
10864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = Tcp4TxToken.CompletionToken.Status;
10874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
10884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_WARN,
10894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "WARNING - Failed the transmission, Status: %r\r\n",
10904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
10914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
10934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Try again
10944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
10954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = EFI_SUCCESS;
10964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
10974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
10984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//  Exit now
10994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm//
11004684b66f261ffb74fa7575ed10df43cc0645a42fdarylmStatus = EFI_NOT_STARTED;
11014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
11024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
11034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Synchronize with the TimerCallback routine
11064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
11084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Account for the data sent
11114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TotalBytesSent += Packet.DataLength;
11134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Release the TimerCallback routine synchronization
11164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    gBS->RestoreTPL ( TplPrevious );
11184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  } while ( !EFI_ERROR ( Status ));
11194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
11214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
11224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
11234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
11244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
11254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
11284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Open the network connection and send the data.
11294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval EFI_SUCCESS   Continue looping
11314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval other         Stopped by user's Control-C input
11324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
11344684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
11354684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTcp4Open (
11364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
11374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
11384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINTN Index;
11394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT8 * pIpAddress;
11404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
11414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
11434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Use do/while and break instead of goto
11444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
11454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  do {
11464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Locate the TCP protocol
11484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = Tcp4Locate ( );
11504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
11514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
11524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
11534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Create the necessary events
11564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
11574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CreateEvent ( 0,
11584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                TPL_CALLBACK,
11594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
11604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
11614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                &Tcp4CloseToken.CompletionToken.Event );
11624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
11634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
11644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to create the close event, Status: %r\r\n",
11654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
11664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4CloseToken.CompletionToken.Event = NULL;
11674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
11684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
11694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
11704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: Close event open\r\n",
11714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Tcp4CloseToken.CompletionToken.Event ));
11724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CreateEvent ( 0,
11744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                TPL_CALLBACK,
11754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
11764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
11774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                &Tcp4ConnectToken.CompletionToken.Event );
11784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
11794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
11804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to create the connect event, Status: %r\r\n",
11814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
11824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4ConnectToken.CompletionToken.Event = NULL;
11834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
11844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
11854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
11864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: Connect event open\r\n",
11874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Tcp4ConnectToken.CompletionToken.Event ));
11884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
11894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CreateEvent ( 0,
11904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                TPL_CALLBACK,
11914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
11924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
11934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                &Tcp4ListenToken.CompletionToken.Event );
11944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
11954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
11964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to create the listen event, Status: %r\r\n",
11974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
11984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4ListenToken.CompletionToken.Event = NULL;
11994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
12004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
12014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
12024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: Listen event open\r\n",
12034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Tcp4ListenToken.CompletionToken.Event ));
12044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
12054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CreateEvent ( 0,
12064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                TPL_CALLBACK,
12074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
12084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                NULL,
12094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                &Tcp4TxToken.CompletionToken.Event );
12104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
12114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
12124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to create the TX event, Status: %r\r\n",
12134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
12144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Tcp4TxToken.CompletionToken.Event = NULL;
12154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
12164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
12174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
12184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: TX event open\r\n",
12194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Tcp4TxToken.CompletionToken.Event ));
12204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
12214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
12224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Configure the local TCP port
12234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
12244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.TimeToLive = 255;
12254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.TypeOfService = 0;
12264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.ControlOption = NULL;
12274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;
12284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;
12294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;
12304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;
12314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;
12324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.StationPort = 0;
1233f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)  ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
1234f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );
1235f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );
1236f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );
1237b8a86b22291344499256f735c47c341d2a105986lpleahy    Tcp4ConfigData.AccessPoint.RemotePort = ntohs (((struct sockaddr_in *)&RemoteHostAddress)->sin_port);
12384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;
12394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;
12404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;
12414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;
12424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;
12434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = pTcp4Protocol->Configure ( pTcp4Protocol,
12444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                        &Tcp4ConfigData );
12454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
12467dc1329100c370992cdd430359512443bd1ee9f2darylm      DEBUG (( DEBUG_ERROR,
12474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to configure TCP port, Status: %r\r\n",
12484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
12494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
12504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
12514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
12524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: TCP4 port configured\r\n",
12534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pTcp4Protocol ));
12544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
12554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
12564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Connect to the remote TCP port
12574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
12584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = pTcp4Protocol->Connect ( pTcp4Protocol,
12594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                      &Tcp4ConnectToken );
12604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
12614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
12624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
12634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
12644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
12654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
12664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->WaitForEvent ( 1,
12674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 &Tcp4ConnectToken.CompletionToken.Event,
12684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                                 &Index );
12694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
12704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
12714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to wait for the connection, Status: %r\r\n",
12724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
12734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
12744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
12754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = Tcp4ConnectToken.CompletionToken.Status;
12764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
12774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_WARN,
12784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "WARNING - Failed to connect to the remote system, Status: %r\r\n",
12794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
12804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
12814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
12824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
12834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: TCP4 port connected\r\n",
12844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pTcp4Protocol ));
12854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    bTcp4Connected = TRUE;
12864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
12874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
12884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Display the connection
12894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1290f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
12914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Print ( L"Connected to %d.%d.%d.%d:%d\r\n",
12924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            pIpAddress[0],
12934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            pIpAddress[1],
12944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            pIpAddress[2],
12954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            pIpAddress[3],
1296b8a86b22291344499256f735c47c341d2a105986lpleahy            ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
12974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  } while ( 0 );
12984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
12994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( EFI_ERROR ( Status )) {
13004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
13014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Try again
13024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
13034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = EFI_SUCCESS;
13044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
13054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  else {
13064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
13074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Semd data until the connection breaks
13084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
13094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = Tcp4Send ( );
13104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
13114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
13134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
13144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
13154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
13164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
13174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
13204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Handle the timer callback
13214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [in] Event     Event that caused this callback
13234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [in] pContext  Context for this routine
13244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
13254684b66f261ffb74fa7575ed10df43cc0645a42fdarylmVOID
132653c31c516489d4cd46d20d59a3705720be3443f1lpleahyEFIAPI
13274684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTimerCallback (
13284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  IN EFI_EVENT Event,
13294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  IN VOID * pContext
13304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
13314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
1332f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 Average;
1333f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT64 BitsPerSecond;
1334f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT32 Index;
1335f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  UINT64 TotalBytes;
13364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
13384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Notify the other code of the timer tick
13394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
13404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  bTick = TRUE;
13414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
13434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Update the average bytes per second
13444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
1345f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy  if ( 0 != TotalBytesSent ) {
1346f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    BytesSent[ In ] = TotalBytesSent;
1347f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    TotalBytesSent = 0;
1348f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    In += 1;
1349f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    if ( DATA_SAMPLES <= In ) {
1350f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      In = 0;
1351f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    }
13524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
13544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Separate the samples
13554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1356f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    if ( DATA_SAMPLES == Samples ) {
13574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Print ( L"---------- Stable average ----------\r\n" );
13584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
13594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Samples += 1;
13604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
13614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1362f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //  Compute the data rate
1363f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
1364f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    TotalBytes = 0;
1365f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {
1366f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      TotalBytes += BytesSent[ Index ];
1367f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    }
1368f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );
1369f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    BitsPerSecond = Average * 8;
1370f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy
1371f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    //
13724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Display the data rate
13734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
1374f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    if (( RANGE_SWITCH >> 10 ) > Average ) {
1375f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1376f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Average,
1377f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              BitsPerSecond );
13784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
13794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
1380f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      BitsPerSecond /= 1000;
1381f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy      if ( RANGE_SWITCH > Average ) {
1382f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy        Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1383f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                Average >> 10,
1384f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                (( Average & 0x3ff ) * 1000 ) >> 10,
1385f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                BitsPerSecond );
13864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
13874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      else {
1388f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy        BitsPerSecond /= 1000;
13894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        Average >>= 10;
1390f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy        if ( RANGE_SWITCH > Average ) {
1391f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy          Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1392f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                  Average >> 10,
1393f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                  (( Average & 0x3ff ) * 1000 ) >> 10,
1394f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                  BitsPerSecond );
13954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        }
13964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        else {
1397f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy          BitsPerSecond /= 1000;
13984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          Average >>= 10;
1399f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy          if ( RANGE_SWITCH > Average ) {
1400f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1401f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                    Average >> 10,
1402f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                    (( Average & 0x3ff ) * 1000 ) >> 10,
1403f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                    BitsPerSecond );
14044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          }
14054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          else {
1406f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            BitsPerSecond /= 1000;
14074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            Average >>= 10;
1408f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy            if ( RANGE_SWITCH > Average ) {
1409f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1410f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      Average >> 10,
1411f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      (( Average & 0x3ff ) * 1000 ) >> 10,
1412f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      BitsPerSecond );
14134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            }
14144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            else {
1415f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              BitsPerSecond /= 1000;
14164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Average >>= 10;
1417f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy              Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1418f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      Average >> 10,
1419f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      (( Average & 0x3ff ) * 1000 ) >> 10,
1420f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy                      BitsPerSecond );
14214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            }
14224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm          }
14234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        }
14244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
14254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
14264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
14274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
14284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
14314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Create the timer
14324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The timer was successfully created
14344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        Timer initialization failed
14354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
14364684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
14374684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTimerCreate (
14384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
14394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
14404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
14414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Create the timer
14444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
14464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                              TPL_DATASOURCE,
14474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                              TimerCallback,
14484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                              NULL,
14494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                              &pTimer );
14504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( EFI_ERROR ( Status )) {
14514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_ERROR,
14524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "ERROR - Failed to allocate the timer event, Status: %r\r\n",
14534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              Status ));
14544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
14554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  else {
14564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    DEBUG (( DEBUG_INFO,
14574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              "0x%08x: Timer created\r\n",
14584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm              pTimer ));
14594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
14604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
14634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
14654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
14664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
14694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Stop the timer
14704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The timer was stopped successfully
14724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        The timer failed to stop
14734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
14744684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
14754684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTimerStop (
14764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
14774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
14784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
14794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Assume success
14824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_SUCCESS;
14844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
14854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Determine if the timer is running
14874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
14884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( bTimerRunning ) {
14894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
14904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Stop the timer
14914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
14924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->SetTimer ( pTimer,
14934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                             TimerCancel,
14944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                             0 );
14954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
14964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
14974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to stop the timer, Status: %r\r\n",
14984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
14994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
15004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
15014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
15024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Timer timer is now stopped
15034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
15044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      bTimerRunning = FALSE;
15054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
15064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Timer stopped\r\n",
15074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                pTimer ));
15084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
15094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
15104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
15134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
15154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
15164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
15194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Start the timer
15204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [in] Milliseconds  The number of milliseconds between timer callbacks
15224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The timer was successfully created
15244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        Timer initialization failed
15254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
15264684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
15274684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTimerStart (
15284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINTN Milliseconds
15294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
15304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
15314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
15324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  UINT64 TimeDelay;
15334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Stop the timer if necessary
15364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_SUCCESS;
15384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( bTimerRunning ) {
15394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = TimerStop ( );
15404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
15414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( !EFI_ERROR ( Status )) {
15424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
15434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Compute the new delay
15444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
15454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TimeDelay = Milliseconds;
15464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TimeDelay *= 1000 * 10;
15474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
15494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Start the timer
15504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
15514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->SetTimer ( pTimer,
15524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                             TimerPeriodic,
15534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                             TimeDelay );
15544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
15554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
15564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to start the timer, Status: %r\r\n",
15574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
15584684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
15594684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
15604684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
15614684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  The timer is now running
15624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
15634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      bTimerRunning = TRUE;
15644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
15654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        "0x%08x: Timer running\r\n",
15664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        pTimer ));
15674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
15684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
15694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
15724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
15744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
15754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
15784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Destroy the timer
15794684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  EFI_SUCCESS  The timer was destroyed successfully
15814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other        Failed to destroy the timer
15824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
15834684b66f261ffb74fa7575ed10df43cc0645a42fdarylmEFI_STATUS
15844684b66f261ffb74fa7575ed10df43cc0645a42fdarylmTimerDestroy (
15854684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
15864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
15874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
15884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15904684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Assume success
15914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Status = EFI_SUCCESS;
15934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
15944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Determine if the timer is running
15964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
15974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( bTimerRunning ) {
15984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
15994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Stop the timer
16004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = TimerStop ( );
16024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
16034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
16044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Done with this timer
16064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = gBS->CloseEvent ( pTimer );
16084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
16094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_ERROR,
16104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "ERROR - Failed to free the timer event, Status: %r\r\n",
16114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                Status ));
16124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
16134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    else {
16144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      DEBUG (( DEBUG_INFO,
16154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                "0x%08x: Timer Destroyed\r\n",
16164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm                pTimer ));
16174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      pTimer = NULL;
16184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
16194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
16204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
16224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
16234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
16244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
16254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
16264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm/**
16294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  Send data to the DataSink program to test a network's bandwidth.
16304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [in] Argc  The number of arguments
16324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @param [in] Argv  The argument value array
16334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  0        The application exited normally.
16354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  @retval  Other    An error occurred.
16364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm**/
16374684b66f261ffb74fa7575ed10df43cc0645a42fdarylmint
16384684b66f261ffb74fa7575ed10df43cc0645a42fdarylmmain (
16394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  IN int Argc,
16404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  IN char **Argv
16414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  )
16424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm{
16434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS (* pClose) ();
16444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS (* pOpen) ();
16454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  EFI_STATUS Status;
16464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  DEBUG (( DEBUG_INFO,
16484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            "DataSource starting\r\n" ));
16494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
16514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Validate the command line
16524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
165359bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  if ( 2 > Argc ) {
165459bc059327dd519619fa437c0d7c941e090cd8a3lpleahy    Print ( L"%s  <remote IP address> [Use TCP]\r\n", Argv[0] );
16554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    return -1;
16564684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
16574684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
165859bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  //
165959bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  //  Determine if TCP should be used
166059bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  //
166159bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  bTcp4 = (BOOLEAN)( 2 < Argc );
16624684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16634684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
16644684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Determine the support routines
16654684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
16664684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  if ( bTcp4 ) {
16674684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    pOpen = Tcp4Open;
16684684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    pClose = Tcp4Close;
16694684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    bTcp4Connecting = TRUE;
16704684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
16714684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  else {
16724684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    pOpen = SocketOpen;
16734684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    pClose = SocketClose;
16744684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
16754684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16764684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
16774684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Use for/break instead of goto
16784684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
167959bc059327dd519619fa437c0d7c941e090cd8a3lpleahy  for ( ; ; ) {
16804684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16814684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  No bytes sent so far
16824684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16834684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    TotalBytesSent = 0;
16844684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Samples = 0;
1685f6e5cdd5cfa100e777db38e5f7b26b7ffcf41330lpleahy    memset ( &BytesSent, 0, sizeof ( BytesSent ));
16864684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16874684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16884684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Get the IP address
16894684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
169059bc059327dd519619fa437c0d7c941e090cd8a3lpleahy    pRemoteHost = Argv[1];
16914684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = IpAddress ( );
16924684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
16934684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
16944684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
16954684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
16964684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16974684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Create the timer
16984684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
16994684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    bTick = TRUE;
17004684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    Status = TimerCreate ( );
17014684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    if ( EFI_ERROR ( Status )) {
17024684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      break;
17034684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    }
17044684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17054684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
17064684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Loop forever abusing the specified system
17074684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
17084684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    do {
17094684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
17104684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Start a timer to perform connection polling and display updates
17114684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
17124684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = TimerStart ( 2 * 1000 );
17134684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      if ( EFI_ERROR ( Status )) {
17144684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        break;
17154684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
17164684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17174684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
17184684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Open the network connection and send the data
17194684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
17204684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = pOpen ( );
17214684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      if ( EFI_ERROR ( Status )) {
17224684b66f261ffb74fa7575ed10df43cc0645a42fdarylm        break;
17234684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      }
17244684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17254684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
17264684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //  Done with the network connection
17274684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      //
17284684b66f261ffb74fa7575ed10df43cc0645a42fdarylm      Status = pClose ( );
17294684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    } while ( !EFI_ERROR ( Status ));
17304684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17314684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
17324684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  Close the network connection if necessary
17334684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
17344684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    pClose ( );
17354684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17364684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
17374684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //  All done
17384684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    //
17394684b66f261ffb74fa7575ed10df43cc0645a42fdarylm    break;
17404684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  }
17414684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17424684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
17434684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Stop the timer if necessary
17444684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
17454684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  TimerStop ( );
17464684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  TimerDestroy ( );
17474684b66f261ffb74fa7575ed10df43cc0645a42fdarylm
17484684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
17494684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //  Return the operation status
17504684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  //
17514684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  DEBUG (( DEBUG_INFO,
17524684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            "DataSource exiting, Status: %r\r\n",
17534684b66f261ffb74fa7575ed10df43cc0645a42fdarylm            Status ));
17544684b66f261ffb74fa7575ed10df43cc0645a42fdarylm  return Status;
17554684b66f261ffb74fa7575ed10df43cc0645a42fdarylm}
1756