2 Data source for network testing.
4 Copyright (c) 2011-2012, Intel Corporation. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiLib.h>
18 #include <netinet/in.h>
20 #include <Protocol/ServiceBinding.h>
21 #include <Protocol/Tcp4.h>
23 #include <sys/EfiSysCall.h>
25 #include <sys/socket.h>
31 #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples
32 #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges
33 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
34 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
35 #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples
37 #define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL
39 #define PACKET_SIZE 1448 ///< Size of data packets
40 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
51 BOOLEAN bTcp4
; ///< TRUE if TCP4 is being used
52 BOOLEAN bTcp4Connected
; ///< TRUE if connected to remote system
53 BOOLEAN bTcp4Connecting
; ///< TRUE while connection in progress
54 UINTN Tcp4Index
; ///< Index into handle array
55 EFI_HANDLE Tcp4Controller
; ///< Network controller handle
56 EFI_HANDLE Tcp4Handle
; ///< TCP4 port handle
57 EFI_TCP4_PROTOCOL
* pTcp4Protocol
; ///< TCP4 protocol pointer
58 EFI_SERVICE_BINDING_PROTOCOL
* pTcp4Service
; ///< TCP4 Service binding
59 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;///< TCP4 configuration data
60 EFI_TCP4_OPTION Tcp4Option
; ///< TCP4 port options
61 EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken
;///< Close control
62 EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken
; ///< Connection control
63 EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken
; ///< Listen control
64 EFI_TCP4_IO_TOKEN Tcp4TxToken
; ///< Normal data token
69 volatile BOOLEAN bTick
;
70 BOOLEAN bTimerRunning
;
74 // Remote IP Address Data
76 struct sockaddr_in6 RemoteHostAddress
;
82 UINT64 TotalBytesSent
;
85 UINT64 BytesSent
[ DATA_SAMPLES
];
86 UINT8 Buffer
[ DATA_BUFFER_SIZE
];
90 // Forward routine declarations
92 EFI_STATUS
TimerStart ( UINTN Milliseconds
);
96 Check for control C entered at console
98 @retval EFI_SUCCESS Control C not entered
99 @retval EFI_ABORTED Control C entered
108 // Assume no user intervention
110 Status
= EFI_SUCCESS
;
113 // Display user stop request
115 if ( EFI_ERROR ( Status
)) {
117 "User stop request!\r\n" ));
121 // Return the check status
130 @param [in] pDigit The address of the next digit
131 @param [out] pValue The address to receive the value
133 @return Returns the address of the separator
148 while (( '0' <= *pDigit
) && ( '9' >= *pDigit
)) {
150 // Make room for the new least significant digit
155 // Convert the digit from ASCII to binary
157 Value
+= *pDigit
- '0';
160 // Set the next digit
171 // Return the next separator
180 @retval EFI_SUCCESS The IP address is valid
181 @retval Other Failure to convert the IP address
187 struct sockaddr_in
* pRemoteAddress4
;
188 struct sockaddr_in6
* pRemoteAddress6
;
189 UINT32 RemoteAddress
;
203 Status
= EFI_INVALID_PARAMETER
;
206 // Get the port number
208 ZeroMem ( &RemoteHostAddress
, sizeof ( RemoteHostAddress
));
209 RemoteHostAddress
.sin6_port
= htons ( PcdGet16 ( DataSource_Port
));
210 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
211 pRemoteAddress6
= &RemoteHostAddress
;
214 // Convert the IP address from a string to a numeric value
216 if (( 4 == sscanf ( pRemoteHost
,
225 && ( 255 >= Value4
)) {
227 // Build the IPv4 address
229 pRemoteAddress4
->sin_len
= sizeof ( *pRemoteAddress4
);
230 pRemoteAddress4
->sin_family
= AF_INET
;
231 RemoteAddress
= Value1
235 pRemoteAddress4
->sin_addr
.s_addr
= RemoteAddress
;
236 Status
= EFI_SUCCESS
;
239 // Display the IP address
242 "%d.%d.%d.%d: Remote host IP address\r\n",
248 else if (( 8 == sscanf ( pRemoteHost
,
249 "%x:%x:%x:%x:%x:%x:%x:%x",
258 && ( 0xffff >= Value1
)
259 && ( 0xffff >= Value2
)
260 && ( 0xffff >= Value3
)
261 && ( 0xffff >= Value4
)
262 && ( 0xffff >= Value5
)
263 && ( 0xffff >= Value6
)
264 && ( 0xffff >= Value7
)
265 && ( 0xffff >= Value8
)) {
267 // Build the IPv6 address
269 pRemoteAddress6
->sin6_len
= sizeof ( *pRemoteAddress6
);
270 pRemoteAddress6
->sin6_family
= AF_INET6
;
271 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ] = (UINT8
)( Value1
>> 8 );
272 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ] = (UINT8
)Value1
;
273 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ] = (UINT8
)( Value2
>> 8 );
274 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ] = (UINT8
)Value2
;
275 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ] = (UINT8
)( Value3
>> 8 );
276 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ] = (UINT8
)Value3
;
277 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ] = (UINT8
)( Value4
>> 8 );
278 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ] = (UINT8
)Value4
;
279 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ] = (UINT8
)( Value5
>> 8 );
280 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ] = (UINT8
)Value5
;
281 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ] = (UINT8
)( Value6
>> 8 );
282 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ] = (UINT8
)Value6
;
283 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ] = (UINT8
)( Value7
>> 8 );
284 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ] = (UINT8
)Value7
;
285 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ] = (UINT8
)( Value8
>> 8 );
286 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ] = (UINT8
)Value8
;
287 Status
= EFI_SUCCESS
;
290 // Display the IP address
293 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
304 Print ( L
"ERROR - Invalid IP address!\r\n" );
308 // Return the operation status
317 @retval EFI_SUCCESS The application is running normally
318 @retval Other The user stopped the application
328 // Determine if the socket is open
330 Status
= EFI_DEVICE_ERROR
;
331 if ( -1 != Socket
) {
333 // Attempt to close the socket
335 CloseStatus
= close ( Socket
);
336 if ( 0 == CloseStatus
) {
338 "0x%08x: Socket closed\r\n",
341 Status
= EFI_SUCCESS
;
344 DEBUG (( DEBUG_ERROR
,
345 "ERROR: Failed to close socket, errno: %d\r\n",
351 // Return the operation status
360 @retval EFI_SUCCESS The application is running normally
361 @retval Other The user stopped the application
368 struct sockaddr_in
* pRemoteAddress4
;
369 struct sockaddr_in6
* pRemoteAddress6
;
373 // Display the connecting message
375 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
376 pRemoteAddress6
= &RemoteHostAddress
;
377 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
378 Print ( L
"Connecting to remote system %d.%d.%d.%d:%d\r\n",
379 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
380 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
381 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
382 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
383 ntohs ( pRemoteAddress4
->sin_port
));
386 Print ( L
"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
387 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
388 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
389 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
390 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
391 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
392 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
393 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
394 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
395 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
396 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
397 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
398 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
399 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
400 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
401 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
402 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
403 ntohs ( pRemoteAddress6
->sin6_port
));
407 // Connect to the remote system
409 Status
= EFI_SUCCESS
;
412 // Check for user stop request
415 Status
= ControlCCheck ( );
416 if ( EFI_ERROR ( Status
)) {
421 if ( EFI_ERROR ( Status
)) {
426 // Connect to the remote system
428 ConnectStatus
= connect ( Socket
,
429 (struct sockaddr
*)pRemoteAddress6
,
430 pRemoteAddress6
->sin6_len
);
431 if ( -1 != ConnectStatus
) {
432 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
433 Print ( L
"Connected to remote system %d.%d.%d.%d:%d\r\n",
434 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
435 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
436 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
437 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
438 ntohs ( pRemoteAddress4
->sin_port
));
441 Print ( L
"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
442 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
443 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
444 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
445 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
446 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
447 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
448 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
449 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
450 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
451 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
452 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
453 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
454 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
455 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
456 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
457 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
458 ntohs ( pRemoteAddress6
->sin6_port
));
460 Print ( L
"ConnectStatus: %d, Status: %r\r\n", ConnectStatus
, Status
);
464 // Close the socket and try again
466 if ( EAGAIN
!= errno
) {
467 Status
= EFI_NOT_STARTED
;
471 } while ( -1 == ConnectStatus
);
474 // Return the operation status
476 Print ( L
"SocketConnect returning Status: %r\r\n", Status
);
484 @param [in] Family Network family, AF_INET or AF_INET6
486 @retval EFI_SUCCESS The application is running normally
487 @retval Other The user stopped the application
497 // Loop creating the socket
500 "Creating the socket\r\n" ));
503 // Check for user stop request
505 Status
= ControlCCheck ( );
506 if ( EFI_ERROR ( Status
)) {
511 // Attempt to create the socket
513 Socket
= socket ( Family
,
516 if ( -1 != Socket
) {
518 "0x%08x: Socket created\r\n",
522 } while ( -1 == Socket
);
525 // Return the operation status
532 Send data over the socket
534 @retval EFI_SUCCESS The application is running normally
535 @retval Other The user stopped the application
548 TimerStart ( 1 * 1000 );
551 // Loop until the connection breaks or the user stops
555 // Check for user stop request
557 Status
= ControlCCheck ( );
558 if ( EFI_ERROR ( Status
)) {
565 BytesSent
= write ( Socket
, &Buffer
[0], sizeof ( Buffer
));
566 if ( -1 == BytesSent
) {
568 "ERROR: send failed, errno: %d\r\n",
570 Print ( L
"ERROR: send failed, errno: %d\r\n", errno
);
575 Status
= EFI_SUCCESS
;
580 Status
= EFI_NOT_STARTED
;
585 // Synchronize with the TimerCallback routine
587 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
590 // Account for the data sent
592 TotalBytesSent
+= BytesSent
;
595 // Release the TimerCallback routine synchronization
597 gBS
->RestoreTPL ( TplPrevious
);
598 } while ( !EFI_ERROR ( Status
));
601 // Return the operation status
608 Open the network connection and send the data.
610 @retval EFI_SUCCESS Continue looping
611 @retval other Stopped by user's Control-C input
621 // Use do/while and break instead of goto
625 // Wait for the network layer to initialize
627 Status
= SocketNew ( RemoteHostAddress
.sin6_family
);
628 if ( EFI_ERROR ( Status
)) {
633 // Wait for the remote network application to start
635 Status
= SocketConnect ( );
636 Print ( L
"Status: %r\r\n", Status
);
637 if ( EFI_NOT_STARTED
== Status
) {
638 Status
= SocketClose ( );
641 else if ( EFI_SUCCESS
!= Status
) {
649 // Send data until the connection breaks
651 Status
= SocketSend ( );
652 if ( EFI_ERROR ( Status
)) {
658 // Return the operation status
660 Print ( L
"Returning Status: %r\r\n", Status
);
666 Close the TCP connection
668 @retval EFI_SUCCESS The application is running normally
669 @retval Other The user stopped the application
682 if ( bTcp4Connected
) {
683 Tcp4CloseToken
.AbortOnClose
= TRUE
;
684 Status
= pTcp4Protocol
->Close ( pTcp4Protocol
,
686 if ( EFI_ERROR ( Status
)) {
687 DEBUG (( DEBUG_ERROR
,
688 "ERROR - Failed to start the TCP port close, Status: %r\r\n",
692 Status
= gBS
->WaitForEvent ( 1,
693 &Tcp4CloseToken
.CompletionToken
.Event
,
695 if ( EFI_ERROR ( Status
)) {
696 DEBUG (( DEBUG_ERROR
,
697 "ERROR - Failed to wait for close event, Status: %r\r\n",
701 Status
= Tcp4CloseToken
.CompletionToken
.Status
;
702 if ( EFI_ERROR ( Status
)) {
703 DEBUG (( DEBUG_ERROR
,
704 "ERROR - Failed to close the TCP port, Status: %r\r\n",
709 "0x%08x: TCP port closed\r\n",
711 bTcp4Connected
= FALSE
;
714 // Display the port closed message
716 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
717 Print ( L
"Closed connection to %d.%d.%d.%d:%d\r\n",
722 ntohs ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
729 // Release the events
731 if ( NULL
!= Tcp4TxToken
.CompletionToken
.Event
) {
732 Status
= gBS
->CloseEvent ( Tcp4TxToken
.CompletionToken
.Event
);
733 if ( !EFI_ERROR ( Status
)) {
735 "0x%08x: TX event closed\r\n",
736 Tcp4TxToken
.CompletionToken
.Event
));
737 Tcp4TxToken
.CompletionToken
.Event
= NULL
;
740 DEBUG (( DEBUG_ERROR
,
741 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
746 if ( NULL
!= Tcp4ListenToken
.CompletionToken
.Event
) {
747 Status
= gBS
->CloseEvent ( Tcp4ListenToken
.CompletionToken
.Event
);
748 if ( !EFI_ERROR ( Status
)) {
750 "0x%08x: Listen event closed\r\n",
751 Tcp4ListenToken
.CompletionToken
.Event
));
752 Tcp4ListenToken
.CompletionToken
.Event
= NULL
;
755 DEBUG (( DEBUG_ERROR
,
756 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
761 if ( NULL
!= Tcp4ConnectToken
.CompletionToken
.Event
) {
762 Status
= gBS
->CloseEvent ( Tcp4ConnectToken
.CompletionToken
.Event
);
763 if ( !EFI_ERROR ( Status
)) {
765 "0x%08x: Connect event closed\r\n",
766 Tcp4ConnectToken
.CompletionToken
.Event
));
767 Tcp4ConnectToken
.CompletionToken
.Event
= NULL
;
770 DEBUG (( DEBUG_ERROR
,
771 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
776 if ( NULL
!= Tcp4CloseToken
.CompletionToken
.Event
) {
777 Status
= gBS
->CloseEvent ( Tcp4CloseToken
.CompletionToken
.Event
);
778 if ( !EFI_ERROR ( Status
)) {
780 "0x%08x: Close event closed\r\n",
781 Tcp4CloseToken
.CompletionToken
.Event
));
782 Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
785 DEBUG (( DEBUG_ERROR
,
786 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
792 // Close the TCP protocol
794 if ( NULL
!= pTcp4Protocol
) {
795 Status
= gBS
->CloseProtocol ( Tcp4Handle
,
796 &gEfiTcp4ProtocolGuid
,
799 if ( EFI_ERROR ( Status
)) {
800 DEBUG (( DEBUG_ERROR
,
801 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
806 "0x%08x: TCP4 protocol closed\r\n",
808 pTcp4Protocol
= NULL
;
813 // Done with the TCP service
815 if ( NULL
!= Tcp4Handle
) {
816 Status
= pTcp4Service
->DestroyChild ( pTcp4Service
,
818 if ( EFI_ERROR ( Status
)) {
819 DEBUG (( DEBUG_ERROR
,
820 "ERROR - Failed to release TCP service handle, Status: %r\r\n",
825 "Ox%08x: TCP service closed\r\n",
832 // Close the service protocol
834 if ( NULL
!= pTcp4Service
) {
835 Status
= gBS
->CloseProtocol ( Tcp4Controller
,
836 &gEfiTcp4ServiceBindingProtocolGuid
,
839 if ( !EFI_ERROR ( Status
)) {
841 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
846 DEBUG (( DEBUG_ERROR
,
847 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
851 Tcp4Controller
= NULL
;
852 bTcp4Connecting
= TRUE
;
855 // Mark the connection as closed
857 Status
= EFI_SUCCESS
;
860 // Return the operation status
869 @retval EFI_SUCCESS Protocol found
870 @retval other Protocl not found
877 EFI_HANDLE
* pHandles
;
882 // Use do/while and break instead of goto
886 // Attempt to locate the next TCP adapter in the system
888 Status
= gBS
->LocateHandleBuffer ( ByProtocol
,
889 &gEfiTcp4ServiceBindingProtocolGuid
,
893 if ( EFI_ERROR ( Status
)) {
895 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
901 // Wrap the index if necessary
903 if ( HandleCount
<= Tcp4Index
) {
907 // Wait for the next timer tick
915 // Display the connecting message
917 if ( bTcp4Connecting
) {
918 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
919 Print ( L
"Connecting to %d.%d.%d.%d:%d\r\n",
924 ntohs ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
925 bTcp4Connecting
= FALSE
;
929 // Open the network controller's service protocol
931 Tcp4Controller
= pHandles
[ Tcp4Index
++ ];
932 Status
= gBS
->OpenProtocol (
934 &gEfiTcp4ServiceBindingProtocolGuid
,
935 (VOID
**) &pTcp4Service
,
938 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
939 if ( EFI_ERROR ( Status
)) {
940 DEBUG (( DEBUG_ERROR
,
941 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
943 Tcp4Controller
= NULL
;
947 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
951 // Connect to the TCP service
953 Status
= pTcp4Service
->CreateChild ( pTcp4Service
,
955 if ( EFI_ERROR ( Status
)) {
956 DEBUG (( DEBUG_ERROR
,
957 "ERROR - Failed to open TCP service, Status: %r\r\n",
963 "Ox%08x: TCP service opened\r\n",
967 // Locate the TCP protcol
969 Status
= gBS
->OpenProtocol ( Tcp4Handle
,
970 &gEfiTcp4ProtocolGuid
,
971 (VOID
**)&pTcp4Protocol
,
974 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
975 if ( EFI_ERROR ( Status
)) {
976 DEBUG (( DEBUG_ERROR
,
977 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",
979 pTcp4Protocol
= NULL
;
983 "0x%08x: TCP4 protocol opened\r\n",
988 // Release the handle buffer
990 gBS
->FreePool ( pHandles
);
993 // Return the operation status
1000 Send data over the TCP4 connection
1002 @retval EFI_SUCCESS The application is running normally
1003 @retval Other The user stopped the application
1010 EFI_TCP4_TRANSMIT_DATA Packet
;
1012 EFI_TPL TplPrevious
;
1015 // Restart the timer
1017 TimerStart ( 1 * 1000 );
1020 // Initialize the packet
1022 Packet
.DataLength
= sizeof ( Buffer
);
1023 Packet
.FragmentCount
= 1;
1024 Packet
.Push
= FALSE
;
1025 Packet
.Urgent
= FALSE
;
1026 Packet
.FragmentTable
[0].FragmentBuffer
= &Buffer
[0];
1027 Packet
.FragmentTable
[0].FragmentLength
= sizeof ( Buffer
);
1028 Tcp4TxToken
.Packet
.TxData
= &Packet
;
1031 // Loop until the connection breaks or the user stops
1035 // Check for user stop request
1037 Status
= ControlCCheck ( );
1038 if ( EFI_ERROR ( Status
)) {
1045 Status
= pTcp4Protocol
->Transmit ( pTcp4Protocol
,
1047 if ( EFI_ERROR ( Status
)) {
1048 DEBUG (( DEBUG_ERROR
,
1049 "ERROR - Failed to start the transmit, Status: %r\r\n",
1055 Status
= EFI_SUCCESS
;
1060 // Wait for the transmit to complete
1062 Status
= gBS
->WaitForEvent ( 1,
1063 &Tcp4TxToken
.CompletionToken
.Event
,
1065 if ( EFI_ERROR ( Status
)) {
1066 DEBUG (( DEBUG_ERROR
,
1067 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
1073 Status
= EFI_SUCCESS
;
1078 // Get the transmit status
1080 Status
= Tcp4TxToken
.CompletionToken
.Status
;
1081 if ( EFI_ERROR ( Status
)) {
1082 DEBUG (( DEBUG_WARN
,
1083 "WARNING - Failed the transmission, Status: %r\r\n",
1089 Status
= EFI_SUCCESS
;
1094 Status
= EFI_NOT_STARTED
;
1099 // Synchronize with the TimerCallback routine
1101 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
1104 // Account for the data sent
1106 TotalBytesSent
+= Packet
.DataLength
;
1109 // Release the TimerCallback routine synchronization
1111 gBS
->RestoreTPL ( TplPrevious
);
1112 } while ( !EFI_ERROR ( Status
));
1115 // Return the operation status
1122 Open the network connection and send the data.
1124 @retval EFI_SUCCESS Continue looping
1125 @retval other Stopped by user's Control-C input
1137 // Use do/while and break instead of goto
1141 // Locate the TCP protocol
1143 Status
= Tcp4Locate ( );
1144 if ( EFI_ERROR ( Status
)) {
1149 // Create the necessary events
1151 Status
= gBS
->CreateEvent ( 0,
1155 &Tcp4CloseToken
.CompletionToken
.Event
);
1156 if ( EFI_ERROR ( Status
)) {
1157 DEBUG (( DEBUG_ERROR
,
1158 "ERROR - Failed to create the close event, Status: %r\r\n",
1160 Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
1163 DEBUG (( DEBUG_INFO
,
1164 "0x%08x: Close event open\r\n",
1165 Tcp4CloseToken
.CompletionToken
.Event
));
1167 Status
= gBS
->CreateEvent ( 0,
1171 &Tcp4ConnectToken
.CompletionToken
.Event
);
1172 if ( EFI_ERROR ( Status
)) {
1173 DEBUG (( DEBUG_ERROR
,
1174 "ERROR - Failed to create the connect event, Status: %r\r\n",
1176 Tcp4ConnectToken
.CompletionToken
.Event
= NULL
;
1179 DEBUG (( DEBUG_INFO
,
1180 "0x%08x: Connect event open\r\n",
1181 Tcp4ConnectToken
.CompletionToken
.Event
));
1183 Status
= gBS
->CreateEvent ( 0,
1187 &Tcp4ListenToken
.CompletionToken
.Event
);
1188 if ( EFI_ERROR ( Status
)) {
1189 DEBUG (( DEBUG_ERROR
,
1190 "ERROR - Failed to create the listen event, Status: %r\r\n",
1192 Tcp4ListenToken
.CompletionToken
.Event
= NULL
;
1195 DEBUG (( DEBUG_INFO
,
1196 "0x%08x: Listen event open\r\n",
1197 Tcp4ListenToken
.CompletionToken
.Event
));
1199 Status
= gBS
->CreateEvent ( 0,
1203 &Tcp4TxToken
.CompletionToken
.Event
);
1204 if ( EFI_ERROR ( Status
)) {
1205 DEBUG (( DEBUG_ERROR
,
1206 "ERROR - Failed to create the TX event, Status: %r\r\n",
1208 Tcp4TxToken
.CompletionToken
.Event
= NULL
;
1211 DEBUG (( DEBUG_INFO
,
1212 "0x%08x: TX event open\r\n",
1213 Tcp4TxToken
.CompletionToken
.Event
));
1216 // Configure the local TCP port
1218 Tcp4ConfigData
.TimeToLive
= 255;
1219 Tcp4ConfigData
.TypeOfService
= 0;
1220 Tcp4ConfigData
.ControlOption
= NULL
;
1221 Tcp4ConfigData
.AccessPoint
.ActiveFlag
= TRUE
;
1222 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[0] = 0;
1223 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[1] = 0;
1224 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[2] = 0;
1225 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[3] = 0;
1226 Tcp4ConfigData
.AccessPoint
.StationPort
= 0;
1227 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0] = (UINT8
) ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
1228 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 8 );
1229 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 16 );
1230 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 24 );
1231 Tcp4ConfigData
.AccessPoint
.RemotePort
= ntohs (((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
);
1232 Tcp4ConfigData
.AccessPoint
.UseDefaultAddress
= TRUE
;
1233 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[0] = 0;
1234 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[1] = 0;
1235 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[2] = 0;
1236 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[3] = 0;
1237 Status
= pTcp4Protocol
->Configure ( pTcp4Protocol
,
1239 if ( EFI_ERROR ( Status
)) {
1240 DEBUG (( DEBUG_ERROR
,
1241 "ERROR - Failed to configure TCP port, Status: %r\r\n",
1245 DEBUG (( DEBUG_INFO
,
1246 "0x%08x: TCP4 port configured\r\n",
1250 // Connect to the remote TCP port
1252 Status
= pTcp4Protocol
->Connect ( pTcp4Protocol
,
1253 &Tcp4ConnectToken
);
1254 if ( EFI_ERROR ( Status
)) {
1255 DEBUG (( DEBUG_ERROR
,
1256 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
1260 Status
= gBS
->WaitForEvent ( 1,
1261 &Tcp4ConnectToken
.CompletionToken
.Event
,
1263 if ( EFI_ERROR ( Status
)) {
1264 DEBUG (( DEBUG_ERROR
,
1265 "ERROR - Failed to wait for the connection, Status: %r\r\n",
1269 Status
= Tcp4ConnectToken
.CompletionToken
.Status
;
1270 if ( EFI_ERROR ( Status
)) {
1271 DEBUG (( DEBUG_WARN
,
1272 "WARNING - Failed to connect to the remote system, Status: %r\r\n",
1276 DEBUG (( DEBUG_INFO
,
1277 "0x%08x: TCP4 port connected\r\n",
1279 bTcp4Connected
= TRUE
;
1282 // Display the connection
1284 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
1285 Print ( L
"Connected to %d.%d.%d.%d:%d\r\n",
1290 ntohs ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
1293 if ( EFI_ERROR ( Status
)) {
1297 Status
= EFI_SUCCESS
;
1301 // Semd data until the connection breaks
1303 Status
= Tcp4Send ( );
1307 // Return the operation status
1314 Handle the timer callback
1316 @param [in] Event Event that caused this callback
1317 @param [in] pContext Context for this routine
1327 UINT64 BitsPerSecond
;
1332 // Notify the other code of the timer tick
1337 // Update the average bytes per second
1339 if ( 0 != TotalBytesSent
) {
1340 BytesSent
[ In
] = TotalBytesSent
;
1343 if ( DATA_SAMPLES
<= In
) {
1348 // Separate the samples
1350 if ( DATA_SAMPLES
== Samples
) {
1351 Print ( L
"---------- Stable average ----------\r\n" );
1356 // Compute the data rate
1359 for ( Index
= 0; DATA_SAMPLES
> Index
; Index
++ ) {
1360 TotalBytes
+= BytesSent
[ Index
];
1362 Average
= (UINT32
)RShiftU64 ( TotalBytes
, DATA_SAMPLE_SHIFT
);
1363 BitsPerSecond
= Average
* 8;
1366 // Display the data rate
1368 if (( RANGE_SWITCH
>> 10 ) > Average
) {
1369 Print ( L
"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1374 BitsPerSecond
/= 1000;
1375 if ( RANGE_SWITCH
> Average
) {
1376 Print ( L
"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1378 (( Average
& 0x3ff ) * 1000 ) >> 10,
1382 BitsPerSecond
/= 1000;
1384 if ( RANGE_SWITCH
> Average
) {
1385 Print ( L
"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1387 (( Average
& 0x3ff ) * 1000 ) >> 10,
1391 BitsPerSecond
/= 1000;
1393 if ( RANGE_SWITCH
> Average
) {
1394 Print ( L
"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1396 (( Average
& 0x3ff ) * 1000 ) >> 10,
1400 BitsPerSecond
/= 1000;
1402 if ( RANGE_SWITCH
> Average
) {
1403 Print ( L
"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1405 (( Average
& 0x3ff ) * 1000 ) >> 10,
1409 BitsPerSecond
/= 1000;
1411 Print ( L
"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1413 (( Average
& 0x3ff ) * 1000 ) >> 10,
1427 @retval EFI_SUCCESS The timer was successfully created
1428 @retval Other Timer initialization failed
1439 Status
= gBS
->CreateEvent ( EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1444 if ( EFI_ERROR ( Status
)) {
1445 DEBUG (( DEBUG_ERROR
,
1446 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1450 DEBUG (( DEBUG_INFO
,
1451 "0x%08x: Timer created\r\n",
1456 // Return the operation status
1465 @retval EFI_SUCCESS The timer was stopped successfully
1466 @retval Other The timer failed to stop
1477 Status
= EFI_SUCCESS
;
1480 // Determine if the timer is running
1482 if ( bTimerRunning
) {
1486 Status
= gBS
->SetTimer ( pTimer
,
1489 if ( EFI_ERROR ( Status
)) {
1490 DEBUG (( DEBUG_ERROR
,
1491 "ERROR - Failed to stop the timer, Status: %r\r\n",
1496 // Timer timer is now stopped
1498 bTimerRunning
= FALSE
;
1499 DEBUG (( DEBUG_INFO
,
1500 "0x%08x: Timer stopped\r\n",
1506 // Return the operation status
1515 @param [in] Milliseconds The number of milliseconds between timer callbacks
1517 @retval EFI_SUCCESS The timer was successfully created
1518 @retval Other Timer initialization failed
1529 // Stop the timer if necessary
1531 Status
= EFI_SUCCESS
;
1532 if ( bTimerRunning
) {
1533 Status
= TimerStop ( );
1535 if ( !EFI_ERROR ( Status
)) {
1537 // Compute the new delay
1539 TimeDelay
= Milliseconds
;
1540 TimeDelay
*= 1000 * 10;
1545 Status
= gBS
->SetTimer ( pTimer
,
1548 if ( EFI_ERROR ( Status
)) {
1549 DEBUG (( DEBUG_ERROR
,
1550 "ERROR - Failed to start the timer, Status: %r\r\n",
1555 // The timer is now running
1557 bTimerRunning
= TRUE
;
1558 DEBUG (( DEBUG_INFO
,
1559 "0x%08x: Timer running\r\n",
1565 // Return the operation status
1574 @retval EFI_SUCCESS The timer was destroyed successfully
1575 @retval Other Failed to destroy the timer
1586 Status
= EFI_SUCCESS
;
1589 // Determine if the timer is running
1591 if ( bTimerRunning
) {
1595 Status
= TimerStop ( );
1597 if (( !EFI_ERROR ( Status
)) && ( NULL
!= pTimer
)) {
1599 // Done with this timer
1601 Status
= gBS
->CloseEvent ( pTimer
);
1602 if ( EFI_ERROR ( Status
)) {
1603 DEBUG (( DEBUG_ERROR
,
1604 "ERROR - Failed to free the timer event, Status: %r\r\n",
1608 DEBUG (( DEBUG_INFO
,
1609 "0x%08x: Timer Destroyed\r\n",
1616 // Return the operation status
1623 Send data to the DataSink program to test a network's bandwidth.
1625 @param [in] Argc The number of arguments
1626 @param [in] Argv The argument value array
1628 @retval 0 The application exited normally.
1629 @retval Other An error occurred.
1637 EFI_STATUS (* pClose
) ();
1638 EFI_STATUS (* pOpen
) ();
1641 DEBUG (( DEBUG_INFO
,
1642 "DataSource starting\r\n" ));
1645 // Validate the command line
1648 Print ( L
"%s <remote IP address> [Use TCP]\r\n", Argv
[0] );
1653 // Determine if TCP should be used
1655 bTcp4
= (BOOLEAN
)( 2 < Argc
);
1658 // Determine the support routines
1663 bTcp4Connecting
= TRUE
;
1667 pClose
= SocketClose
;
1671 // Use for/break instead of goto
1675 // No bytes sent so far
1679 memset ( &BytesSent
, 0, sizeof ( BytesSent
));
1682 // Get the IP address
1684 pRemoteHost
= Argv
[1];
1685 Status
= IpAddress ( );
1686 if ( EFI_ERROR ( Status
)) {
1694 Status
= TimerCreate ( );
1695 if ( EFI_ERROR ( Status
)) {
1700 // Loop forever abusing the specified system
1704 // Start a timer to perform connection polling and display updates
1706 Status
= TimerStart ( 2 * 1000 );
1707 if ( EFI_ERROR ( Status
)) {
1712 // Open the network connection and send the data
1715 if ( EFI_ERROR ( Status
)) {
1720 // Done with the network connection
1722 Status
= pClose ( );
1723 } while ( !EFI_ERROR ( Status
));
1726 // Close the network connection if necessary
1737 // Stop the timer if necessary
1743 // Return the operation status
1745 DEBUG (( DEBUG_INFO
,
1746 "DataSource exiting, Status: %r\r\n",