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>
36 #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples
37 #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges
38 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
39 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
40 #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples
42 #define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL
44 #define PACKET_SIZE 1448 ///< Size of data packets
45 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
56 BOOLEAN bTcp4
; ///< TRUE if TCP4 is being used
57 BOOLEAN bTcp4Connected
; ///< TRUE if connected to remote system
58 BOOLEAN bTcp4Connecting
; ///< TRUE while connection in progress
59 UINTN Tcp4Index
; ///< Index into handle array
60 EFI_HANDLE Tcp4Controller
; ///< Network controller handle
61 EFI_HANDLE Tcp4Handle
; ///< TCP4 port handle
62 EFI_TCP4_PROTOCOL
* pTcp4Protocol
; ///< TCP4 protocol pointer
63 EFI_SERVICE_BINDING_PROTOCOL
* pTcp4Service
; ///< TCP4 Service binding
64 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;///< TCP4 configuration data
65 EFI_TCP4_OPTION Tcp4Option
; ///< TCP4 port options
66 EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken
;///< Close control
67 EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken
; ///< Connection control
68 EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken
; ///< Listen control
69 EFI_TCP4_IO_TOKEN Tcp4TxToken
; ///< Normal data token
74 volatile BOOLEAN bTick
;
75 BOOLEAN bTimerRunning
;
79 // Remote IP Address Data
81 struct sockaddr_in6 RemoteHostAddress
;
87 UINT64 TotalBytesSent
;
90 UINT64 BytesSent
[ DATA_SAMPLES
];
91 UINT8 Buffer
[ DATA_BUFFER_SIZE
];
95 // Forward routine declarations
97 EFI_STATUS
TimerStart ( UINTN Milliseconds
);
101 Check for control C entered at console
103 @retval EFI_SUCCESS Control C not entered
104 @retval EFI_ABORTED Control C entered
113 // Assume no user intervention
115 Status
= EFI_SUCCESS
;
118 // Display user stop request
120 if ( EFI_ERROR ( Status
)) {
122 "User stop request!\r\n" ));
126 // Return the check status
135 @param [in] pDigit The address of the next digit
136 @param [out] pValue The address to receive the value
138 @return Returns the address of the separator
153 while (( '0' <= *pDigit
) && ( '9' >= *pDigit
)) {
155 // Make room for the new least significant digit
160 // Convert the digit from ASCII to binary
162 Value
+= *pDigit
- '0';
165 // Set the next digit
176 // Return the next separator
185 @retval EFI_SUCCESS The IP address is valid
186 @retval Other Failure to convert the IP address
192 struct sockaddr_in
* pRemoteAddress4
;
193 struct sockaddr_in6
* pRemoteAddress6
;
194 UINT32 RemoteAddress
;
208 Status
= EFI_INVALID_PARAMETER
;
211 // Get the port number
213 ZeroMem ( &RemoteHostAddress
, sizeof ( RemoteHostAddress
));
214 RemoteHostAddress
.sin6_port
= htons ( PcdGet16 ( DataSource_Port
));
215 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
216 pRemoteAddress6
= &RemoteHostAddress
;
219 // Convert the IP address from a string to a numeric value
221 if (( 4 == sscanf ( pRemoteHost
,
230 && ( 255 >= Value4
)) {
232 // Build the IPv4 address
234 pRemoteAddress4
->sin_len
= sizeof ( *pRemoteAddress4
);
235 pRemoteAddress4
->sin_family
= AF_INET
;
236 RemoteAddress
= Value1
240 pRemoteAddress4
->sin_addr
.s_addr
= RemoteAddress
;
241 Status
= EFI_SUCCESS
;
244 // Display the IP address
247 "%d.%d.%d.%d: Remote host IP address\r\n",
253 else if (( 8 == sscanf ( pRemoteHost
,
254 "%x:%x:%x:%x:%x:%x:%x:%x",
263 && ( 0xffff >= Value1
)
264 && ( 0xffff >= Value2
)
265 && ( 0xffff >= Value3
)
266 && ( 0xffff >= Value4
)
267 && ( 0xffff >= Value5
)
268 && ( 0xffff >= Value6
)
269 && ( 0xffff >= Value7
)
270 && ( 0xffff >= Value8
)) {
272 // Build the IPv6 address
274 pRemoteAddress6
->sin6_len
= sizeof ( *pRemoteAddress6
);
275 pRemoteAddress6
->sin6_family
= AF_INET6
;
276 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ] = (UINT8
)( Value1
>> 8 );
277 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ] = (UINT8
)Value1
;
278 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ] = (UINT8
)( Value2
>> 8 );
279 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ] = (UINT8
)Value2
;
280 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ] = (UINT8
)( Value3
>> 8 );
281 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ] = (UINT8
)Value3
;
282 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ] = (UINT8
)( Value4
>> 8 );
283 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ] = (UINT8
)Value4
;
284 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ] = (UINT8
)( Value5
>> 8 );
285 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ] = (UINT8
)Value5
;
286 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ] = (UINT8
)( Value6
>> 8 );
287 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ] = (UINT8
)Value6
;
288 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ] = (UINT8
)( Value7
>> 8 );
289 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ] = (UINT8
)Value7
;
290 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ] = (UINT8
)( Value8
>> 8 );
291 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ] = (UINT8
)Value8
;
292 Status
= EFI_SUCCESS
;
295 // Display the IP address
298 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
309 Print ( L
"ERROR - Invalid IP address!\r\n" );
313 // Return the operation status
322 @retval EFI_SUCCESS The application is running normally
323 @retval Other The user stopped the application
333 // Determine if the socket is open
335 Status
= EFI_DEVICE_ERROR
;
336 if ( -1 != Socket
) {
338 // Attempt to close the socket
340 CloseStatus
= close ( Socket
);
341 if ( 0 == CloseStatus
) {
343 "0x%08x: Socket closed\r\n",
346 Status
= EFI_SUCCESS
;
349 DEBUG (( DEBUG_ERROR
,
350 "ERROR: Failed to close socket, errno: %d\r\n",
356 // Return the operation status
365 @retval EFI_SUCCESS The application is running normally
366 @retval Other The user stopped the application
373 struct sockaddr_in
* pRemoteAddress4
;
374 struct sockaddr_in6
* pRemoteAddress6
;
378 // Display the connecting message
380 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
381 pRemoteAddress6
= &RemoteHostAddress
;
382 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
383 Print ( L
"Connecting to remote system %d.%d.%d.%d:%d\r\n",
384 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
385 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
386 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
387 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
388 htons ( pRemoteAddress4
->sin_port
));
391 Print ( L
"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
392 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
393 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
394 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
395 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
396 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
397 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
398 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
399 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
400 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
401 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
402 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
403 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
404 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
405 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
406 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
407 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
408 htons ( pRemoteAddress6
->sin6_port
));
412 // Connect to the remote system
414 Status
= EFI_SUCCESS
;
417 // Check for user stop request
420 Status
= ControlCCheck ( );
421 if ( EFI_ERROR ( Status
)) {
426 if ( EFI_ERROR ( Status
)) {
431 // Connect to the remote system
433 ConnectStatus
= connect ( Socket
,
434 (struct sockaddr
*)pRemoteAddress6
,
435 pRemoteAddress6
->sin6_len
);
436 if ( -1 != ConnectStatus
) {
437 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
438 Print ( L
"Connected to remote system %d.%d.%d.%d:%d\r\n",
439 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
440 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
441 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
442 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
443 htons ( pRemoteAddress4
->sin_port
));
446 Print ( L
"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
447 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
448 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
449 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
450 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
451 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
452 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
453 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
454 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
455 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
456 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
457 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
458 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
459 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
460 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
461 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
462 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
463 htons ( pRemoteAddress6
->sin6_port
));
468 // Close the socket and try again
470 if ( EAGAIN
!= errno
) {
471 Status
= EFI_NOT_STARTED
;
475 } while ( -1 == ConnectStatus
);
478 // Return the operation status
487 @param [in] Family Network family, AF_INET or AF_INET6
489 @retval EFI_SUCCESS The application is running normally
490 @retval Other The user stopped the application
500 // Loop creating the socket
503 "Creating the socket\r\n" ));
506 // Check for user stop request
508 Status
= ControlCCheck ( );
509 if ( EFI_ERROR ( Status
)) {
514 // Attempt to create the socket
516 Socket
= socket ( Family
,
519 if ( -1 != Socket
) {
521 "0x%08x: Socket created\r\n",
525 } while ( -1 == Socket
);
528 // Return the operation status
535 Send data over the socket
537 @retval EFI_SUCCESS The application is running normally
538 @retval Other The user stopped the application
551 TimerStart ( 1 * 1000 );
554 // Loop until the connection breaks or the user stops
558 // Check for user stop request
560 Status
= ControlCCheck ( );
561 if ( EFI_ERROR ( Status
)) {
568 BytesSent
= write ( Socket
, &Buffer
[0], sizeof ( Buffer
));
569 if ( -1 == BytesSent
) {
571 "ERROR: send failed, errno: %d\r\n",
577 Status
= EFI_SUCCESS
;
582 Status
= EFI_NOT_STARTED
;
587 // Synchronize with the TimerCallback routine
589 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
592 // Account for the data sent
594 TotalBytesSent
+= BytesSent
;
597 // Release the TimerCallback routine synchronization
599 gBS
->RestoreTPL ( TplPrevious
);
600 } while ( !EFI_ERROR ( Status
));
603 // Return the operation status
610 Open the network connection and send the data.
612 @retval EFI_SUCCESS Continue looping
613 @retval other Stopped by user's Control-C input
623 // Use do/while and break instead of goto
627 // Wait for the network layer to initialize
629 Status
= SocketNew ( RemoteHostAddress
.sin6_family
);
630 if ( EFI_ERROR ( Status
)) {
635 // Wait for the remote network application to start
637 Status
= SocketConnect ( );
638 if ( EFI_NOT_STARTED
== Status
) {
639 Status
= SocketClose ( );
642 else if ( EFI_SUCCESS
!= Status
) {
650 // Send data until the connection breaks
652 Status
= SocketSend ( );
653 if ( EFI_ERROR ( Status
)) {
659 // Return the operation 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 htons ( ((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 htons ( ((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
= ((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 htons ( ((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
1326 UINT64 BitsPerSecond
;
1331 // Notify the other code of the timer tick
1336 // Update the average bytes per second
1338 if ( 0 != TotalBytesSent
) {
1339 BytesSent
[ In
] = TotalBytesSent
;
1342 if ( DATA_SAMPLES
<= In
) {
1347 // Separate the samples
1349 if ( DATA_SAMPLES
== Samples
) {
1350 Print ( L
"---------- Stable average ----------\r\n" );
1355 // Compute the data rate
1358 for ( Index
= 0; DATA_SAMPLES
> Index
; Index
++ ) {
1359 TotalBytes
+= BytesSent
[ Index
];
1361 Average
= (UINT32
)RShiftU64 ( TotalBytes
, DATA_SAMPLE_SHIFT
);
1362 BitsPerSecond
= Average
* 8;
1365 // Display the data rate
1367 if (( RANGE_SWITCH
>> 10 ) > Average
) {
1368 Print ( L
"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1373 BitsPerSecond
/= 1000;
1374 if ( RANGE_SWITCH
> Average
) {
1375 Print ( L
"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1377 (( Average
& 0x3ff ) * 1000 ) >> 10,
1381 BitsPerSecond
/= 1000;
1383 if ( RANGE_SWITCH
> Average
) {
1384 Print ( L
"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1386 (( Average
& 0x3ff ) * 1000 ) >> 10,
1390 BitsPerSecond
/= 1000;
1392 if ( RANGE_SWITCH
> Average
) {
1393 Print ( L
"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1395 (( Average
& 0x3ff ) * 1000 ) >> 10,
1399 BitsPerSecond
/= 1000;
1401 if ( RANGE_SWITCH
> Average
) {
1402 Print ( L
"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1404 (( Average
& 0x3ff ) * 1000 ) >> 10,
1408 BitsPerSecond
/= 1000;
1410 Print ( L
"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1412 (( Average
& 0x3ff ) * 1000 ) >> 10,
1426 @retval EFI_SUCCESS The timer was successfully created
1427 @retval Other Timer initialization failed
1438 Status
= gBS
->CreateEvent ( EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1443 if ( EFI_ERROR ( Status
)) {
1444 DEBUG (( DEBUG_ERROR
,
1445 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1449 DEBUG (( DEBUG_INFO
,
1450 "0x%08x: Timer created\r\n",
1455 // Return the operation status
1464 @retval EFI_SUCCESS The timer was stopped successfully
1465 @retval Other The timer failed to stop
1476 Status
= EFI_SUCCESS
;
1479 // Determine if the timer is running
1481 if ( bTimerRunning
) {
1485 Status
= gBS
->SetTimer ( pTimer
,
1488 if ( EFI_ERROR ( Status
)) {
1489 DEBUG (( DEBUG_ERROR
,
1490 "ERROR - Failed to stop the timer, Status: %r\r\n",
1495 // Timer timer is now stopped
1497 bTimerRunning
= FALSE
;
1498 DEBUG (( DEBUG_INFO
,
1499 "0x%08x: Timer stopped\r\n",
1505 // Return the operation status
1514 @param [in] Milliseconds The number of milliseconds between timer callbacks
1516 @retval EFI_SUCCESS The timer was successfully created
1517 @retval Other Timer initialization failed
1528 // Stop the timer if necessary
1530 Status
= EFI_SUCCESS
;
1531 if ( bTimerRunning
) {
1532 Status
= TimerStop ( );
1534 if ( !EFI_ERROR ( Status
)) {
1536 // Compute the new delay
1538 TimeDelay
= Milliseconds
;
1539 TimeDelay
*= 1000 * 10;
1544 Status
= gBS
->SetTimer ( pTimer
,
1547 if ( EFI_ERROR ( Status
)) {
1548 DEBUG (( DEBUG_ERROR
,
1549 "ERROR - Failed to start the timer, Status: %r\r\n",
1554 // The timer is now running
1556 bTimerRunning
= TRUE
;
1557 DEBUG (( DEBUG_INFO
,
1558 "0x%08x: Timer running\r\n",
1564 // Return the operation status
1573 @retval EFI_SUCCESS The timer was destroyed successfully
1574 @retval Other Failed to destroy the timer
1585 Status
= EFI_SUCCESS
;
1588 // Determine if the timer is running
1590 if ( bTimerRunning
) {
1594 Status
= TimerStop ( );
1596 if (( !EFI_ERROR ( Status
)) && ( NULL
!= pTimer
)) {
1598 // Done with this timer
1600 Status
= gBS
->CloseEvent ( pTimer
);
1601 if ( EFI_ERROR ( Status
)) {
1602 DEBUG (( DEBUG_ERROR
,
1603 "ERROR - Failed to free the timer event, Status: %r\r\n",
1607 DEBUG (( DEBUG_INFO
,
1608 "0x%08x: Timer Destroyed\r\n",
1615 // Return the operation status
1622 Send data to the DataSink program to test a network's bandwidth.
1624 @param [in] Argc The number of arguments
1625 @param [in] Argv The argument value array
1627 @retval 0 The application exited normally.
1628 @retval Other An error occurred.
1636 EFI_STATUS (* pClose
) ();
1637 EFI_STATUS (* pOpen
) ();
1640 DEBUG (( DEBUG_INFO
,
1641 "DataSource starting\r\n" ));
1644 // Validate the command line
1647 Print ( L
"%s <remote IP address> [Use TCP]\r\n", Argv
[0] );
1652 // Determine if TCP should be used
1654 bTcp4
= (BOOLEAN
)( 2 < Argc
);
1657 // Determine the support routines
1662 bTcp4Connecting
= TRUE
;
1666 pClose
= SocketClose
;
1670 // Use for/break instead of goto
1674 // No bytes sent so far
1678 memset ( &BytesSent
, 0, sizeof ( BytesSent
));
1681 // Get the IP address
1683 pRemoteHost
= Argv
[1];
1684 Status
= IpAddress ( );
1685 if ( EFI_ERROR ( Status
)) {
1693 Status
= TimerCreate ( );
1694 if ( EFI_ERROR ( Status
)) {
1699 // Loop forever abusing the specified system
1703 // Start a timer to perform connection polling and display updates
1705 Status
= TimerStart ( 2 * 1000 );
1706 if ( EFI_ERROR ( Status
)) {
1711 // Open the network connection and send the data
1714 if ( EFI_ERROR ( Status
)) {
1719 // Done with the network connection
1721 Status
= pClose ( );
1722 } while ( !EFI_ERROR ( Status
));
1725 // Close the network connection if necessary
1736 // Stop the timer if necessary
1742 // Return the operation status
1744 DEBUG (( DEBUG_INFO
,
1745 "DataSource exiting, Status: %r\r\n",