]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Sockets/DataSource/DataSource.c
- For writing sin_port, htons() must be used.
[mirror_edk2.git] / AppPkg / Applications / Sockets / DataSource / DataSource.c
1 /** @file
2 Data source for network testing.
3
4 Copyright (c) 2011-2012, 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
9
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.
12
13 **/
14
15 #include <errno.h>
16 #include <Uefi.h>
17
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>
23
24 #include <netinet/in.h>
25
26 #include <Protocol/ServiceBinding.h>
27 #include <Protocol/Tcp4.h>
28
29 #include <sys/EfiSysCall.h>
30 #include <sys/poll.h>
31 #include <sys/socket.h>
32
33 #include <stdio.h>
34 #include <string.h>
35
36
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
42
43 #define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL
44
45 #define PACKET_SIZE 1448 ///< Size of data packets
46 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
47
48
49 //
50 // Socket Data
51 //
52 int Socket = -1;
53
54 //
55 // TCP V4 Data
56 //
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
71
72 //
73 // Timer Data
74 //
75 volatile BOOLEAN bTick;
76 BOOLEAN bTimerRunning;
77 EFI_EVENT pTimer;
78
79 //
80 // Remote IP Address Data
81 //
82 struct sockaddr_in6 RemoteHostAddress;
83 CHAR8 * pRemoteHost;
84
85 //
86 // Traffic Data
87 //
88 UINT64 TotalBytesSent;
89 UINT32 In;
90 UINT32 Samples;
91 UINT64 BytesSent[ DATA_SAMPLES ];
92 UINT8 Buffer[ DATA_BUFFER_SIZE ];
93
94
95 //
96 // Forward routine declarations
97 //
98 EFI_STATUS TimerStart ( UINTN Milliseconds );
99
100
101 /**
102 Check for control C entered at console
103
104 @retval EFI_SUCCESS Control C not entered
105 @retval EFI_ABORTED Control C entered
106 **/
107 EFI_STATUS
108 ControlCCheck (
109 )
110 {
111 EFI_STATUS Status;
112
113 //
114 // Assume no user intervention
115 //
116 Status = EFI_SUCCESS;
117
118 //
119 // Display user stop request
120 //
121 if ( EFI_ERROR ( Status )) {
122 DEBUG (( DEBUG_INFO,
123 "User stop request!\r\n" ));
124 }
125
126 //
127 // Return the check status
128 //
129 return Status;
130 }
131
132
133 /**
134 Get a digit
135
136 @param [in] pDigit The address of the next digit
137 @param [out] pValue The address to receive the value
138
139 @return Returns the address of the separator
140
141 **/
142 CHAR8 *
143 GetDigit (
144 CHAR8 * pDigit,
145 UINT32 * pValue
146 )
147 {
148 UINT32 Value;
149
150 //
151 // Walk the digits
152 //
153 Value = 0;
154 while (( '0' <= *pDigit ) && ( '9' >= *pDigit )) {
155 //
156 // Make room for the new least significant digit
157 //
158 Value *= 10;
159
160 //
161 // Convert the digit from ASCII to binary
162 //
163 Value += *pDigit - '0';
164
165 //
166 // Set the next digit
167 //
168 pDigit += 1;
169 }
170
171 //
172 // Return the value
173 //
174 *pValue = Value;
175
176 //
177 // Return the next separator
178 //
179 return pDigit;
180 }
181
182
183 /**
184 Get the IP address
185
186 @retval EFI_SUCCESS The IP address is valid
187 @retval Other Failure to convert the IP address
188 **/
189 EFI_STATUS
190 IpAddress (
191 )
192 {
193 struct sockaddr_in * pRemoteAddress4;
194 struct sockaddr_in6 * pRemoteAddress6;
195 UINT32 RemoteAddress;
196 EFI_STATUS Status;
197 UINT32 Value1;
198 UINT32 Value2;
199 UINT32 Value3;
200 UINT32 Value4;
201 UINT32 Value5;
202 UINT32 Value6;
203 UINT32 Value7;
204 UINT32 Value8;
205
206 //
207 // Assume failure
208 //
209 Status = EFI_INVALID_PARAMETER;
210
211 //
212 // Get the port number
213 //
214 ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));
215 RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));
216 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;
217 pRemoteAddress6 = &RemoteHostAddress;
218
219 //
220 // Convert the IP address from a string to a numeric value
221 //
222 if (( 4 == sscanf ( pRemoteHost,
223 "%d.%d.%d.%d",
224 &Value1,
225 &Value2,
226 &Value3,
227 &Value4 ))
228 && ( 255 >= Value1 )
229 && ( 255 >= Value2 )
230 && ( 255 >= Value3 )
231 && ( 255 >= Value4 )) {
232 //
233 // Build the IPv4 address
234 //
235 pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );
236 pRemoteAddress4->sin_family = AF_INET;
237 RemoteAddress = Value1
238 | ( Value2 << 8 )
239 | ( Value3 << 16 )
240 | ( Value4 << 24 );
241 pRemoteAddress4->sin_addr.s_addr = RemoteAddress;
242 Status = EFI_SUCCESS;
243
244 //
245 // Display the IP address
246 //
247 DEBUG (( DEBUG_INFO,
248 "%d.%d.%d.%d: Remote host IP address\r\n",
249 Value1,
250 Value2,
251 Value3,
252 Value4 ));
253 }
254 else if (( 8 == sscanf ( pRemoteHost,
255 "%x:%x:%x:%x:%x:%x:%x:%x",
256 &Value1,
257 &Value2,
258 &Value3,
259 &Value4,
260 &Value5,
261 &Value6,
262 &Value7,
263 &Value8 ))
264 && ( 0xffff >= Value1 )
265 && ( 0xffff >= Value2 )
266 && ( 0xffff >= Value3 )
267 && ( 0xffff >= Value4 )
268 && ( 0xffff >= Value5 )
269 && ( 0xffff >= Value6 )
270 && ( 0xffff >= Value7 )
271 && ( 0xffff >= Value8 )) {
272 //
273 // Build the IPv6 address
274 //
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;
294
295 //
296 // Display the IP address
297 //
298 DEBUG (( DEBUG_INFO,
299 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
300 Value1,
301 Value2,
302 Value3,
303 Value4,
304 Value5,
305 Value6,
306 Value7,
307 Value8 ));
308 }
309 else {
310 Print ( L"ERROR - Invalid IP address!\r\n" );
311 }
312
313 //
314 // Return the operation status
315 //
316 return Status;
317 }
318
319
320 /**
321 Close the socket
322
323 @retval EFI_SUCCESS The application is running normally
324 @retval Other The user stopped the application
325 **/
326 EFI_STATUS
327 SocketClose (
328 )
329 {
330 int CloseStatus;
331 EFI_STATUS Status;
332
333 //
334 // Determine if the socket is open
335 //
336 Status = EFI_DEVICE_ERROR;
337 if ( -1 != Socket ) {
338 //
339 // Attempt to close the socket
340 //
341 CloseStatus = close ( Socket );
342 if ( 0 == CloseStatus ) {
343 DEBUG (( DEBUG_INFO,
344 "0x%08x: Socket closed\r\n",
345 Socket ));
346 Socket = -1;
347 Status = EFI_SUCCESS;
348 }
349 else {
350 DEBUG (( DEBUG_ERROR,
351 "ERROR: Failed to close socket, errno: %d\r\n",
352 errno ));
353 }
354 }
355
356 //
357 // Return the operation status
358 //
359 return Status;
360 }
361
362
363 /**
364 Connect the socket
365
366 @retval EFI_SUCCESS The application is running normally
367 @retval Other The user stopped the application
368 **/
369 EFI_STATUS
370 SocketConnect (
371 )
372 {
373 int ConnectStatus;
374 struct sockaddr_in * pRemoteAddress4;
375 struct sockaddr_in6 * pRemoteAddress6;
376 EFI_STATUS Status;
377
378 //
379 // Display the connecting message
380 //
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 ntohs ( pRemoteAddress4->sin_port ));
390 }
391 else {
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 ntohs ( pRemoteAddress6->sin6_port ));
410 }
411
412 //
413 // Connect to the remote system
414 //
415 Status = EFI_SUCCESS;
416 do {
417 //
418 // Check for user stop request
419 //
420 while ( !bTick ) {
421 Status = ControlCCheck ( );
422 if ( EFI_ERROR ( Status )) {
423 break;
424 }
425 }
426 bTick = FALSE;
427 if ( EFI_ERROR ( Status )) {
428 break;
429 }
430
431 //
432 // Connect to the remote system
433 //
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 ntohs ( pRemoteAddress4->sin_port ));
445 }
446 else {
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 ntohs ( pRemoteAddress6->sin6_port ));
465 }
466 Print ( L"ConnectStatus: %d, Status: %r\r\n", ConnectStatus, Status );
467 }
468 else {
469 //
470 // Close the socket and try again
471 //
472 if ( EAGAIN != errno ) {
473 Status = EFI_NOT_STARTED;
474 break;
475 }
476 }
477 } while ( -1 == ConnectStatus );
478
479 //
480 // Return the operation status
481 //
482 Print ( L"SocketConnect returning Status: %r\r\n", Status );
483 return Status;
484 }
485
486
487 /**
488 Create the socket
489
490 @param [in] Family Network family, AF_INET or AF_INET6
491
492 @retval EFI_SUCCESS The application is running normally
493 @retval Other The user stopped the application
494 **/
495 EFI_STATUS
496 SocketNew (
497 sa_family_t Family
498 )
499 {
500 EFI_STATUS Status;
501
502 //
503 // Loop creating the socket
504 //
505 DEBUG (( DEBUG_INFO,
506 "Creating the socket\r\n" ));
507 do {
508 //
509 // Check for user stop request
510 //
511 Status = ControlCCheck ( );
512 if ( EFI_ERROR ( Status )) {
513 break;
514 }
515
516 //
517 // Attempt to create the socket
518 //
519 Socket = socket ( Family,
520 SOCK_STREAM,
521 IPPROTO_TCP );
522 if ( -1 != Socket ) {
523 DEBUG (( DEBUG_INFO,
524 "0x%08x: Socket created\r\n",
525 Socket ));
526 break;
527 }
528 } while ( -1 == Socket );
529
530 //
531 // Return the operation status
532 //
533 return Status;
534 }
535
536
537 /**
538 Send data over the socket
539
540 @retval EFI_SUCCESS The application is running normally
541 @retval Other The user stopped the application
542 **/
543 EFI_STATUS
544 SocketSend (
545 )
546 {
547 size_t BytesSent;
548 EFI_STATUS Status;
549 EFI_TPL TplPrevious;
550
551 //
552 // Restart the timer
553 //
554 TimerStart ( 1 * 1000 );
555
556 //
557 // Loop until the connection breaks or the user stops
558 //
559 do {
560 //
561 // Check for user stop request
562 //
563 Status = ControlCCheck ( );
564 if ( EFI_ERROR ( Status )) {
565 break;
566 }
567
568 //
569 // Send some bytes
570 //
571 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));
572 if ( -1 == BytesSent ) {
573 DEBUG (( DEBUG_INFO,
574 "ERROR: send failed, errno: %d\r\n",
575 errno ));
576 Print ( L"ERROR: send failed, errno: %d\r\n", errno );
577
578 //
579 // Try again
580 //
581 Status = EFI_SUCCESS;
582
583 //
584 // Exit now
585 //
586 Status = EFI_NOT_STARTED;
587 break;
588 }
589
590 //
591 // Synchronize with the TimerCallback routine
592 //
593 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
594
595 //
596 // Account for the data sent
597 //
598 TotalBytesSent += BytesSent;
599
600 //
601 // Release the TimerCallback routine synchronization
602 //
603 gBS->RestoreTPL ( TplPrevious );
604 } while ( !EFI_ERROR ( Status ));
605
606 //
607 // Return the operation status
608 //
609 return Status;
610 }
611
612
613 /**
614 Open the network connection and send the data.
615
616 @retval EFI_SUCCESS Continue looping
617 @retval other Stopped by user's Control-C input
618
619 **/
620 EFI_STATUS
621 SocketOpen (
622 )
623 {
624 EFI_STATUS Status;
625
626 //
627 // Use do/while and break instead of goto
628 //
629 do {
630 //
631 // Wait for the network layer to initialize
632 //
633 Status = SocketNew ( RemoteHostAddress.sin6_family );
634 if ( EFI_ERROR ( Status )) {
635 break;
636 }
637
638 //
639 // Wait for the remote network application to start
640 //
641 Status = SocketConnect ( );
642 Print ( L"Status: %r\r\n", Status );
643 if ( EFI_NOT_STARTED == Status ) {
644 Status = SocketClose ( );
645 continue;
646 }
647 else if ( EFI_SUCCESS != Status ) {
648 //
649 // Control-C
650 //
651 break;
652 }
653
654 //
655 // Send data until the connection breaks
656 //
657 Status = SocketSend ( );
658 if ( EFI_ERROR ( Status )) {
659 break;
660 }
661 } while ( FALSE );
662
663 //
664 // Return the operation status
665 //
666 Print ( L"Returning Status: %r\r\n", Status );
667 return Status;
668 }
669
670
671 /**
672 Close the TCP connection
673
674 @retval EFI_SUCCESS The application is running normally
675 @retval Other The user stopped the application
676 **/
677 EFI_STATUS
678 Tcp4Close (
679 )
680 {
681 UINTN Index;
682 UINT8 * pIpAddress;
683 EFI_STATUS Status;
684
685 //
686 // Close the port
687 //
688 if ( bTcp4Connected ) {
689 Tcp4CloseToken.AbortOnClose = TRUE;
690 Status = pTcp4Protocol->Close ( pTcp4Protocol,
691 &Tcp4CloseToken );
692 if ( EFI_ERROR ( Status )) {
693 DEBUG (( DEBUG_ERROR,
694 "ERROR - Failed to start the TCP port close, Status: %r\r\n",
695 Status ));
696 }
697 else {
698 Status = gBS->WaitForEvent ( 1,
699 &Tcp4CloseToken.CompletionToken.Event,
700 &Index );
701 if ( EFI_ERROR ( Status )) {
702 DEBUG (( DEBUG_ERROR,
703 "ERROR - Failed to wait for close event, Status: %r\r\n",
704 Status ));
705 }
706 else {
707 Status = Tcp4CloseToken.CompletionToken.Status;
708 if ( EFI_ERROR ( Status )) {
709 DEBUG (( DEBUG_ERROR,
710 "ERROR - Failed to close the TCP port, Status: %r\r\n",
711 Status ));
712 }
713 else {
714 DEBUG (( DEBUG_INFO,
715 "0x%08x: TCP port closed\r\n",
716 pTcp4Protocol ));
717 bTcp4Connected = FALSE;
718
719 //
720 // Display the port closed message
721 //
722 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
723 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",
724 pIpAddress[0],
725 pIpAddress[1],
726 pIpAddress[2],
727 pIpAddress[3],
728 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
729 }
730 }
731 }
732 }
733
734 //
735 // Release the events
736 //
737 if ( NULL != Tcp4TxToken.CompletionToken.Event ) {
738 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );
739 if ( !EFI_ERROR ( Status )) {
740 DEBUG (( DEBUG_INFO,
741 "0x%08x: TX event closed\r\n",
742 Tcp4TxToken.CompletionToken.Event ));
743 Tcp4TxToken.CompletionToken.Event = NULL;
744 }
745 else {
746 DEBUG (( DEBUG_ERROR,
747 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
748 Status ));
749 }
750 }
751
752 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {
753 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );
754 if ( !EFI_ERROR ( Status )) {
755 DEBUG (( DEBUG_INFO,
756 "0x%08x: Listen event closed\r\n",
757 Tcp4ListenToken.CompletionToken.Event ));
758 Tcp4ListenToken.CompletionToken.Event = NULL;
759 }
760 else {
761 DEBUG (( DEBUG_ERROR,
762 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
763 Status ));
764 }
765 }
766
767 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {
768 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );
769 if ( !EFI_ERROR ( Status )) {
770 DEBUG (( DEBUG_INFO,
771 "0x%08x: Connect event closed\r\n",
772 Tcp4ConnectToken.CompletionToken.Event ));
773 Tcp4ConnectToken.CompletionToken.Event = NULL;
774 }
775 else {
776 DEBUG (( DEBUG_ERROR,
777 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
778 Status ));
779 }
780 }
781
782 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {
783 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );
784 if ( !EFI_ERROR ( Status )) {
785 DEBUG (( DEBUG_INFO,
786 "0x%08x: Close event closed\r\n",
787 Tcp4CloseToken.CompletionToken.Event ));
788 Tcp4CloseToken.CompletionToken.Event = NULL;
789 }
790 else {
791 DEBUG (( DEBUG_ERROR,
792 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
793 Status ));
794 }
795 }
796
797 //
798 // Close the TCP protocol
799 //
800 if ( NULL != pTcp4Protocol ) {
801 Status = gBS->CloseProtocol ( Tcp4Handle,
802 &gEfiTcp4ProtocolGuid,
803 gImageHandle,
804 NULL );
805 if ( EFI_ERROR ( Status )) {
806 DEBUG (( DEBUG_ERROR,
807 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
808 Status ));
809 }
810 else {
811 DEBUG (( DEBUG_INFO,
812 "0x%08x: TCP4 protocol closed\r\n",
813 pTcp4Protocol ));
814 pTcp4Protocol = NULL;
815 }
816 }
817
818 //
819 // Done with the TCP service
820 //
821 if ( NULL != Tcp4Handle ) {
822 Status = pTcp4Service->DestroyChild ( pTcp4Service,
823 Tcp4Handle );
824 if ( EFI_ERROR ( Status )) {
825 DEBUG (( DEBUG_ERROR,
826 "ERROR - Failed to release TCP service handle, Status: %r\r\n",
827 Status ));
828 }
829 else {
830 DEBUG (( DEBUG_INFO,
831 "Ox%08x: TCP service closed\r\n",
832 Tcp4Handle ));
833 Tcp4Handle = NULL;
834 }
835 }
836
837 //
838 // Close the service protocol
839 //
840 if ( NULL != pTcp4Service ) {
841 Status = gBS->CloseProtocol ( Tcp4Controller,
842 &gEfiTcp4ServiceBindingProtocolGuid,
843 gImageHandle,
844 NULL );
845 if ( !EFI_ERROR ( Status )) {
846 DEBUG (( DEBUG_INFO,
847 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
848 Tcp4Controller ));
849 pTcp4Service = NULL;
850 }
851 else {
852 DEBUG (( DEBUG_ERROR,
853 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
854 Status ));
855 }
856 }
857 Tcp4Controller = NULL;
858 bTcp4Connecting = TRUE;
859
860 //
861 // Mark the connection as closed
862 //
863 Status = EFI_SUCCESS;
864
865 //
866 // Return the operation status
867 //
868 return Status;
869 }
870
871
872 /**
873 Locate TCP protocol
874
875 @retval EFI_SUCCESS Protocol found
876 @retval other Protocl not found
877 **/
878 EFI_STATUS
879 Tcp4Locate (
880 )
881 {
882 UINTN HandleCount;
883 EFI_HANDLE * pHandles;
884 UINT8 * pIpAddress;
885 EFI_STATUS Status;
886
887 //
888 // Use do/while and break instead of goto
889 //
890 do {
891 //
892 // Attempt to locate the next TCP adapter in the system
893 //
894 Status = gBS->LocateHandleBuffer ( ByProtocol,
895 &gEfiTcp4ServiceBindingProtocolGuid,
896 NULL,
897 &HandleCount,
898 &pHandles );
899 if ( EFI_ERROR ( Status )) {
900 DEBUG (( DEBUG_WARN,
901 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
902 Status ));
903 break;
904 }
905
906 //
907 // Wrap the index if necessary
908 //
909 if ( HandleCount <= Tcp4Index ) {
910 Tcp4Index = 0;
911
912 //
913 // Wait for the next timer tick
914 //
915 do {
916 } while ( !bTick );
917 bTick = FALSE;
918 }
919
920 //
921 // Display the connecting message
922 //
923 if ( bTcp4Connecting ) {
924 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
925 Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",
926 pIpAddress[0],
927 pIpAddress[1],
928 pIpAddress[2],
929 pIpAddress[3],
930 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
931 bTcp4Connecting = FALSE;
932 }
933
934 //
935 // Open the network controller's service protocol
936 //
937 Tcp4Controller = pHandles[ Tcp4Index++ ];
938 Status = gBS->OpenProtocol (
939 Tcp4Controller,
940 &gEfiTcp4ServiceBindingProtocolGuid,
941 (VOID **) &pTcp4Service,
942 gImageHandle,
943 NULL,
944 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
945 if ( EFI_ERROR ( Status )) {
946 DEBUG (( DEBUG_ERROR,
947 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
948 Tcp4Controller ));
949 Tcp4Controller = NULL;
950 break;
951 }
952 DEBUG (( DEBUG_INFO,
953 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
954 Tcp4Controller ));
955
956 //
957 // Connect to the TCP service
958 //
959 Status = pTcp4Service->CreateChild ( pTcp4Service,
960 &Tcp4Handle );
961 if ( EFI_ERROR ( Status )) {
962 DEBUG (( DEBUG_ERROR,
963 "ERROR - Failed to open TCP service, Status: %r\r\n",
964 Status ));
965 Tcp4Handle = NULL;
966 break;
967 }
968 DEBUG (( DEBUG_INFO,
969 "Ox%08x: TCP service opened\r\n",
970 Tcp4Handle ));
971
972 //
973 // Locate the TCP protcol
974 //
975 Status = gBS->OpenProtocol ( Tcp4Handle,
976 &gEfiTcp4ProtocolGuid,
977 (VOID **)&pTcp4Protocol,
978 gImageHandle,
979 NULL,
980 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
981 if ( EFI_ERROR ( Status )) {
982 DEBUG (( DEBUG_ERROR,
983 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",
984 Status ));
985 pTcp4Protocol = NULL;
986 break;
987 }
988 DEBUG (( DEBUG_INFO,
989 "0x%08x: TCP4 protocol opened\r\n",
990 pTcp4Protocol ));
991 }while ( FALSE );
992
993 //
994 // Release the handle buffer
995 //
996 gBS->FreePool ( pHandles );
997
998 //
999 // Return the operation status
1000 //
1001 return Status;
1002 }
1003
1004
1005 /**
1006 Send data over the TCP4 connection
1007
1008 @retval EFI_SUCCESS The application is running normally
1009 @retval Other The user stopped the application
1010 **/
1011 EFI_STATUS
1012 Tcp4Send (
1013 )
1014 {
1015 UINTN Index;
1016 EFI_TCP4_TRANSMIT_DATA Packet;
1017 EFI_STATUS Status;
1018 EFI_TPL TplPrevious;
1019
1020 //
1021 // Restart the timer
1022 //
1023 TimerStart ( 1 * 1000 );
1024
1025 //
1026 // Initialize the packet
1027 //
1028 Packet.DataLength = sizeof ( Buffer );
1029 Packet.FragmentCount = 1;
1030 Packet.Push = FALSE;
1031 Packet.Urgent = FALSE;
1032 Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];
1033 Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );
1034 Tcp4TxToken.Packet.TxData = &Packet;
1035
1036 //
1037 // Loop until the connection breaks or the user stops
1038 //
1039 do {
1040 //
1041 // Check for user stop request
1042 //
1043 Status = ControlCCheck ( );
1044 if ( EFI_ERROR ( Status )) {
1045 break;
1046 }
1047
1048 //
1049 // Send some bytes
1050 //
1051 Status = pTcp4Protocol->Transmit ( pTcp4Protocol,
1052 &Tcp4TxToken );
1053 if ( EFI_ERROR ( Status )) {
1054 DEBUG (( DEBUG_ERROR,
1055 "ERROR - Failed to start the transmit, Status: %r\r\n",
1056 Status ));
1057
1058 //
1059 // Try again
1060 //
1061 Status = EFI_SUCCESS;
1062 break;
1063 }
1064
1065 //
1066 // Wait for the transmit to complete
1067 //
1068 Status = gBS->WaitForEvent ( 1,
1069 &Tcp4TxToken.CompletionToken.Event,
1070 &Index );
1071 if ( EFI_ERROR ( Status )) {
1072 DEBUG (( DEBUG_ERROR,
1073 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
1074 Status ));
1075
1076 //
1077 // Try again
1078 //
1079 Status = EFI_SUCCESS;
1080 break;
1081 }
1082
1083 //
1084 // Get the transmit status
1085 //
1086 Status = Tcp4TxToken.CompletionToken.Status;
1087 if ( EFI_ERROR ( Status )) {
1088 DEBUG (( DEBUG_WARN,
1089 "WARNING - Failed the transmission, Status: %r\r\n",
1090 Status ));
1091
1092 //
1093 // Try again
1094 //
1095 Status = EFI_SUCCESS;
1096
1097 //
1098 // Exit now
1099 //
1100 Status = EFI_NOT_STARTED;
1101 break;
1102 }
1103
1104 //
1105 // Synchronize with the TimerCallback routine
1106 //
1107 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
1108
1109 //
1110 // Account for the data sent
1111 //
1112 TotalBytesSent += Packet.DataLength;
1113
1114 //
1115 // Release the TimerCallback routine synchronization
1116 //
1117 gBS->RestoreTPL ( TplPrevious );
1118 } while ( !EFI_ERROR ( Status ));
1119
1120 //
1121 // Return the operation status
1122 //
1123 return Status;
1124 }
1125
1126
1127 /**
1128 Open the network connection and send the data.
1129
1130 @retval EFI_SUCCESS Continue looping
1131 @retval other Stopped by user's Control-C input
1132
1133 **/
1134 EFI_STATUS
1135 Tcp4Open (
1136 )
1137 {
1138 UINTN Index;
1139 UINT8 * pIpAddress;
1140 EFI_STATUS Status;
1141
1142 //
1143 // Use do/while and break instead of goto
1144 //
1145 do {
1146 //
1147 // Locate the TCP protocol
1148 //
1149 Status = Tcp4Locate ( );
1150 if ( EFI_ERROR ( Status )) {
1151 break;
1152 }
1153
1154 //
1155 // Create the necessary events
1156 //
1157 Status = gBS->CreateEvent ( 0,
1158 TPL_CALLBACK,
1159 NULL,
1160 NULL,
1161 &Tcp4CloseToken.CompletionToken.Event );
1162 if ( EFI_ERROR ( Status )) {
1163 DEBUG (( DEBUG_ERROR,
1164 "ERROR - Failed to create the close event, Status: %r\r\n",
1165 Status ));
1166 Tcp4CloseToken.CompletionToken.Event = NULL;
1167 break;
1168 }
1169 DEBUG (( DEBUG_INFO,
1170 "0x%08x: Close event open\r\n",
1171 Tcp4CloseToken.CompletionToken.Event ));
1172
1173 Status = gBS->CreateEvent ( 0,
1174 TPL_CALLBACK,
1175 NULL,
1176 NULL,
1177 &Tcp4ConnectToken.CompletionToken.Event );
1178 if ( EFI_ERROR ( Status )) {
1179 DEBUG (( DEBUG_ERROR,
1180 "ERROR - Failed to create the connect event, Status: %r\r\n",
1181 Status ));
1182 Tcp4ConnectToken.CompletionToken.Event = NULL;
1183 break;
1184 }
1185 DEBUG (( DEBUG_INFO,
1186 "0x%08x: Connect event open\r\n",
1187 Tcp4ConnectToken.CompletionToken.Event ));
1188
1189 Status = gBS->CreateEvent ( 0,
1190 TPL_CALLBACK,
1191 NULL,
1192 NULL,
1193 &Tcp4ListenToken.CompletionToken.Event );
1194 if ( EFI_ERROR ( Status )) {
1195 DEBUG (( DEBUG_ERROR,
1196 "ERROR - Failed to create the listen event, Status: %r\r\n",
1197 Status ));
1198 Tcp4ListenToken.CompletionToken.Event = NULL;
1199 break;
1200 }
1201 DEBUG (( DEBUG_INFO,
1202 "0x%08x: Listen event open\r\n",
1203 Tcp4ListenToken.CompletionToken.Event ));
1204
1205 Status = gBS->CreateEvent ( 0,
1206 TPL_CALLBACK,
1207 NULL,
1208 NULL,
1209 &Tcp4TxToken.CompletionToken.Event );
1210 if ( EFI_ERROR ( Status )) {
1211 DEBUG (( DEBUG_ERROR,
1212 "ERROR - Failed to create the TX event, Status: %r\r\n",
1213 Status ));
1214 Tcp4TxToken.CompletionToken.Event = NULL;
1215 break;
1216 }
1217 DEBUG (( DEBUG_INFO,
1218 "0x%08x: TX event open\r\n",
1219 Tcp4TxToken.CompletionToken.Event ));
1220
1221 //
1222 // Configure the local TCP port
1223 //
1224 Tcp4ConfigData.TimeToLive = 255;
1225 Tcp4ConfigData.TypeOfService = 0;
1226 Tcp4ConfigData.ControlOption = NULL;
1227 Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;
1228 Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;
1229 Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;
1230 Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;
1231 Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;
1232 Tcp4ConfigData.AccessPoint.StationPort = 0;
1233 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
1234 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );
1235 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );
1236 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );
1237 Tcp4ConfigData.AccessPoint.RemotePort = ntohs (((struct sockaddr_in *)&RemoteHostAddress)->sin_port);
1238 Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;
1239 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;
1240 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;
1241 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;
1242 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;
1243 Status = pTcp4Protocol->Configure ( pTcp4Protocol,
1244 &Tcp4ConfigData );
1245 if ( EFI_ERROR ( Status )) {
1246 DEBUG (( DEBUG_ERROR,
1247 "ERROR - Failed to configure TCP port, Status: %r\r\n",
1248 Status ));
1249 break;
1250 }
1251 DEBUG (( DEBUG_INFO,
1252 "0x%08x: TCP4 port configured\r\n",
1253 pTcp4Protocol ));
1254
1255 //
1256 // Connect to the remote TCP port
1257 //
1258 Status = pTcp4Protocol->Connect ( pTcp4Protocol,
1259 &Tcp4ConnectToken );
1260 if ( EFI_ERROR ( Status )) {
1261 DEBUG (( DEBUG_ERROR,
1262 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
1263 Status ));
1264 break;
1265 }
1266 Status = gBS->WaitForEvent ( 1,
1267 &Tcp4ConnectToken.CompletionToken.Event,
1268 &Index );
1269 if ( EFI_ERROR ( Status )) {
1270 DEBUG (( DEBUG_ERROR,
1271 "ERROR - Failed to wait for the connection, Status: %r\r\n",
1272 Status ));
1273 break;
1274 }
1275 Status = Tcp4ConnectToken.CompletionToken.Status;
1276 if ( EFI_ERROR ( Status )) {
1277 DEBUG (( DEBUG_WARN,
1278 "WARNING - Failed to connect to the remote system, Status: %r\r\n",
1279 Status ));
1280 break;
1281 }
1282 DEBUG (( DEBUG_INFO,
1283 "0x%08x: TCP4 port connected\r\n",
1284 pTcp4Protocol ));
1285 bTcp4Connected = TRUE;
1286
1287 //
1288 // Display the connection
1289 //
1290 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
1291 Print ( L"Connected to %d.%d.%d.%d:%d\r\n",
1292 pIpAddress[0],
1293 pIpAddress[1],
1294 pIpAddress[2],
1295 pIpAddress[3],
1296 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
1297 } while ( 0 );
1298
1299 if ( EFI_ERROR ( Status )) {
1300 //
1301 // Try again
1302 //
1303 Status = EFI_SUCCESS;
1304 }
1305 else {
1306 //
1307 // Semd data until the connection breaks
1308 //
1309 Status = Tcp4Send ( );
1310 }
1311
1312 //
1313 // Return the operation status
1314 //
1315 return Status;
1316 }
1317
1318
1319 /**
1320 Handle the timer callback
1321
1322 @param [in] Event Event that caused this callback
1323 @param [in] pContext Context for this routine
1324 **/
1325 VOID
1326 EFIAPI
1327 TimerCallback (
1328 IN EFI_EVENT Event,
1329 IN VOID * pContext
1330 )
1331 {
1332 UINT32 Average;
1333 UINT64 BitsPerSecond;
1334 UINT32 Index;
1335 UINT64 TotalBytes;
1336
1337 //
1338 // Notify the other code of the timer tick
1339 //
1340 bTick = TRUE;
1341
1342 //
1343 // Update the average bytes per second
1344 //
1345 if ( 0 != TotalBytesSent ) {
1346 BytesSent[ In ] = TotalBytesSent;
1347 TotalBytesSent = 0;
1348 In += 1;
1349 if ( DATA_SAMPLES <= In ) {
1350 In = 0;
1351 }
1352
1353 //
1354 // Separate the samples
1355 //
1356 if ( DATA_SAMPLES == Samples ) {
1357 Print ( L"---------- Stable average ----------\r\n" );
1358 }
1359 Samples += 1;
1360
1361 //
1362 // Compute the data rate
1363 //
1364 TotalBytes = 0;
1365 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {
1366 TotalBytes += BytesSent[ Index ];
1367 }
1368 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );
1369 BitsPerSecond = Average * 8;
1370
1371 //
1372 // Display the data rate
1373 //
1374 if (( RANGE_SWITCH >> 10 ) > Average ) {
1375 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1376 Average,
1377 BitsPerSecond );
1378 }
1379 else {
1380 BitsPerSecond /= 1000;
1381 if ( RANGE_SWITCH > Average ) {
1382 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1383 Average >> 10,
1384 (( Average & 0x3ff ) * 1000 ) >> 10,
1385 BitsPerSecond );
1386 }
1387 else {
1388 BitsPerSecond /= 1000;
1389 Average >>= 10;
1390 if ( RANGE_SWITCH > Average ) {
1391 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1392 Average >> 10,
1393 (( Average & 0x3ff ) * 1000 ) >> 10,
1394 BitsPerSecond );
1395 }
1396 else {
1397 BitsPerSecond /= 1000;
1398 Average >>= 10;
1399 if ( RANGE_SWITCH > Average ) {
1400 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1401 Average >> 10,
1402 (( Average & 0x3ff ) * 1000 ) >> 10,
1403 BitsPerSecond );
1404 }
1405 else {
1406 BitsPerSecond /= 1000;
1407 Average >>= 10;
1408 if ( RANGE_SWITCH > Average ) {
1409 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1410 Average >> 10,
1411 (( Average & 0x3ff ) * 1000 ) >> 10,
1412 BitsPerSecond );
1413 }
1414 else {
1415 BitsPerSecond /= 1000;
1416 Average >>= 10;
1417 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1418 Average >> 10,
1419 (( Average & 0x3ff ) * 1000 ) >> 10,
1420 BitsPerSecond );
1421 }
1422 }
1423 }
1424 }
1425 }
1426 }
1427 }
1428
1429
1430 /**
1431 Create the timer
1432
1433 @retval EFI_SUCCESS The timer was successfully created
1434 @retval Other Timer initialization failed
1435 **/
1436 EFI_STATUS
1437 TimerCreate (
1438 )
1439 {
1440 EFI_STATUS Status;
1441
1442 //
1443 // Create the timer
1444 //
1445 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
1446 TPL_DATASOURCE,
1447 TimerCallback,
1448 NULL,
1449 &pTimer );
1450 if ( EFI_ERROR ( Status )) {
1451 DEBUG (( DEBUG_ERROR,
1452 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1453 Status ));
1454 }
1455 else {
1456 DEBUG (( DEBUG_INFO,
1457 "0x%08x: Timer created\r\n",
1458 pTimer ));
1459 }
1460
1461 //
1462 // Return the operation status
1463 //
1464 return Status;
1465 }
1466
1467
1468 /**
1469 Stop the timer
1470
1471 @retval EFI_SUCCESS The timer was stopped successfully
1472 @retval Other The timer failed to stop
1473 **/
1474 EFI_STATUS
1475 TimerStop (
1476 )
1477 {
1478 EFI_STATUS Status;
1479
1480 //
1481 // Assume success
1482 //
1483 Status = EFI_SUCCESS;
1484
1485 //
1486 // Determine if the timer is running
1487 //
1488 if ( bTimerRunning ) {
1489 //
1490 // Stop the timer
1491 //
1492 Status = gBS->SetTimer ( pTimer,
1493 TimerCancel,
1494 0 );
1495 if ( EFI_ERROR ( Status )) {
1496 DEBUG (( DEBUG_ERROR,
1497 "ERROR - Failed to stop the timer, Status: %r\r\n",
1498 Status ));
1499 }
1500 else {
1501 //
1502 // Timer timer is now stopped
1503 //
1504 bTimerRunning = FALSE;
1505 DEBUG (( DEBUG_INFO,
1506 "0x%08x: Timer stopped\r\n",
1507 pTimer ));
1508 }
1509 }
1510
1511 //
1512 // Return the operation status
1513 //
1514 return Status;
1515 }
1516
1517
1518 /**
1519 Start the timer
1520
1521 @param [in] Milliseconds The number of milliseconds between timer callbacks
1522
1523 @retval EFI_SUCCESS The timer was successfully created
1524 @retval Other Timer initialization failed
1525 **/
1526 EFI_STATUS
1527 TimerStart (
1528 UINTN Milliseconds
1529 )
1530 {
1531 EFI_STATUS Status;
1532 UINT64 TimeDelay;
1533
1534 //
1535 // Stop the timer if necessary
1536 //
1537 Status = EFI_SUCCESS;
1538 if ( bTimerRunning ) {
1539 Status = TimerStop ( );
1540 }
1541 if ( !EFI_ERROR ( Status )) {
1542 //
1543 // Compute the new delay
1544 //
1545 TimeDelay = Milliseconds;
1546 TimeDelay *= 1000 * 10;
1547
1548 //
1549 // Start the timer
1550 //
1551 Status = gBS->SetTimer ( pTimer,
1552 TimerPeriodic,
1553 TimeDelay );
1554 if ( EFI_ERROR ( Status )) {
1555 DEBUG (( DEBUG_ERROR,
1556 "ERROR - Failed to start the timer, Status: %r\r\n",
1557 Status ));
1558 }
1559 else {
1560 //
1561 // The timer is now running
1562 //
1563 bTimerRunning = TRUE;
1564 DEBUG (( DEBUG_INFO,
1565 "0x%08x: Timer running\r\n",
1566 pTimer ));
1567 }
1568 }
1569
1570 //
1571 // Return the operation status
1572 //
1573 return Status;
1574 }
1575
1576
1577 /**
1578 Destroy the timer
1579
1580 @retval EFI_SUCCESS The timer was destroyed successfully
1581 @retval Other Failed to destroy the timer
1582 **/
1583 EFI_STATUS
1584 TimerDestroy (
1585 )
1586 {
1587 EFI_STATUS Status;
1588
1589 //
1590 // Assume success
1591 //
1592 Status = EFI_SUCCESS;
1593
1594 //
1595 // Determine if the timer is running
1596 //
1597 if ( bTimerRunning ) {
1598 //
1599 // Stop the timer
1600 //
1601 Status = TimerStop ( );
1602 }
1603 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
1604 //
1605 // Done with this timer
1606 //
1607 Status = gBS->CloseEvent ( pTimer );
1608 if ( EFI_ERROR ( Status )) {
1609 DEBUG (( DEBUG_ERROR,
1610 "ERROR - Failed to free the timer event, Status: %r\r\n",
1611 Status ));
1612 }
1613 else {
1614 DEBUG (( DEBUG_INFO,
1615 "0x%08x: Timer Destroyed\r\n",
1616 pTimer ));
1617 pTimer = NULL;
1618 }
1619 }
1620
1621 //
1622 // Return the operation status
1623 //
1624 return Status;
1625 }
1626
1627
1628 /**
1629 Send data to the DataSink program to test a network's bandwidth.
1630
1631 @param [in] Argc The number of arguments
1632 @param [in] Argv The argument value array
1633
1634 @retval 0 The application exited normally.
1635 @retval Other An error occurred.
1636 **/
1637 int
1638 main (
1639 IN int Argc,
1640 IN char **Argv
1641 )
1642 {
1643 EFI_STATUS (* pClose) ();
1644 EFI_STATUS (* pOpen) ();
1645 EFI_STATUS Status;
1646
1647 DEBUG (( DEBUG_INFO,
1648 "DataSource starting\r\n" ));
1649
1650 //
1651 // Validate the command line
1652 //
1653 if ( 2 > Argc ) {
1654 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] );
1655 return -1;
1656 }
1657
1658 //
1659 // Determine if TCP should be used
1660 //
1661 bTcp4 = (BOOLEAN)( 2 < Argc );
1662
1663 //
1664 // Determine the support routines
1665 //
1666 if ( bTcp4 ) {
1667 pOpen = Tcp4Open;
1668 pClose = Tcp4Close;
1669 bTcp4Connecting = TRUE;
1670 }
1671 else {
1672 pOpen = SocketOpen;
1673 pClose = SocketClose;
1674 }
1675
1676 //
1677 // Use for/break instead of goto
1678 //
1679 for ( ; ; ) {
1680 //
1681 // No bytes sent so far
1682 //
1683 TotalBytesSent = 0;
1684 Samples = 0;
1685 memset ( &BytesSent, 0, sizeof ( BytesSent ));
1686
1687 //
1688 // Get the IP address
1689 //
1690 pRemoteHost = Argv[1];
1691 Status = IpAddress ( );
1692 if ( EFI_ERROR ( Status )) {
1693 break;
1694 }
1695
1696 //
1697 // Create the timer
1698 //
1699 bTick = TRUE;
1700 Status = TimerCreate ( );
1701 if ( EFI_ERROR ( Status )) {
1702 break;
1703 }
1704
1705 //
1706 // Loop forever abusing the specified system
1707 //
1708 do {
1709 //
1710 // Start a timer to perform connection polling and display updates
1711 //
1712 Status = TimerStart ( 2 * 1000 );
1713 if ( EFI_ERROR ( Status )) {
1714 break;
1715 }
1716
1717 //
1718 // Open the network connection and send the data
1719 //
1720 Status = pOpen ( );
1721 if ( EFI_ERROR ( Status )) {
1722 break;
1723 }
1724
1725 //
1726 // Done with the network connection
1727 //
1728 Status = pClose ( );
1729 } while ( !EFI_ERROR ( Status ));
1730
1731 //
1732 // Close the network connection if necessary
1733 //
1734 pClose ( );
1735
1736 //
1737 // All done
1738 //
1739 break;
1740 }
1741
1742 //
1743 // Stop the timer if necessary
1744 //
1745 TimerStop ( );
1746 TimerDestroy ( );
1747
1748 //
1749 // Return the operation status
1750 //
1751 DEBUG (( DEBUG_INFO,
1752 "DataSource exiting, Status: %r\r\n",
1753 Status ));
1754 return Status;
1755 }