2 Data source for network testing.
4 Copyright (c) 2011, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiLib.h>
24 #include <netinet/in.h>
26 #include <Protocol/ServiceBinding.h>
27 #include <Protocol/Tcp4.h>
29 #include <sys/EfiSysCall.h>
31 #include <sys/socket.h>
37 #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples
38 #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges
39 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
40 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
41 #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples
43 #define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL
45 #define PACKET_SIZE 1448 ///< Size of data packets
46 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
57 BOOLEAN bTcp4
; ///< TRUE if TCP4 is being used
58 BOOLEAN bTcp4Connected
; ///< TRUE if connected to remote system
59 BOOLEAN bTcp4Connecting
; ///< TRUE while connection in progress
60 UINTN Tcp4Index
; ///< Index into handle array
61 EFI_HANDLE Tcp4Controller
; ///< Network controller handle
62 EFI_HANDLE Tcp4Handle
; ///< TCP4 port handle
63 EFI_TCP4_PROTOCOL
* pTcp4Protocol
; ///< TCP4 protocol pointer
64 EFI_SERVICE_BINDING_PROTOCOL
* pTcp4Service
; ///< TCP4 Service binding
65 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;///< TCP4 configuration data
66 EFI_TCP4_OPTION Tcp4Option
; ///< TCP4 port options
67 EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken
;///< Close control
68 EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken
; ///< Connection control
69 EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken
; ///< Listen control
70 EFI_TCP4_IO_TOKEN Tcp4TxToken
; ///< Normal data token
75 volatile BOOLEAN bTick
;
76 BOOLEAN bTimerRunning
;
80 // Remote IP Address Data
82 struct sockaddr_in6 RemoteHostAddress
;
88 UINT64 TotalBytesSent
;
91 UINT64 BytesSent
[ DATA_SAMPLES
];
92 UINT8 Buffer
[ DATA_BUFFER_SIZE
];
96 // Forward routine declarations
98 EFI_STATUS
TimerStart ( UINTN Milliseconds
);
102 Check for control C entered at console
104 @retval EFI_SUCCESS Control C not entered
105 @retval EFI_ABORTED Control C entered
114 // Assume no user intervention
116 Status
= EFI_SUCCESS
;
119 // Display user stop request
121 if ( EFI_ERROR ( Status
)) {
123 "User stop request!\r\n" ));
127 // Return the check status
136 @param [in] pDigit The address of the next digit
137 @param [out] pValue The address to receive the value
139 @return Returns the address of the separator
154 while (( '0' <= *pDigit
) && ( '9' >= *pDigit
)) {
156 // Make room for the new least significant digit
161 // Convert the digit from ASCII to binary
163 Value
+= *pDigit
- '0';
166 // Set the next digit
177 // Return the next separator
186 @retval EFI_SUCCESS The IP address is valid
187 @retval Other Failure to convert the IP address
193 struct sockaddr_in
* pRemoteAddress4
;
194 struct sockaddr_in6
* pRemoteAddress6
;
195 UINT32 RemoteAddress
;
209 Status
= EFI_INVALID_PARAMETER
;
212 // Get the port number
214 ZeroMem ( &RemoteHostAddress
, sizeof ( RemoteHostAddress
));
215 RemoteHostAddress
.sin6_port
= htons ( PcdGet16 ( DataSource_Port
));
216 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
217 pRemoteAddress6
= &RemoteHostAddress
;
220 // Convert the IP address from a string to a numeric value
222 if (( 4 == sscanf ( pRemoteHost
,
231 && ( 255 >= Value4
)) {
233 // Build the IPv4 address
235 pRemoteAddress4
->sin_len
= sizeof ( *pRemoteAddress4
);
236 pRemoteAddress4
->sin_family
= AF_INET
;
237 RemoteAddress
= Value1
241 pRemoteAddress4
->sin_addr
.s_addr
= RemoteAddress
;
242 Status
= EFI_SUCCESS
;
245 // Display the IP address
248 "%d.%d.%d.%d: Remote host IP address\r\n",
254 else if (( 8 == sscanf ( pRemoteHost
,
255 "%x:%x:%x:%x:%x:%x:%x:%x",
264 && ( 0xffff >= Value1
)
265 && ( 0xffff >= Value2
)
266 && ( 0xffff >= Value3
)
267 && ( 0xffff >= Value4
)
268 && ( 0xffff >= Value5
)
269 && ( 0xffff >= Value6
)
270 && ( 0xffff >= Value7
)
271 && ( 0xffff >= Value8
)) {
273 // Build the IPv6 address
275 pRemoteAddress6
->sin6_len
= sizeof ( *pRemoteAddress6
);
276 pRemoteAddress6
->sin6_family
= AF_INET6
;
277 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ] = (UINT8
)( Value1
>> 8 );
278 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ] = (UINT8
)Value1
;
279 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ] = (UINT8
)( Value2
>> 8 );
280 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ] = (UINT8
)Value2
;
281 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ] = (UINT8
)( Value3
>> 8 );
282 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ] = (UINT8
)Value3
;
283 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ] = (UINT8
)( Value4
>> 8 );
284 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ] = (UINT8
)Value4
;
285 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ] = (UINT8
)( Value5
>> 8 );
286 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ] = (UINT8
)Value5
;
287 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ] = (UINT8
)( Value6
>> 8 );
288 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ] = (UINT8
)Value6
;
289 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ] = (UINT8
)( Value7
>> 8 );
290 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ] = (UINT8
)Value7
;
291 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ] = (UINT8
)( Value8
>> 8 );
292 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ] = (UINT8
)Value8
;
293 Status
= EFI_SUCCESS
;
296 // Display the IP address
299 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
310 Print ( L
"ERROR - Invalid IP address!\r\n" );
314 // Return the operation status
323 @retval EFI_SUCCESS The application is running normally
324 @retval Other The user stopped the application
334 // Determine if the socket is open
336 Status
= EFI_DEVICE_ERROR
;
337 if ( -1 != Socket
) {
339 // Attempt to close the socket
341 CloseStatus
= close ( Socket
);
342 if ( 0 == CloseStatus
) {
344 "0x%08x: Socket closed\r\n",
347 Status
= EFI_SUCCESS
;
350 DEBUG (( DEBUG_ERROR
,
351 "ERROR: Failed to close socket, errno: %d\r\n",
357 // Return the operation status
366 @retval EFI_SUCCESS The application is running normally
367 @retval Other The user stopped the application
374 struct sockaddr_in
* pRemoteAddress4
;
375 struct sockaddr_in6
* pRemoteAddress6
;
379 // Display the connecting message
381 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
382 pRemoteAddress6
= &RemoteHostAddress
;
383 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
384 Print ( L
"Connecting to remote system %d.%d.%d.%d:%d\r\n",
385 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
386 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
387 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
388 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
389 htons ( pRemoteAddress4
->sin_port
));
392 Print ( L
"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
393 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
394 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
395 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
396 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
397 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
398 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
399 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
400 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
401 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
402 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
403 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
404 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
405 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
406 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
407 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
408 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
409 htons ( pRemoteAddress6
->sin6_port
));
413 // Connect to the remote system
415 Status
= EFI_SUCCESS
;
418 // Check for user stop request
421 Status
= ControlCCheck ( );
422 if ( EFI_ERROR ( Status
)) {
427 if ( EFI_ERROR ( Status
)) {
432 // Connect to the remote system
434 ConnectStatus
= connect ( Socket
,
435 (struct sockaddr
*)pRemoteAddress6
,
436 pRemoteAddress6
->sin6_len
);
437 if ( -1 != ConnectStatus
) {
438 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
439 Print ( L
"Connected to remote system %d.%d.%d.%d:%d\r\n",
440 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
441 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
442 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
443 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
444 htons ( pRemoteAddress4
->sin_port
));
447 Print ( L
"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
448 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
449 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
450 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
451 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
452 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
453 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
454 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
455 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
456 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
457 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
458 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
459 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
460 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
461 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
462 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
463 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
464 htons ( pRemoteAddress6
->sin6_port
));
469 // Close the socket and try again
471 if ( EAGAIN
!= errno
) {
472 Status
= EFI_NOT_STARTED
;
476 } while ( -1 == ConnectStatus
);
479 // Return the operation status
488 @param [in] Family Network family, AF_INET or AF_INET6
490 @retval EFI_SUCCESS The application is running normally
491 @retval Other The user stopped the application
501 // Loop creating the socket
504 "Creating the socket\r\n" ));
507 // Check for user stop request
509 Status
= ControlCCheck ( );
510 if ( EFI_ERROR ( Status
)) {
515 // Attempt to create the socket
517 Socket
= socket ( Family
,
520 if ( -1 != Socket
) {
522 "0x%08x: Socket created\r\n",
526 } while ( -1 == Socket
);
529 // Return the operation status
536 Send data over the socket
538 @retval EFI_SUCCESS The application is running normally
539 @retval Other The user stopped the application
552 TimerStart ( 1 * 1000 );
555 // Loop until the connection breaks or the user stops
559 // Check for user stop request
561 Status
= ControlCCheck ( );
562 if ( EFI_ERROR ( Status
)) {
569 BytesSent
= write ( Socket
, &Buffer
[0], sizeof ( Buffer
));
570 if ( -1 == BytesSent
) {
572 "ERROR: send failed, errno: %d\r\n",
578 Status
= EFI_SUCCESS
;
583 Status
= EFI_NOT_STARTED
;
588 // Synchronize with the TimerCallback routine
590 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
593 // Account for the data sent
595 TotalBytesSent
+= BytesSent
;
598 // Release the TimerCallback routine synchronization
600 gBS
->RestoreTPL ( TplPrevious
);
601 } while ( !EFI_ERROR ( Status
));
604 // Return the operation status
611 Open the network connection and send the data.
613 @retval EFI_SUCCESS Continue looping
614 @retval other Stopped by user's Control-C input
624 // Use do/while and break instead of goto
628 // Wait for the network layer to initialize
630 Status
= SocketNew ( RemoteHostAddress
.sin6_family
);
631 if ( EFI_ERROR ( Status
)) {
636 // Wait for the remote network application to start
638 Status
= SocketConnect ( );
639 if ( EFI_NOT_STARTED
== Status
) {
640 Status
= SocketClose ( );
643 else if ( EFI_SUCCESS
!= Status
) {
651 // Send data until the connection breaks
653 Status
= SocketSend ( );
654 if ( EFI_ERROR ( Status
)) {
660 // Return the operation status
667 Close the TCP connection
669 @retval EFI_SUCCESS The application is running normally
670 @retval Other The user stopped the application
683 if ( bTcp4Connected
) {
684 Tcp4CloseToken
.AbortOnClose
= TRUE
;
685 Status
= pTcp4Protocol
->Close ( pTcp4Protocol
,
687 if ( EFI_ERROR ( Status
)) {
688 DEBUG (( DEBUG_ERROR
,
689 "ERROR - Failed to start the TCP port close, Status: %r\r\n",
693 Status
= gBS
->WaitForEvent ( 1,
694 &Tcp4CloseToken
.CompletionToken
.Event
,
696 if ( EFI_ERROR ( Status
)) {
697 DEBUG (( DEBUG_ERROR
,
698 "ERROR - Failed to wait for close event, Status: %r\r\n",
702 Status
= Tcp4CloseToken
.CompletionToken
.Status
;
703 if ( EFI_ERROR ( Status
)) {
704 DEBUG (( DEBUG_ERROR
,
705 "ERROR - Failed to close the TCP port, Status: %r\r\n",
710 "0x%08x: TCP port closed\r\n",
712 bTcp4Connected
= FALSE
;
715 // Display the port closed message
717 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
718 Print ( L
"Closed connection to %d.%d.%d.%d:%d\r\n",
723 htons ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
730 // Release the events
732 if ( NULL
!= Tcp4TxToken
.CompletionToken
.Event
) {
733 Status
= gBS
->CloseEvent ( Tcp4TxToken
.CompletionToken
.Event
);
734 if ( !EFI_ERROR ( Status
)) {
736 "0x%08x: TX event closed\r\n",
737 Tcp4TxToken
.CompletionToken
.Event
));
738 Tcp4TxToken
.CompletionToken
.Event
= NULL
;
741 DEBUG (( DEBUG_ERROR
,
742 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
747 if ( NULL
!= Tcp4ListenToken
.CompletionToken
.Event
) {
748 Status
= gBS
->CloseEvent ( Tcp4ListenToken
.CompletionToken
.Event
);
749 if ( !EFI_ERROR ( Status
)) {
751 "0x%08x: Listen event closed\r\n",
752 Tcp4ListenToken
.CompletionToken
.Event
));
753 Tcp4ListenToken
.CompletionToken
.Event
= NULL
;
756 DEBUG (( DEBUG_ERROR
,
757 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
762 if ( NULL
!= Tcp4ConnectToken
.CompletionToken
.Event
) {
763 Status
= gBS
->CloseEvent ( Tcp4ConnectToken
.CompletionToken
.Event
);
764 if ( !EFI_ERROR ( Status
)) {
766 "0x%08x: Connect event closed\r\n",
767 Tcp4ConnectToken
.CompletionToken
.Event
));
768 Tcp4ConnectToken
.CompletionToken
.Event
= NULL
;
771 DEBUG (( DEBUG_ERROR
,
772 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
777 if ( NULL
!= Tcp4CloseToken
.CompletionToken
.Event
) {
778 Status
= gBS
->CloseEvent ( Tcp4CloseToken
.CompletionToken
.Event
);
779 if ( !EFI_ERROR ( Status
)) {
781 "0x%08x: Close event closed\r\n",
782 Tcp4CloseToken
.CompletionToken
.Event
));
783 Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
786 DEBUG (( DEBUG_ERROR
,
787 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
793 // Close the TCP protocol
795 if ( NULL
!= pTcp4Protocol
) {
796 Status
= gBS
->CloseProtocol ( Tcp4Handle
,
797 &gEfiTcp4ProtocolGuid
,
800 if ( EFI_ERROR ( Status
)) {
801 DEBUG (( DEBUG_ERROR
,
802 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
807 "0x%08x: TCP4 protocol closed\r\n",
809 pTcp4Protocol
= NULL
;
814 // Done with the TCP service
816 if ( NULL
!= Tcp4Handle
) {
817 Status
= pTcp4Service
->DestroyChild ( pTcp4Service
,
819 if ( EFI_ERROR ( Status
)) {
820 DEBUG (( DEBUG_ERROR
,
821 "ERROR - Failed to release TCP service handle, Status: %r\r\n",
826 "Ox%08x: TCP service closed\r\n",
833 // Close the service protocol
835 if ( NULL
!= pTcp4Service
) {
836 Status
= gBS
->CloseProtocol ( Tcp4Controller
,
837 &gEfiTcp4ServiceBindingProtocolGuid
,
840 if ( !EFI_ERROR ( Status
)) {
842 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
847 DEBUG (( DEBUG_ERROR
,
848 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
852 Tcp4Controller
= NULL
;
853 bTcp4Connecting
= TRUE
;
856 // Mark the connection as closed
858 Status
= EFI_SUCCESS
;
861 // Return the operation status
870 @retval EFI_SUCCESS Protocol found
871 @retval other Protocl not found
878 EFI_HANDLE
* pHandles
;
883 // Use do/while and break instead of goto
887 // Attempt to locate the next TCP adapter in the system
889 Status
= gBS
->LocateHandleBuffer ( ByProtocol
,
890 &gEfiTcp4ServiceBindingProtocolGuid
,
894 if ( EFI_ERROR ( Status
)) {
896 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
902 // Wrap the index if necessary
904 if ( HandleCount
<= Tcp4Index
) {
908 // Wait for the next timer tick
916 // Display the connecting message
918 if ( bTcp4Connecting
) {
919 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
920 Print ( L
"Connecting to %d.%d.%d.%d:%d\r\n",
925 htons ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
926 bTcp4Connecting
= FALSE
;
930 // Open the network controller's service protocol
932 Tcp4Controller
= pHandles
[ Tcp4Index
++ ];
933 Status
= gBS
->OpenProtocol (
935 &gEfiTcp4ServiceBindingProtocolGuid
,
936 (VOID
**) &pTcp4Service
,
939 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
940 if ( EFI_ERROR ( Status
)) {
941 DEBUG (( DEBUG_ERROR
,
942 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
944 Tcp4Controller
= NULL
;
948 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
952 // Connect to the TCP service
954 Status
= pTcp4Service
->CreateChild ( pTcp4Service
,
956 if ( EFI_ERROR ( Status
)) {
957 DEBUG (( DEBUG_ERROR
,
958 "ERROR - Failed to open TCP service, Status: %r\r\n",
964 "Ox%08x: TCP service opened\r\n",
968 // Locate the TCP protcol
970 Status
= gBS
->OpenProtocol ( Tcp4Handle
,
971 &gEfiTcp4ProtocolGuid
,
972 (VOID
**)&pTcp4Protocol
,
975 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
976 if ( EFI_ERROR ( Status
)) {
977 DEBUG (( DEBUG_ERROR
,
978 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",
980 pTcp4Protocol
= NULL
;
984 "0x%08x: TCP4 protocol opened\r\n",
989 // Release the handle buffer
991 gBS
->FreePool ( pHandles
);
994 // Return the operation status
1001 Send data over the TCP4 connection
1003 @retval EFI_SUCCESS The application is running normally
1004 @retval Other The user stopped the application
1011 EFI_TCP4_TRANSMIT_DATA Packet
;
1013 EFI_TPL TplPrevious
;
1016 // Restart the timer
1018 TimerStart ( 1 * 1000 );
1021 // Initialize the packet
1023 Packet
.DataLength
= sizeof ( Buffer
);
1024 Packet
.FragmentCount
= 1;
1025 Packet
.Push
= FALSE
;
1026 Packet
.Urgent
= FALSE
;
1027 Packet
.FragmentTable
[0].FragmentBuffer
= &Buffer
[0];
1028 Packet
.FragmentTable
[0].FragmentLength
= sizeof ( Buffer
);
1029 Tcp4TxToken
.Packet
.TxData
= &Packet
;
1032 // Loop until the connection breaks or the user stops
1036 // Check for user stop request
1038 Status
= ControlCCheck ( );
1039 if ( EFI_ERROR ( Status
)) {
1046 Status
= pTcp4Protocol
->Transmit ( pTcp4Protocol
,
1048 if ( EFI_ERROR ( Status
)) {
1049 DEBUG (( DEBUG_ERROR
,
1050 "ERROR - Failed to start the transmit, Status: %r\r\n",
1056 Status
= EFI_SUCCESS
;
1061 // Wait for the transmit to complete
1063 Status
= gBS
->WaitForEvent ( 1,
1064 &Tcp4TxToken
.CompletionToken
.Event
,
1066 if ( EFI_ERROR ( Status
)) {
1067 DEBUG (( DEBUG_ERROR
,
1068 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
1074 Status
= EFI_SUCCESS
;
1079 // Get the transmit status
1081 Status
= Tcp4TxToken
.CompletionToken
.Status
;
1082 if ( EFI_ERROR ( Status
)) {
1083 DEBUG (( DEBUG_WARN
,
1084 "WARNING - Failed the transmission, Status: %r\r\n",
1090 Status
= EFI_SUCCESS
;
1095 Status
= EFI_NOT_STARTED
;
1100 // Synchronize with the TimerCallback routine
1102 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
1105 // Account for the data sent
1107 TotalBytesSent
+= Packet
.DataLength
;
1110 // Release the TimerCallback routine synchronization
1112 gBS
->RestoreTPL ( TplPrevious
);
1113 } while ( !EFI_ERROR ( Status
));
1116 // Return the operation status
1123 Open the network connection and send the data.
1125 @retval EFI_SUCCESS Continue looping
1126 @retval other Stopped by user's Control-C input
1138 // Use do/while and break instead of goto
1142 // Locate the TCP protocol
1144 Status
= Tcp4Locate ( );
1145 if ( EFI_ERROR ( Status
)) {
1150 // Create the necessary events
1152 Status
= gBS
->CreateEvent ( 0,
1156 &Tcp4CloseToken
.CompletionToken
.Event
);
1157 if ( EFI_ERROR ( Status
)) {
1158 DEBUG (( DEBUG_ERROR
,
1159 "ERROR - Failed to create the close event, Status: %r\r\n",
1161 Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
1164 DEBUG (( DEBUG_INFO
,
1165 "0x%08x: Close event open\r\n",
1166 Tcp4CloseToken
.CompletionToken
.Event
));
1168 Status
= gBS
->CreateEvent ( 0,
1172 &Tcp4ConnectToken
.CompletionToken
.Event
);
1173 if ( EFI_ERROR ( Status
)) {
1174 DEBUG (( DEBUG_ERROR
,
1175 "ERROR - Failed to create the connect event, Status: %r\r\n",
1177 Tcp4ConnectToken
.CompletionToken
.Event
= NULL
;
1180 DEBUG (( DEBUG_INFO
,
1181 "0x%08x: Connect event open\r\n",
1182 Tcp4ConnectToken
.CompletionToken
.Event
));
1184 Status
= gBS
->CreateEvent ( 0,
1188 &Tcp4ListenToken
.CompletionToken
.Event
);
1189 if ( EFI_ERROR ( Status
)) {
1190 DEBUG (( DEBUG_ERROR
,
1191 "ERROR - Failed to create the listen event, Status: %r\r\n",
1193 Tcp4ListenToken
.CompletionToken
.Event
= NULL
;
1196 DEBUG (( DEBUG_INFO
,
1197 "0x%08x: Listen event open\r\n",
1198 Tcp4ListenToken
.CompletionToken
.Event
));
1200 Status
= gBS
->CreateEvent ( 0,
1204 &Tcp4TxToken
.CompletionToken
.Event
);
1205 if ( EFI_ERROR ( Status
)) {
1206 DEBUG (( DEBUG_ERROR
,
1207 "ERROR - Failed to create the TX event, Status: %r\r\n",
1209 Tcp4TxToken
.CompletionToken
.Event
= NULL
;
1212 DEBUG (( DEBUG_INFO
,
1213 "0x%08x: TX event open\r\n",
1214 Tcp4TxToken
.CompletionToken
.Event
));
1217 // Configure the local TCP port
1219 Tcp4ConfigData
.TimeToLive
= 255;
1220 Tcp4ConfigData
.TypeOfService
= 0;
1221 Tcp4ConfigData
.ControlOption
= NULL
;
1222 Tcp4ConfigData
.AccessPoint
.ActiveFlag
= TRUE
;
1223 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[0] = 0;
1224 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[1] = 0;
1225 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[2] = 0;
1226 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[3] = 0;
1227 Tcp4ConfigData
.AccessPoint
.StationPort
= 0;
1228 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0] = (UINT8
) ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
1229 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 8 );
1230 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 16 );
1231 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 24 );
1232 Tcp4ConfigData
.AccessPoint
.RemotePort
= ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
;
1233 Tcp4ConfigData
.AccessPoint
.UseDefaultAddress
= TRUE
;
1234 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[0] = 0;
1235 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[1] = 0;
1236 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[2] = 0;
1237 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[3] = 0;
1238 Status
= pTcp4Protocol
->Configure ( pTcp4Protocol
,
1240 if ( EFI_ERROR ( Status
)) {
1241 DEBUG (( DEBUG_ERROR
,
1242 "ERROR - Failed to configure TCP port, Status: %r\r\n",
1246 DEBUG (( DEBUG_INFO
,
1247 "0x%08x: TCP4 port configured\r\n",
1251 // Connect to the remote TCP port
1253 Status
= pTcp4Protocol
->Connect ( pTcp4Protocol
,
1254 &Tcp4ConnectToken
);
1255 if ( EFI_ERROR ( Status
)) {
1256 DEBUG (( DEBUG_ERROR
,
1257 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
1261 Status
= gBS
->WaitForEvent ( 1,
1262 &Tcp4ConnectToken
.CompletionToken
.Event
,
1264 if ( EFI_ERROR ( Status
)) {
1265 DEBUG (( DEBUG_ERROR
,
1266 "ERROR - Failed to wait for the connection, Status: %r\r\n",
1270 Status
= Tcp4ConnectToken
.CompletionToken
.Status
;
1271 if ( EFI_ERROR ( Status
)) {
1272 DEBUG (( DEBUG_WARN
,
1273 "WARNING - Failed to connect to the remote system, Status: %r\r\n",
1277 DEBUG (( DEBUG_INFO
,
1278 "0x%08x: TCP4 port connected\r\n",
1280 bTcp4Connected
= TRUE
;
1283 // Display the connection
1285 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
1286 Print ( L
"Connected to %d.%d.%d.%d:%d\r\n",
1291 htons ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
1294 if ( EFI_ERROR ( Status
)) {
1298 Status
= EFI_SUCCESS
;
1302 // Semd data until the connection breaks
1304 Status
= Tcp4Send ( );
1308 // Return the operation status
1315 Handle the timer callback
1317 @param [in] Event Event that caused this callback
1318 @param [in] pContext Context for this routine
1328 UINT64 BitsPerSecond
;
1333 // Notify the other code of the timer tick
1338 // Update the average bytes per second
1340 if ( 0 != TotalBytesSent
) {
1341 BytesSent
[ In
] = TotalBytesSent
;
1344 if ( DATA_SAMPLES
<= In
) {
1349 // Separate the samples
1351 if ( DATA_SAMPLES
== Samples
) {
1352 Print ( L
"---------- Stable average ----------\r\n" );
1357 // Compute the data rate
1360 for ( Index
= 0; DATA_SAMPLES
> Index
; Index
++ ) {
1361 TotalBytes
+= BytesSent
[ Index
];
1363 Average
= (UINT32
)RShiftU64 ( TotalBytes
, DATA_SAMPLE_SHIFT
);
1364 BitsPerSecond
= Average
* 8;
1367 // Display the data rate
1369 if (( RANGE_SWITCH
>> 10 ) > Average
) {
1370 Print ( L
"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1375 BitsPerSecond
/= 1000;
1376 if ( RANGE_SWITCH
> Average
) {
1377 Print ( L
"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1379 (( Average
& 0x3ff ) * 1000 ) >> 10,
1383 BitsPerSecond
/= 1000;
1385 if ( RANGE_SWITCH
> Average
) {
1386 Print ( L
"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1388 (( Average
& 0x3ff ) * 1000 ) >> 10,
1392 BitsPerSecond
/= 1000;
1394 if ( RANGE_SWITCH
> Average
) {
1395 Print ( L
"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1397 (( Average
& 0x3ff ) * 1000 ) >> 10,
1401 BitsPerSecond
/= 1000;
1403 if ( RANGE_SWITCH
> Average
) {
1404 Print ( L
"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1406 (( Average
& 0x3ff ) * 1000 ) >> 10,
1410 BitsPerSecond
/= 1000;
1412 Print ( L
"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1414 (( Average
& 0x3ff ) * 1000 ) >> 10,
1428 @retval EFI_SUCCESS The timer was successfully created
1429 @retval Other Timer initialization failed
1440 Status
= gBS
->CreateEvent ( EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1445 if ( EFI_ERROR ( Status
)) {
1446 DEBUG (( DEBUG_ERROR
,
1447 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1451 DEBUG (( DEBUG_INFO
,
1452 "0x%08x: Timer created\r\n",
1457 // Return the operation status
1466 @retval EFI_SUCCESS The timer was stopped successfully
1467 @retval Other The timer failed to stop
1478 Status
= EFI_SUCCESS
;
1481 // Determine if the timer is running
1483 if ( bTimerRunning
) {
1487 Status
= gBS
->SetTimer ( pTimer
,
1490 if ( EFI_ERROR ( Status
)) {
1491 DEBUG (( DEBUG_ERROR
,
1492 "ERROR - Failed to stop the timer, Status: %r\r\n",
1497 // Timer timer is now stopped
1499 bTimerRunning
= FALSE
;
1500 DEBUG (( DEBUG_INFO
,
1501 "0x%08x: Timer stopped\r\n",
1507 // Return the operation status
1516 @param [in] Milliseconds The number of milliseconds between timer callbacks
1518 @retval EFI_SUCCESS The timer was successfully created
1519 @retval Other Timer initialization failed
1530 // Stop the timer if necessary
1532 Status
= EFI_SUCCESS
;
1533 if ( bTimerRunning
) {
1534 Status
= TimerStop ( );
1536 if ( !EFI_ERROR ( Status
)) {
1538 // Compute the new delay
1540 TimeDelay
= Milliseconds
;
1541 TimeDelay
*= 1000 * 10;
1546 Status
= gBS
->SetTimer ( pTimer
,
1549 if ( EFI_ERROR ( Status
)) {
1550 DEBUG (( DEBUG_ERROR
,
1551 "ERROR - Failed to start the timer, Status: %r\r\n",
1556 // The timer is now running
1558 bTimerRunning
= TRUE
;
1559 DEBUG (( DEBUG_INFO
,
1560 "0x%08x: Timer running\r\n",
1566 // Return the operation status
1575 @retval EFI_SUCCESS The timer was destroyed successfully
1576 @retval Other Failed to destroy the timer
1587 Status
= EFI_SUCCESS
;
1590 // Determine if the timer is running
1592 if ( bTimerRunning
) {
1596 Status
= TimerStop ( );
1598 if (( !EFI_ERROR ( Status
)) && ( NULL
!= pTimer
)) {
1600 // Done with this timer
1602 Status
= gBS
->CloseEvent ( pTimer
);
1603 if ( EFI_ERROR ( Status
)) {
1604 DEBUG (( DEBUG_ERROR
,
1605 "ERROR - Failed to free the timer event, Status: %r\r\n",
1609 DEBUG (( DEBUG_INFO
,
1610 "0x%08x: Timer Destroyed\r\n",
1617 // Return the operation status
1624 Send data to the DataSink program to test a network's bandwidth.
1626 @param [in] Argc The number of arguments
1627 @param [in] Argv The argument value array
1629 @retval 0 The application exited normally.
1630 @retval Other An error occurred.
1638 EFI_STATUS (* pClose
) ();
1639 EFI_STATUS (* pOpen
) ();
1642 DEBUG (( DEBUG_INFO
,
1643 "DataSource starting\r\n" ));
1646 // Validate the command line
1649 Print ( L
"%s <remote IP address> [Use TCP]\r\n", Argv
[0] );
1654 // Determine if TCP should be used
1656 bTcp4
= (BOOLEAN
)( 2 < Argc
);
1659 // Determine the support routines
1664 bTcp4Connecting
= TRUE
;
1668 pClose
= SocketClose
;
1672 // Use for/break instead of goto
1676 // No bytes sent so far
1680 memset ( &BytesSent
, 0, sizeof ( BytesSent
));
1683 // Get the IP address
1685 pRemoteHost
= Argv
[1];
1686 Status
= IpAddress ( );
1687 if ( EFI_ERROR ( Status
)) {
1695 Status
= TimerCreate ( );
1696 if ( EFI_ERROR ( Status
)) {
1701 // Loop forever abusing the specified system
1705 // Start a timer to perform connection polling and display updates
1707 Status
= TimerStart ( 2 * 1000 );
1708 if ( EFI_ERROR ( Status
)) {
1713 // Open the network connection and send the data
1716 if ( EFI_ERROR ( Status
)) {
1721 // Done with the network connection
1723 Status
= pClose ( );
1724 } while ( !EFI_ERROR ( Status
));
1727 // Close the network connection if necessary
1738 // Stop the timer if necessary
1744 // Return the operation status
1746 DEBUG (( DEBUG_INFO
,
1747 "DataSource exiting, Status: %r\r\n",