]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Sockets/DataSource/DataSource.c
6ca3b587e01237b8f25f9084de22eea1b6fbbca8
[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 EFIAPI
1322 TimerCallback (
1323 IN EFI_EVENT Event,
1324 IN VOID * pContext
1325 )
1326 {
1327 UINT32 Average;
1328 UINT64 BitsPerSecond;
1329 UINT32 Index;
1330 UINT64 TotalBytes;
1331
1332 //
1333 // Notify the other code of the timer tick
1334 //
1335 bTick = TRUE;
1336
1337 //
1338 // Update the average bytes per second
1339 //
1340 if ( 0 != TotalBytesSent ) {
1341 BytesSent[ In ] = TotalBytesSent;
1342 TotalBytesSent = 0;
1343 In += 1;
1344 if ( DATA_SAMPLES <= In ) {
1345 In = 0;
1346 }
1347
1348 //
1349 // Separate the samples
1350 //
1351 if ( DATA_SAMPLES == Samples ) {
1352 Print ( L"---------- Stable average ----------\r\n" );
1353 }
1354 Samples += 1;
1355
1356 //
1357 // Compute the data rate
1358 //
1359 TotalBytes = 0;
1360 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {
1361 TotalBytes += BytesSent[ Index ];
1362 }
1363 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );
1364 BitsPerSecond = Average * 8;
1365
1366 //
1367 // Display the data rate
1368 //
1369 if (( RANGE_SWITCH >> 10 ) > Average ) {
1370 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1371 Average,
1372 BitsPerSecond );
1373 }
1374 else {
1375 BitsPerSecond /= 1000;
1376 if ( RANGE_SWITCH > Average ) {
1377 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1378 Average >> 10,
1379 (( Average & 0x3ff ) * 1000 ) >> 10,
1380 BitsPerSecond );
1381 }
1382 else {
1383 BitsPerSecond /= 1000;
1384 Average >>= 10;
1385 if ( RANGE_SWITCH > Average ) {
1386 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1387 Average >> 10,
1388 (( Average & 0x3ff ) * 1000 ) >> 10,
1389 BitsPerSecond );
1390 }
1391 else {
1392 BitsPerSecond /= 1000;
1393 Average >>= 10;
1394 if ( RANGE_SWITCH > Average ) {
1395 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1396 Average >> 10,
1397 (( Average & 0x3ff ) * 1000 ) >> 10,
1398 BitsPerSecond );
1399 }
1400 else {
1401 BitsPerSecond /= 1000;
1402 Average >>= 10;
1403 if ( RANGE_SWITCH > Average ) {
1404 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1405 Average >> 10,
1406 (( Average & 0x3ff ) * 1000 ) >> 10,
1407 BitsPerSecond );
1408 }
1409 else {
1410 BitsPerSecond /= 1000;
1411 Average >>= 10;
1412 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1413 Average >> 10,
1414 (( Average & 0x3ff ) * 1000 ) >> 10,
1415 BitsPerSecond );
1416 }
1417 }
1418 }
1419 }
1420 }
1421 }
1422 }
1423
1424
1425 /**
1426 Create the timer
1427
1428 @retval EFI_SUCCESS The timer was successfully created
1429 @retval Other Timer initialization failed
1430 **/
1431 EFI_STATUS
1432 TimerCreate (
1433 )
1434 {
1435 EFI_STATUS Status;
1436
1437 //
1438 // Create the timer
1439 //
1440 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
1441 TPL_DATASOURCE,
1442 TimerCallback,
1443 NULL,
1444 &pTimer );
1445 if ( EFI_ERROR ( Status )) {
1446 DEBUG (( DEBUG_ERROR,
1447 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1448 Status ));
1449 }
1450 else {
1451 DEBUG (( DEBUG_INFO,
1452 "0x%08x: Timer created\r\n",
1453 pTimer ));
1454 }
1455
1456 //
1457 // Return the operation status
1458 //
1459 return Status;
1460 }
1461
1462
1463 /**
1464 Stop the timer
1465
1466 @retval EFI_SUCCESS The timer was stopped successfully
1467 @retval Other The timer failed to stop
1468 **/
1469 EFI_STATUS
1470 TimerStop (
1471 )
1472 {
1473 EFI_STATUS Status;
1474
1475 //
1476 // Assume success
1477 //
1478 Status = EFI_SUCCESS;
1479
1480 //
1481 // Determine if the timer is running
1482 //
1483 if ( bTimerRunning ) {
1484 //
1485 // Stop the timer
1486 //
1487 Status = gBS->SetTimer ( pTimer,
1488 TimerCancel,
1489 0 );
1490 if ( EFI_ERROR ( Status )) {
1491 DEBUG (( DEBUG_ERROR,
1492 "ERROR - Failed to stop the timer, Status: %r\r\n",
1493 Status ));
1494 }
1495 else {
1496 //
1497 // Timer timer is now stopped
1498 //
1499 bTimerRunning = FALSE;
1500 DEBUG (( DEBUG_INFO,
1501 "0x%08x: Timer stopped\r\n",
1502 pTimer ));
1503 }
1504 }
1505
1506 //
1507 // Return the operation status
1508 //
1509 return Status;
1510 }
1511
1512
1513 /**
1514 Start the timer
1515
1516 @param [in] Milliseconds The number of milliseconds between timer callbacks
1517
1518 @retval EFI_SUCCESS The timer was successfully created
1519 @retval Other Timer initialization failed
1520 **/
1521 EFI_STATUS
1522 TimerStart (
1523 UINTN Milliseconds
1524 )
1525 {
1526 EFI_STATUS Status;
1527 UINT64 TimeDelay;
1528
1529 //
1530 // Stop the timer if necessary
1531 //
1532 Status = EFI_SUCCESS;
1533 if ( bTimerRunning ) {
1534 Status = TimerStop ( );
1535 }
1536 if ( !EFI_ERROR ( Status )) {
1537 //
1538 // Compute the new delay
1539 //
1540 TimeDelay = Milliseconds;
1541 TimeDelay *= 1000 * 10;
1542
1543 //
1544 // Start the timer
1545 //
1546 Status = gBS->SetTimer ( pTimer,
1547 TimerPeriodic,
1548 TimeDelay );
1549 if ( EFI_ERROR ( Status )) {
1550 DEBUG (( DEBUG_ERROR,
1551 "ERROR - Failed to start the timer, Status: %r\r\n",
1552 Status ));
1553 }
1554 else {
1555 //
1556 // The timer is now running
1557 //
1558 bTimerRunning = TRUE;
1559 DEBUG (( DEBUG_INFO,
1560 "0x%08x: Timer running\r\n",
1561 pTimer ));
1562 }
1563 }
1564
1565 //
1566 // Return the operation status
1567 //
1568 return Status;
1569 }
1570
1571
1572 /**
1573 Destroy the timer
1574
1575 @retval EFI_SUCCESS The timer was destroyed successfully
1576 @retval Other Failed to destroy the timer
1577 **/
1578 EFI_STATUS
1579 TimerDestroy (
1580 )
1581 {
1582 EFI_STATUS Status;
1583
1584 //
1585 // Assume success
1586 //
1587 Status = EFI_SUCCESS;
1588
1589 //
1590 // Determine if the timer is running
1591 //
1592 if ( bTimerRunning ) {
1593 //
1594 // Stop the timer
1595 //
1596 Status = TimerStop ( );
1597 }
1598 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
1599 //
1600 // Done with this timer
1601 //
1602 Status = gBS->CloseEvent ( pTimer );
1603 if ( EFI_ERROR ( Status )) {
1604 DEBUG (( DEBUG_ERROR,
1605 "ERROR - Failed to free the timer event, Status: %r\r\n",
1606 Status ));
1607 }
1608 else {
1609 DEBUG (( DEBUG_INFO,
1610 "0x%08x: Timer Destroyed\r\n",
1611 pTimer ));
1612 pTimer = NULL;
1613 }
1614 }
1615
1616 //
1617 // Return the operation status
1618 //
1619 return Status;
1620 }
1621
1622
1623 /**
1624 Send data to the DataSink program to test a network's bandwidth.
1625
1626 @param [in] Argc The number of arguments
1627 @param [in] Argv The argument value array
1628
1629 @retval 0 The application exited normally.
1630 @retval Other An error occurred.
1631 **/
1632 int
1633 main (
1634 IN int Argc,
1635 IN char **Argv
1636 )
1637 {
1638 EFI_STATUS (* pClose) ();
1639 EFI_STATUS (* pOpen) ();
1640 EFI_STATUS Status;
1641
1642 DEBUG (( DEBUG_INFO,
1643 "DataSource starting\r\n" ));
1644
1645 //
1646 // Validate the command line
1647 //
1648 if ( 2 > Argc ) {
1649 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] );
1650 return -1;
1651 }
1652
1653 //
1654 // Determine if TCP should be used
1655 //
1656 bTcp4 = (BOOLEAN)( 2 < Argc );
1657
1658 //
1659 // Determine the support routines
1660 //
1661 if ( bTcp4 ) {
1662 pOpen = Tcp4Open;
1663 pClose = Tcp4Close;
1664 bTcp4Connecting = TRUE;
1665 }
1666 else {
1667 pOpen = SocketOpen;
1668 pClose = SocketClose;
1669 }
1670
1671 //
1672 // Use for/break instead of goto
1673 //
1674 for ( ; ; ) {
1675 //
1676 // No bytes sent so far
1677 //
1678 TotalBytesSent = 0;
1679 Samples = 0;
1680 memset ( &BytesSent, 0, sizeof ( BytesSent ));
1681
1682 //
1683 // Get the IP address
1684 //
1685 pRemoteHost = Argv[1];
1686 Status = IpAddress ( );
1687 if ( EFI_ERROR ( Status )) {
1688 break;
1689 }
1690
1691 //
1692 // Create the timer
1693 //
1694 bTick = TRUE;
1695 Status = TimerCreate ( );
1696 if ( EFI_ERROR ( Status )) {
1697 break;
1698 }
1699
1700 //
1701 // Loop forever abusing the specified system
1702 //
1703 do {
1704 //
1705 // Start a timer to perform connection polling and display updates
1706 //
1707 Status = TimerStart ( 2 * 1000 );
1708 if ( EFI_ERROR ( Status )) {
1709 break;
1710 }
1711
1712 //
1713 // Open the network connection and send the data
1714 //
1715 Status = pOpen ( );
1716 if ( EFI_ERROR ( Status )) {
1717 break;
1718 }
1719
1720 //
1721 // Done with the network connection
1722 //
1723 Status = pClose ( );
1724 } while ( !EFI_ERROR ( Status ));
1725
1726 //
1727 // Close the network connection if necessary
1728 //
1729 pClose ( );
1730
1731 //
1732 // All done
1733 //
1734 break;
1735 }
1736
1737 //
1738 // Stop the timer if necessary
1739 //
1740 TimerStop ( );
1741 TimerDestroy ( );
1742
1743 //
1744 // Return the operation status
1745 //
1746 DEBUG (( DEBUG_INFO,
1747 "DataSource exiting, Status: %r\r\n",
1748 Status ));
1749 return Status;
1750 }