]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Sockets/DataSource/DataSource.c
Fix some errors detected by the GCC 4.4 compiler.
[mirror_edk2.git] / AppPkg / Applications / Sockets / DataSource / DataSource.c
1 /** @file
2 Data source for network testing.
3
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
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 htons ( 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 htons ( 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 htons ( 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 htons ( pRemoteAddress6->sin6_port ));
465 }
466 }
467 else {
468 //
469 // Close the socket and try again
470 //
471 if ( EAGAIN != errno ) {
472 Status = EFI_NOT_STARTED;
473 break;
474 }
475 }
476 } while ( -1 == ConnectStatus );
477
478 //
479 // Return the operation status
480 //
481 return Status;
482 }
483
484
485 /**
486 Create the socket
487
488 @param [in] Family Network family, AF_INET or AF_INET6
489
490 @retval EFI_SUCCESS The application is running normally
491 @retval Other The user stopped the application
492 **/
493 EFI_STATUS
494 SocketNew (
495 sa_family_t Family
496 )
497 {
498 EFI_STATUS Status;
499
500 //
501 // Loop creating the socket
502 //
503 DEBUG (( DEBUG_INFO,
504 "Creating the socket\r\n" ));
505 do {
506 //
507 // Check for user stop request
508 //
509 Status = ControlCCheck ( );
510 if ( EFI_ERROR ( Status )) {
511 break;
512 }
513
514 //
515 // Attempt to create the socket
516 //
517 Socket = socket ( Family,
518 SOCK_STREAM,
519 IPPROTO_TCP );
520 if ( -1 != Socket ) {
521 DEBUG (( DEBUG_INFO,
522 "0x%08x: Socket created\r\n",
523 Socket ));
524 break;
525 }
526 } while ( -1 == Socket );
527
528 //
529 // Return the operation status
530 //
531 return Status;
532 }
533
534
535 /**
536 Send data over the socket
537
538 @retval EFI_SUCCESS The application is running normally
539 @retval Other The user stopped the application
540 **/
541 EFI_STATUS
542 SocketSend (
543 )
544 {
545 size_t BytesSent;
546 EFI_STATUS Status;
547 EFI_TPL TplPrevious;
548
549 //
550 // Restart the timer
551 //
552 TimerStart ( 1 * 1000 );
553
554 //
555 // Loop until the connection breaks or the user stops
556 //
557 do {
558 //
559 // Check for user stop request
560 //
561 Status = ControlCCheck ( );
562 if ( EFI_ERROR ( Status )) {
563 break;
564 }
565
566 //
567 // Send some bytes
568 //
569 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));
570 if ( -1 == BytesSent ) {
571 DEBUG (( DEBUG_INFO,
572 "ERROR: send failed, errno: %d\r\n",
573 errno ));
574
575 //
576 // Try again
577 //
578 Status = EFI_SUCCESS;
579
580 //
581 // Exit now
582 //
583 Status = EFI_NOT_STARTED;
584 break;
585 }
586
587 //
588 // Synchronize with the TimerCallback routine
589 //
590 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
591
592 //
593 // Account for the data sent
594 //
595 TotalBytesSent += BytesSent;
596
597 //
598 // Release the TimerCallback routine synchronization
599 //
600 gBS->RestoreTPL ( TplPrevious );
601 } while ( !EFI_ERROR ( Status ));
602
603 //
604 // Return the operation status
605 //
606 return Status;
607 }
608
609
610 /**
611 Open the network connection and send the data.
612
613 @retval EFI_SUCCESS Continue looping
614 @retval other Stopped by user's Control-C input
615
616 **/
617 EFI_STATUS
618 SocketOpen (
619 )
620 {
621 EFI_STATUS Status;
622
623 //
624 // Use do/while and break instead of goto
625 //
626 do {
627 //
628 // Wait for the network layer to initialize
629 //
630 Status = SocketNew ( RemoteHostAddress.sin6_family );
631 if ( EFI_ERROR ( Status )) {
632 break;
633 }
634
635 //
636 // Wait for the remote network application to start
637 //
638 Status = SocketConnect ( );
639 if ( EFI_NOT_STARTED == Status ) {
640 Status = SocketClose ( );
641 continue;
642 }
643 else if ( EFI_SUCCESS != Status ) {
644 //
645 // Control-C
646 //
647 break;
648 }
649
650 //
651 // Send data until the connection breaks
652 //
653 Status = SocketSend ( );
654 if ( EFI_ERROR ( Status )) {
655 break;
656 }
657 } while ( FALSE );
658
659 //
660 // Return the operation status
661 //
662 return Status;
663 }
664
665
666 /**
667 Close the TCP connection
668
669 @retval EFI_SUCCESS The application is running normally
670 @retval Other The user stopped the application
671 **/
672 EFI_STATUS
673 Tcp4Close (
674 )
675 {
676 UINTN Index;
677 UINT8 * pIpAddress;
678 EFI_STATUS Status;
679
680 //
681 // Close the port
682 //
683 if ( bTcp4Connected ) {
684 Tcp4CloseToken.AbortOnClose = TRUE;
685 Status = pTcp4Protocol->Close ( pTcp4Protocol,
686 &Tcp4CloseToken );
687 if ( EFI_ERROR ( Status )) {
688 DEBUG (( DEBUG_ERROR,
689 "ERROR - Failed to start the TCP port close, Status: %r\r\n",
690 Status ));
691 }
692 else {
693 Status = gBS->WaitForEvent ( 1,
694 &Tcp4CloseToken.CompletionToken.Event,
695 &Index );
696 if ( EFI_ERROR ( Status )) {
697 DEBUG (( DEBUG_ERROR,
698 "ERROR - Failed to wait for close event, Status: %r\r\n",
699 Status ));
700 }
701 else {
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",
706 Status ));
707 }
708 else {
709 DEBUG (( DEBUG_INFO,
710 "0x%08x: TCP port closed\r\n",
711 pTcp4Protocol ));
712 bTcp4Connected = FALSE;
713
714 //
715 // Display the port closed message
716 //
717 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
718 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",
719 pIpAddress[0],
720 pIpAddress[1],
721 pIpAddress[2],
722 pIpAddress[3],
723 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
724 }
725 }
726 }
727 }
728
729 //
730 // Release the events
731 //
732 if ( NULL != Tcp4TxToken.CompletionToken.Event ) {
733 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );
734 if ( !EFI_ERROR ( Status )) {
735 DEBUG (( DEBUG_INFO,
736 "0x%08x: TX event closed\r\n",
737 Tcp4TxToken.CompletionToken.Event ));
738 Tcp4TxToken.CompletionToken.Event = NULL;
739 }
740 else {
741 DEBUG (( DEBUG_ERROR,
742 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
743 Status ));
744 }
745 }
746
747 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {
748 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );
749 if ( !EFI_ERROR ( Status )) {
750 DEBUG (( DEBUG_INFO,
751 "0x%08x: Listen event closed\r\n",
752 Tcp4ListenToken.CompletionToken.Event ));
753 Tcp4ListenToken.CompletionToken.Event = NULL;
754 }
755 else {
756 DEBUG (( DEBUG_ERROR,
757 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
758 Status ));
759 }
760 }
761
762 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {
763 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );
764 if ( !EFI_ERROR ( Status )) {
765 DEBUG (( DEBUG_INFO,
766 "0x%08x: Connect event closed\r\n",
767 Tcp4ConnectToken.CompletionToken.Event ));
768 Tcp4ConnectToken.CompletionToken.Event = NULL;
769 }
770 else {
771 DEBUG (( DEBUG_ERROR,
772 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
773 Status ));
774 }
775 }
776
777 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {
778 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );
779 if ( !EFI_ERROR ( Status )) {
780 DEBUG (( DEBUG_INFO,
781 "0x%08x: Close event closed\r\n",
782 Tcp4CloseToken.CompletionToken.Event ));
783 Tcp4CloseToken.CompletionToken.Event = NULL;
784 }
785 else {
786 DEBUG (( DEBUG_ERROR,
787 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
788 Status ));
789 }
790 }
791
792 //
793 // Close the TCP protocol
794 //
795 if ( NULL != pTcp4Protocol ) {
796 Status = gBS->CloseProtocol ( Tcp4Handle,
797 &gEfiTcp4ProtocolGuid,
798 gImageHandle,
799 NULL );
800 if ( EFI_ERROR ( Status )) {
801 DEBUG (( DEBUG_ERROR,
802 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
803 Status ));
804 }
805 else {
806 DEBUG (( DEBUG_INFO,
807 "0x%08x: TCP4 protocol closed\r\n",
808 pTcp4Protocol ));
809 pTcp4Protocol = NULL;
810 }
811 }
812
813 //
814 // Done with the TCP service
815 //
816 if ( NULL != Tcp4Handle ) {
817 Status = pTcp4Service->DestroyChild ( pTcp4Service,
818 Tcp4Handle );
819 if ( EFI_ERROR ( Status )) {
820 DEBUG (( DEBUG_ERROR,
821 "ERROR - Failed to release TCP service handle, Status: %r\r\n",
822 Status ));
823 }
824 else {
825 DEBUG (( DEBUG_INFO,
826 "Ox%08x: TCP service closed\r\n",
827 Tcp4Handle ));
828 Tcp4Handle = NULL;
829 }
830 }
831
832 //
833 // Close the service protocol
834 //
835 if ( NULL != pTcp4Service ) {
836 Status = gBS->CloseProtocol ( Tcp4Controller,
837 &gEfiTcp4ServiceBindingProtocolGuid,
838 gImageHandle,
839 NULL );
840 if ( !EFI_ERROR ( Status )) {
841 DEBUG (( DEBUG_INFO,
842 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
843 Tcp4Controller ));
844 pTcp4Service = NULL;
845 }
846 else {
847 DEBUG (( DEBUG_ERROR,
848 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
849 Status ));
850 }
851 }
852 Tcp4Controller = NULL;
853 bTcp4Connecting = TRUE;
854
855 //
856 // Mark the connection as closed
857 //
858 Status = EFI_SUCCESS;
859
860 //
861 // Return the operation status
862 //
863 return Status;
864 }
865
866
867 /**
868 Locate TCP protocol
869
870 @retval EFI_SUCCESS Protocol found
871 @retval other Protocl not found
872 **/
873 EFI_STATUS
874 Tcp4Locate (
875 )
876 {
877 UINTN HandleCount;
878 EFI_HANDLE * pHandles;
879 UINT8 * pIpAddress;
880 EFI_STATUS Status;
881
882 //
883 // Use do/while and break instead of goto
884 //
885 do {
886 //
887 // Attempt to locate the next TCP adapter in the system
888 //
889 Status = gBS->LocateHandleBuffer ( ByProtocol,
890 &gEfiTcp4ServiceBindingProtocolGuid,
891 NULL,
892 &HandleCount,
893 &pHandles );
894 if ( EFI_ERROR ( Status )) {
895 DEBUG (( DEBUG_WARN,
896 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
897 Status ));
898 break;
899 }
900
901 //
902 // Wrap the index if necessary
903 //
904 if ( HandleCount <= Tcp4Index ) {
905 Tcp4Index = 0;
906
907 //
908 // Wait for the next timer tick
909 //
910 do {
911 } while ( !bTick );
912 bTick = FALSE;
913 }
914
915 //
916 // Display the connecting message
917 //
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",
921 pIpAddress[0],
922 pIpAddress[1],
923 pIpAddress[2],
924 pIpAddress[3],
925 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
926 bTcp4Connecting = FALSE;
927 }
928
929 //
930 // Open the network controller's service protocol
931 //
932 Tcp4Controller = pHandles[ Tcp4Index++ ];
933 Status = gBS->OpenProtocol (
934 Tcp4Controller,
935 &gEfiTcp4ServiceBindingProtocolGuid,
936 (VOID **) &pTcp4Service,
937 gImageHandle,
938 NULL,
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",
943 Tcp4Controller ));
944 Tcp4Controller = NULL;
945 break;
946 }
947 DEBUG (( DEBUG_INFO,
948 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
949 Tcp4Controller ));
950
951 //
952 // Connect to the TCP service
953 //
954 Status = pTcp4Service->CreateChild ( pTcp4Service,
955 &Tcp4Handle );
956 if ( EFI_ERROR ( Status )) {
957 DEBUG (( DEBUG_ERROR,
958 "ERROR - Failed to open TCP service, Status: %r\r\n",
959 Status ));
960 Tcp4Handle = NULL;
961 break;
962 }
963 DEBUG (( DEBUG_INFO,
964 "Ox%08x: TCP service opened\r\n",
965 Tcp4Handle ));
966
967 //
968 // Locate the TCP protcol
969 //
970 Status = gBS->OpenProtocol ( Tcp4Handle,
971 &gEfiTcp4ProtocolGuid,
972 (VOID **)&pTcp4Protocol,
973 gImageHandle,
974 NULL,
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",
979 Status ));
980 pTcp4Protocol = NULL;
981 break;
982 }
983 DEBUG (( DEBUG_INFO,
984 "0x%08x: TCP4 protocol opened\r\n",
985 pTcp4Protocol ));
986 }while ( FALSE );
987
988 //
989 // Release the handle buffer
990 //
991 gBS->FreePool ( pHandles );
992
993 //
994 // Return the operation status
995 //
996 return Status;
997 }
998
999
1000 /**
1001 Send data over the TCP4 connection
1002
1003 @retval EFI_SUCCESS The application is running normally
1004 @retval Other The user stopped the application
1005 **/
1006 EFI_STATUS
1007 Tcp4Send (
1008 )
1009 {
1010 UINTN Index;
1011 EFI_TCP4_TRANSMIT_DATA Packet;
1012 EFI_STATUS Status;
1013 EFI_TPL TplPrevious;
1014
1015 //
1016 // Restart the timer
1017 //
1018 TimerStart ( 1 * 1000 );
1019
1020 //
1021 // Initialize the packet
1022 //
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;
1030
1031 //
1032 // Loop until the connection breaks or the user stops
1033 //
1034 do {
1035 //
1036 // Check for user stop request
1037 //
1038 Status = ControlCCheck ( );
1039 if ( EFI_ERROR ( Status )) {
1040 break;
1041 }
1042
1043 //
1044 // Send some bytes
1045 //
1046 Status = pTcp4Protocol->Transmit ( pTcp4Protocol,
1047 &Tcp4TxToken );
1048 if ( EFI_ERROR ( Status )) {
1049 DEBUG (( DEBUG_ERROR,
1050 "ERROR - Failed to start the transmit, Status: %r\r\n",
1051 Status ));
1052
1053 //
1054 // Try again
1055 //
1056 Status = EFI_SUCCESS;
1057 break;
1058 }
1059
1060 //
1061 // Wait for the transmit to complete
1062 //
1063 Status = gBS->WaitForEvent ( 1,
1064 &Tcp4TxToken.CompletionToken.Event,
1065 &Index );
1066 if ( EFI_ERROR ( Status )) {
1067 DEBUG (( DEBUG_ERROR,
1068 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
1069 Status ));
1070
1071 //
1072 // Try again
1073 //
1074 Status = EFI_SUCCESS;
1075 break;
1076 }
1077
1078 //
1079 // Get the transmit status
1080 //
1081 Status = Tcp4TxToken.CompletionToken.Status;
1082 if ( EFI_ERROR ( Status )) {
1083 DEBUG (( DEBUG_WARN,
1084 "WARNING - Failed the transmission, Status: %r\r\n",
1085 Status ));
1086
1087 //
1088 // Try again
1089 //
1090 Status = EFI_SUCCESS;
1091
1092 //
1093 // Exit now
1094 //
1095 Status = EFI_NOT_STARTED;
1096 break;
1097 }
1098
1099 //
1100 // Synchronize with the TimerCallback routine
1101 //
1102 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
1103
1104 //
1105 // Account for the data sent
1106 //
1107 TotalBytesSent += Packet.DataLength;
1108
1109 //
1110 // Release the TimerCallback routine synchronization
1111 //
1112 gBS->RestoreTPL ( TplPrevious );
1113 } while ( !EFI_ERROR ( Status ));
1114
1115 //
1116 // Return the operation status
1117 //
1118 return Status;
1119 }
1120
1121
1122 /**
1123 Open the network connection and send the data.
1124
1125 @retval EFI_SUCCESS Continue looping
1126 @retval other Stopped by user's Control-C input
1127
1128 **/
1129 EFI_STATUS
1130 Tcp4Open (
1131 )
1132 {
1133 UINTN Index;
1134 UINT8 * pIpAddress;
1135 EFI_STATUS Status;
1136
1137 //
1138 // Use do/while and break instead of goto
1139 //
1140 do {
1141 //
1142 // Locate the TCP protocol
1143 //
1144 Status = Tcp4Locate ( );
1145 if ( EFI_ERROR ( Status )) {
1146 break;
1147 }
1148
1149 //
1150 // Create the necessary events
1151 //
1152 Status = gBS->CreateEvent ( 0,
1153 TPL_CALLBACK,
1154 NULL,
1155 NULL,
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",
1160 Status ));
1161 Tcp4CloseToken.CompletionToken.Event = NULL;
1162 break;
1163 }
1164 DEBUG (( DEBUG_INFO,
1165 "0x%08x: Close event open\r\n",
1166 Tcp4CloseToken.CompletionToken.Event ));
1167
1168 Status = gBS->CreateEvent ( 0,
1169 TPL_CALLBACK,
1170 NULL,
1171 NULL,
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",
1176 Status ));
1177 Tcp4ConnectToken.CompletionToken.Event = NULL;
1178 break;
1179 }
1180 DEBUG (( DEBUG_INFO,
1181 "0x%08x: Connect event open\r\n",
1182 Tcp4ConnectToken.CompletionToken.Event ));
1183
1184 Status = gBS->CreateEvent ( 0,
1185 TPL_CALLBACK,
1186 NULL,
1187 NULL,
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",
1192 Status ));
1193 Tcp4ListenToken.CompletionToken.Event = NULL;
1194 break;
1195 }
1196 DEBUG (( DEBUG_INFO,
1197 "0x%08x: Listen event open\r\n",
1198 Tcp4ListenToken.CompletionToken.Event ));
1199
1200 Status = gBS->CreateEvent ( 0,
1201 TPL_CALLBACK,
1202 NULL,
1203 NULL,
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",
1208 Status ));
1209 Tcp4TxToken.CompletionToken.Event = NULL;
1210 break;
1211 }
1212 DEBUG (( DEBUG_INFO,
1213 "0x%08x: TX event open\r\n",
1214 Tcp4TxToken.CompletionToken.Event ));
1215
1216 //
1217 // Configure the local TCP port
1218 //
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,
1239 &Tcp4ConfigData );
1240 if ( EFI_ERROR ( Status )) {
1241 DEBUG (( DEBUG_ERROR,
1242 "ERROR - Failed to configure TCP port, Status: %r\r\n",
1243 Status ));
1244 break;
1245 }
1246 DEBUG (( DEBUG_INFO,
1247 "0x%08x: TCP4 port configured\r\n",
1248 pTcp4Protocol ));
1249
1250 //
1251 // Connect to the remote TCP port
1252 //
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",
1258 Status ));
1259 break;
1260 }
1261 Status = gBS->WaitForEvent ( 1,
1262 &Tcp4ConnectToken.CompletionToken.Event,
1263 &Index );
1264 if ( EFI_ERROR ( Status )) {
1265 DEBUG (( DEBUG_ERROR,
1266 "ERROR - Failed to wait for the connection, Status: %r\r\n",
1267 Status ));
1268 break;
1269 }
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",
1274 Status ));
1275 break;
1276 }
1277 DEBUG (( DEBUG_INFO,
1278 "0x%08x: TCP4 port connected\r\n",
1279 pTcp4Protocol ));
1280 bTcp4Connected = TRUE;
1281
1282 //
1283 // Display the connection
1284 //
1285 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
1286 Print ( L"Connected to %d.%d.%d.%d:%d\r\n",
1287 pIpAddress[0],
1288 pIpAddress[1],
1289 pIpAddress[2],
1290 pIpAddress[3],
1291 htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
1292 } while ( 0 );
1293
1294 if ( EFI_ERROR ( Status )) {
1295 //
1296 // Try again
1297 //
1298 Status = EFI_SUCCESS;
1299 }
1300 else {
1301 //
1302 // Semd data until the connection breaks
1303 //
1304 Status = Tcp4Send ( );
1305 }
1306
1307 //
1308 // Return the operation status
1309 //
1310 return Status;
1311 }
1312
1313
1314 /**
1315 Handle the timer callback
1316
1317 @param [in] Event Event that caused this callback
1318 @param [in] pContext Context for this routine
1319 **/
1320 VOID
1321 TimerCallback (
1322 IN EFI_EVENT Event,
1323 IN VOID * pContext
1324 )
1325 {
1326 UINT32 Average;
1327 UINT64 BitsPerSecond;
1328 UINT32 Index;
1329 UINT64 TotalBytes;
1330
1331 //
1332 // Notify the other code of the timer tick
1333 //
1334 bTick = TRUE;
1335
1336 //
1337 // Update the average bytes per second
1338 //
1339 if ( 0 != TotalBytesSent ) {
1340 BytesSent[ In ] = TotalBytesSent;
1341 TotalBytesSent = 0;
1342 In += 1;
1343 if ( DATA_SAMPLES <= In ) {
1344 In = 0;
1345 }
1346
1347 //
1348 // Separate the samples
1349 //
1350 if ( DATA_SAMPLES == Samples ) {
1351 Print ( L"---------- Stable average ----------\r\n" );
1352 }
1353 Samples += 1;
1354
1355 //
1356 // Compute the data rate
1357 //
1358 TotalBytes = 0;
1359 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {
1360 TotalBytes += BytesSent[ Index ];
1361 }
1362 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );
1363 BitsPerSecond = Average * 8;
1364
1365 //
1366 // Display the data rate
1367 //
1368 if (( RANGE_SWITCH >> 10 ) > Average ) {
1369 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1370 Average,
1371 BitsPerSecond );
1372 }
1373 else {
1374 BitsPerSecond /= 1000;
1375 if ( RANGE_SWITCH > Average ) {
1376 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1377 Average >> 10,
1378 (( Average & 0x3ff ) * 1000 ) >> 10,
1379 BitsPerSecond );
1380 }
1381 else {
1382 BitsPerSecond /= 1000;
1383 Average >>= 10;
1384 if ( RANGE_SWITCH > Average ) {
1385 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1386 Average >> 10,
1387 (( Average & 0x3ff ) * 1000 ) >> 10,
1388 BitsPerSecond );
1389 }
1390 else {
1391 BitsPerSecond /= 1000;
1392 Average >>= 10;
1393 if ( RANGE_SWITCH > Average ) {
1394 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1395 Average >> 10,
1396 (( Average & 0x3ff ) * 1000 ) >> 10,
1397 BitsPerSecond );
1398 }
1399 else {
1400 BitsPerSecond /= 1000;
1401 Average >>= 10;
1402 if ( RANGE_SWITCH > Average ) {
1403 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1404 Average >> 10,
1405 (( Average & 0x3ff ) * 1000 ) >> 10,
1406 BitsPerSecond );
1407 }
1408 else {
1409 BitsPerSecond /= 1000;
1410 Average >>= 10;
1411 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1412 Average >> 10,
1413 (( Average & 0x3ff ) * 1000 ) >> 10,
1414 BitsPerSecond );
1415 }
1416 }
1417 }
1418 }
1419 }
1420 }
1421 }
1422
1423
1424 /**
1425 Create the timer
1426
1427 @retval EFI_SUCCESS The timer was successfully created
1428 @retval Other Timer initialization failed
1429 **/
1430 EFI_STATUS
1431 TimerCreate (
1432 )
1433 {
1434 EFI_STATUS Status;
1435
1436 //
1437 // Create the timer
1438 //
1439 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
1440 TPL_DATASOURCE,
1441 TimerCallback,
1442 NULL,
1443 &pTimer );
1444 if ( EFI_ERROR ( Status )) {
1445 DEBUG (( DEBUG_ERROR,
1446 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1447 Status ));
1448 }
1449 else {
1450 DEBUG (( DEBUG_INFO,
1451 "0x%08x: Timer created\r\n",
1452 pTimer ));
1453 }
1454
1455 //
1456 // Return the operation status
1457 //
1458 return Status;
1459 }
1460
1461
1462 /**
1463 Stop the timer
1464
1465 @retval EFI_SUCCESS The timer was stopped successfully
1466 @retval Other The timer failed to stop
1467 **/
1468 EFI_STATUS
1469 TimerStop (
1470 )
1471 {
1472 EFI_STATUS Status;
1473
1474 //
1475 // Assume success
1476 //
1477 Status = EFI_SUCCESS;
1478
1479 //
1480 // Determine if the timer is running
1481 //
1482 if ( bTimerRunning ) {
1483 //
1484 // Stop the timer
1485 //
1486 Status = gBS->SetTimer ( pTimer,
1487 TimerCancel,
1488 0 );
1489 if ( EFI_ERROR ( Status )) {
1490 DEBUG (( DEBUG_ERROR,
1491 "ERROR - Failed to stop the timer, Status: %r\r\n",
1492 Status ));
1493 }
1494 else {
1495 //
1496 // Timer timer is now stopped
1497 //
1498 bTimerRunning = FALSE;
1499 DEBUG (( DEBUG_INFO,
1500 "0x%08x: Timer stopped\r\n",
1501 pTimer ));
1502 }
1503 }
1504
1505 //
1506 // Return the operation status
1507 //
1508 return Status;
1509 }
1510
1511
1512 /**
1513 Start the timer
1514
1515 @param [in] Milliseconds The number of milliseconds between timer callbacks
1516
1517 @retval EFI_SUCCESS The timer was successfully created
1518 @retval Other Timer initialization failed
1519 **/
1520 EFI_STATUS
1521 TimerStart (
1522 UINTN Milliseconds
1523 )
1524 {
1525 EFI_STATUS Status;
1526 UINT64 TimeDelay;
1527
1528 //
1529 // Stop the timer if necessary
1530 //
1531 Status = EFI_SUCCESS;
1532 if ( bTimerRunning ) {
1533 Status = TimerStop ( );
1534 }
1535 if ( !EFI_ERROR ( Status )) {
1536 //
1537 // Compute the new delay
1538 //
1539 TimeDelay = Milliseconds;
1540 TimeDelay *= 1000 * 10;
1541
1542 //
1543 // Start the timer
1544 //
1545 Status = gBS->SetTimer ( pTimer,
1546 TimerPeriodic,
1547 TimeDelay );
1548 if ( EFI_ERROR ( Status )) {
1549 DEBUG (( DEBUG_ERROR,
1550 "ERROR - Failed to start the timer, Status: %r\r\n",
1551 Status ));
1552 }
1553 else {
1554 //
1555 // The timer is now running
1556 //
1557 bTimerRunning = TRUE;
1558 DEBUG (( DEBUG_INFO,
1559 "0x%08x: Timer running\r\n",
1560 pTimer ));
1561 }
1562 }
1563
1564 //
1565 // Return the operation status
1566 //
1567 return Status;
1568 }
1569
1570
1571 /**
1572 Destroy the timer
1573
1574 @retval EFI_SUCCESS The timer was destroyed successfully
1575 @retval Other Failed to destroy the timer
1576 **/
1577 EFI_STATUS
1578 TimerDestroy (
1579 )
1580 {
1581 EFI_STATUS Status;
1582
1583 //
1584 // Assume success
1585 //
1586 Status = EFI_SUCCESS;
1587
1588 //
1589 // Determine if the timer is running
1590 //
1591 if ( bTimerRunning ) {
1592 //
1593 // Stop the timer
1594 //
1595 Status = TimerStop ( );
1596 }
1597 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
1598 //
1599 // Done with this timer
1600 //
1601 Status = gBS->CloseEvent ( pTimer );
1602 if ( EFI_ERROR ( Status )) {
1603 DEBUG (( DEBUG_ERROR,
1604 "ERROR - Failed to free the timer event, Status: %r\r\n",
1605 Status ));
1606 }
1607 else {
1608 DEBUG (( DEBUG_INFO,
1609 "0x%08x: Timer Destroyed\r\n",
1610 pTimer ));
1611 pTimer = NULL;
1612 }
1613 }
1614
1615 //
1616 // Return the operation status
1617 //
1618 return Status;
1619 }
1620
1621
1622 /**
1623 Send data to the DataSink program to test a network's bandwidth.
1624
1625 @param [in] Argc The number of arguments
1626 @param [in] Argv The argument value array
1627
1628 @retval 0 The application exited normally.
1629 @retval Other An error occurred.
1630 **/
1631 int
1632 main (
1633 IN int Argc,
1634 IN char **Argv
1635 )
1636 {
1637 EFI_STATUS (* pClose) ();
1638 EFI_STATUS (* pOpen) ();
1639 EFI_STATUS Status;
1640
1641 DEBUG (( DEBUG_INFO,
1642 "DataSource starting\r\n" ));
1643
1644 //
1645 // Validate the command line
1646 //
1647 if ( 2 > Argc ) {
1648 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] );
1649 return -1;
1650 }
1651
1652 //
1653 // Determine if TCP should be used
1654 //
1655 bTcp4 = (BOOLEAN)( 2 < Argc );
1656
1657 //
1658 // Determine the support routines
1659 //
1660 if ( bTcp4 ) {
1661 pOpen = Tcp4Open;
1662 pClose = Tcp4Close;
1663 bTcp4Connecting = TRUE;
1664 }
1665 else {
1666 pOpen = SocketOpen;
1667 pClose = SocketClose;
1668 }
1669
1670 //
1671 // Use for/break instead of goto
1672 //
1673 for ( ; ; ) {
1674 //
1675 // No bytes sent so far
1676 //
1677 TotalBytesSent = 0;
1678 Samples = 0;
1679 memset ( &BytesSent, 0, sizeof ( BytesSent ));
1680
1681 //
1682 // Get the IP address
1683 //
1684 pRemoteHost = Argv[1];
1685 Status = IpAddress ( );
1686 if ( EFI_ERROR ( Status )) {
1687 break;
1688 }
1689
1690 //
1691 // Create the timer
1692 //
1693 bTick = TRUE;
1694 Status = TimerCreate ( );
1695 if ( EFI_ERROR ( Status )) {
1696 break;
1697 }
1698
1699 //
1700 // Loop forever abusing the specified system
1701 //
1702 do {
1703 //
1704 // Start a timer to perform connection polling and display updates
1705 //
1706 Status = TimerStart ( 2 * 1000 );
1707 if ( EFI_ERROR ( Status )) {
1708 break;
1709 }
1710
1711 //
1712 // Open the network connection and send the data
1713 //
1714 Status = pOpen ( );
1715 if ( EFI_ERROR ( Status )) {
1716 break;
1717 }
1718
1719 //
1720 // Done with the network connection
1721 //
1722 Status = pClose ( );
1723 } while ( !EFI_ERROR ( Status ));
1724
1725 //
1726 // Close the network connection if necessary
1727 //
1728 pClose ( );
1729
1730 //
1731 // All done
1732 //
1733 break;
1734 }
1735
1736 //
1737 // Stop the timer if necessary
1738 //
1739 TimerStop ( );
1740 TimerDestroy ( );
1741
1742 //
1743 // Return the operation status
1744 //
1745 DEBUG (( DEBUG_INFO,
1746 "DataSource exiting, Status: %r\r\n",
1747 Status ));
1748 return Status;
1749 }