]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Sockets/DataSource/DataSource.c
360689e15653b5a8d4276bea9071c81421d2acc8
[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. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <errno.h>
10 #include <Uefi.h>
11
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiLib.h>
17
18 #include <netinet/in.h>
19
20 #include <Protocol/ServiceBinding.h>
21 #include <Protocol/Tcp4.h>
22
23 #include <sys/EfiSysCall.h>
24 #include <sys/poll.h>
25 #include <sys/socket.h>
26
27 #include <stdio.h>
28 #include <string.h>
29
30
31 #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples
32 #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges
33 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
34 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
35 #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples
36
37 #define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL
38
39 #define PACKET_SIZE 1448 ///< Size of data packets
40 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
41
42
43 //
44 // Socket Data
45 //
46 int Socket = -1;
47
48 //
49 // TCP V4 Data
50 //
51 BOOLEAN bTcp4; ///< TRUE if TCP4 is being used
52 BOOLEAN bTcp4Connected; ///< TRUE if connected to remote system
53 BOOLEAN bTcp4Connecting; ///< TRUE while connection in progress
54 UINTN Tcp4Index; ///< Index into handle array
55 EFI_HANDLE Tcp4Controller; ///< Network controller handle
56 EFI_HANDLE Tcp4Handle; ///< TCP4 port handle
57 EFI_TCP4_PROTOCOL * pTcp4Protocol; ///< TCP4 protocol pointer
58 EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service; ///< TCP4 Service binding
59 EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///< TCP4 configuration data
60 EFI_TCP4_OPTION Tcp4Option; ///< TCP4 port options
61 EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///< Close control
62 EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///< Connection control
63 EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken; ///< Listen control
64 EFI_TCP4_IO_TOKEN Tcp4TxToken; ///< Normal data token
65
66 //
67 // Timer Data
68 //
69 volatile BOOLEAN bTick;
70 BOOLEAN bTimerRunning;
71 EFI_EVENT pTimer;
72
73 //
74 // Remote IP Address Data
75 //
76 struct sockaddr_in6 RemoteHostAddress;
77 CHAR8 * pRemoteHost;
78
79 //
80 // Traffic Data
81 //
82 UINT64 TotalBytesSent;
83 UINT32 In;
84 UINT32 Samples;
85 UINT64 BytesSent[ DATA_SAMPLES ];
86 UINT8 Buffer[ DATA_BUFFER_SIZE ];
87
88
89 //
90 // Forward routine declarations
91 //
92 EFI_STATUS TimerStart ( UINTN Milliseconds );
93
94
95 /**
96 Check for control C entered at console
97
98 @retval EFI_SUCCESS Control C not entered
99 @retval EFI_ABORTED Control C entered
100 **/
101 EFI_STATUS
102 ControlCCheck (
103 )
104 {
105 EFI_STATUS Status;
106
107 //
108 // Assume no user intervention
109 //
110 Status = EFI_SUCCESS;
111
112 //
113 // Display user stop request
114 //
115 if ( EFI_ERROR ( Status )) {
116 DEBUG (( DEBUG_INFO,
117 "User stop request!\r\n" ));
118 }
119
120 //
121 // Return the check status
122 //
123 return Status;
124 }
125
126
127 /**
128 Get a digit
129
130 @param [in] pDigit The address of the next digit
131 @param [out] pValue The address to receive the value
132
133 @return Returns the address of the separator
134
135 **/
136 CHAR8 *
137 GetDigit (
138 CHAR8 * pDigit,
139 UINT32 * pValue
140 )
141 {
142 UINT32 Value;
143
144 //
145 // Walk the digits
146 //
147 Value = 0;
148 while (( '0' <= *pDigit ) && ( '9' >= *pDigit )) {
149 //
150 // Make room for the new least significant digit
151 //
152 Value *= 10;
153
154 //
155 // Convert the digit from ASCII to binary
156 //
157 Value += *pDigit - '0';
158
159 //
160 // Set the next digit
161 //
162 pDigit += 1;
163 }
164
165 //
166 // Return the value
167 //
168 *pValue = Value;
169
170 //
171 // Return the next separator
172 //
173 return pDigit;
174 }
175
176
177 /**
178 Get the IP address
179
180 @retval EFI_SUCCESS The IP address is valid
181 @retval Other Failure to convert the IP address
182 **/
183 EFI_STATUS
184 IpAddress (
185 )
186 {
187 struct sockaddr_in * pRemoteAddress4;
188 struct sockaddr_in6 * pRemoteAddress6;
189 UINT32 RemoteAddress;
190 EFI_STATUS Status;
191 UINT32 Value1;
192 UINT32 Value2;
193 UINT32 Value3;
194 UINT32 Value4;
195 UINT32 Value5;
196 UINT32 Value6;
197 UINT32 Value7;
198 UINT32 Value8;
199
200 //
201 // Assume failure
202 //
203 Status = EFI_INVALID_PARAMETER;
204
205 //
206 // Get the port number
207 //
208 ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));
209 RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));
210 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;
211 pRemoteAddress6 = &RemoteHostAddress;
212
213 //
214 // Convert the IP address from a string to a numeric value
215 //
216 if (( 4 == sscanf ( pRemoteHost,
217 "%d.%d.%d.%d",
218 &Value1,
219 &Value2,
220 &Value3,
221 &Value4 ))
222 && ( 255 >= Value1 )
223 && ( 255 >= Value2 )
224 && ( 255 >= Value3 )
225 && ( 255 >= Value4 )) {
226 //
227 // Build the IPv4 address
228 //
229 pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );
230 pRemoteAddress4->sin_family = AF_INET;
231 RemoteAddress = Value1
232 | ( Value2 << 8 )
233 | ( Value3 << 16 )
234 | ( Value4 << 24 );
235 pRemoteAddress4->sin_addr.s_addr = RemoteAddress;
236 Status = EFI_SUCCESS;
237
238 //
239 // Display the IP address
240 //
241 DEBUG (( DEBUG_INFO,
242 "%d.%d.%d.%d: Remote host IP address\r\n",
243 Value1,
244 Value2,
245 Value3,
246 Value4 ));
247 }
248 else if (( 8 == sscanf ( pRemoteHost,
249 "%x:%x:%x:%x:%x:%x:%x:%x",
250 &Value1,
251 &Value2,
252 &Value3,
253 &Value4,
254 &Value5,
255 &Value6,
256 &Value7,
257 &Value8 ))
258 && ( 0xffff >= Value1 )
259 && ( 0xffff >= Value2 )
260 && ( 0xffff >= Value3 )
261 && ( 0xffff >= Value4 )
262 && ( 0xffff >= Value5 )
263 && ( 0xffff >= Value6 )
264 && ( 0xffff >= Value7 )
265 && ( 0xffff >= Value8 )) {
266 //
267 // Build the IPv6 address
268 //
269 pRemoteAddress6->sin6_len = sizeof ( *pRemoteAddress6 );
270 pRemoteAddress6->sin6_family = AF_INET6;
271 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ] = (UINT8)( Value1 >> 8 );
272 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ] = (UINT8)Value1;
273 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ] = (UINT8)( Value2 >> 8 );
274 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ] = (UINT8)Value2;
275 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ] = (UINT8)( Value3 >> 8 );
276 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ] = (UINT8)Value3;
277 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ] = (UINT8)( Value4 >> 8 );
278 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ] = (UINT8)Value4;
279 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ] = (UINT8)( Value5 >> 8 );
280 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ] = (UINT8)Value5;
281 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ] = (UINT8)( Value6 >> 8 );
282 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ] = (UINT8)Value6;
283 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ] = (UINT8)( Value7 >> 8 );
284 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ] = (UINT8)Value7;
285 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ] = (UINT8)( Value8 >> 8 );
286 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ] = (UINT8)Value8;
287 Status = EFI_SUCCESS;
288
289 //
290 // Display the IP address
291 //
292 DEBUG (( DEBUG_INFO,
293 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
294 Value1,
295 Value2,
296 Value3,
297 Value4,
298 Value5,
299 Value6,
300 Value7,
301 Value8 ));
302 }
303 else {
304 Print ( L"ERROR - Invalid IP address!\r\n" );
305 }
306
307 //
308 // Return the operation status
309 //
310 return Status;
311 }
312
313
314 /**
315 Close the socket
316
317 @retval EFI_SUCCESS The application is running normally
318 @retval Other The user stopped the application
319 **/
320 EFI_STATUS
321 SocketClose (
322 )
323 {
324 int CloseStatus;
325 EFI_STATUS Status;
326
327 //
328 // Determine if the socket is open
329 //
330 Status = EFI_DEVICE_ERROR;
331 if ( -1 != Socket ) {
332 //
333 // Attempt to close the socket
334 //
335 CloseStatus = close ( Socket );
336 if ( 0 == CloseStatus ) {
337 DEBUG (( DEBUG_INFO,
338 "0x%08x: Socket closed\r\n",
339 Socket ));
340 Socket = -1;
341 Status = EFI_SUCCESS;
342 }
343 else {
344 DEBUG (( DEBUG_ERROR,
345 "ERROR: Failed to close socket, errno: %d\r\n",
346 errno ));
347 }
348 }
349
350 //
351 // Return the operation status
352 //
353 return Status;
354 }
355
356
357 /**
358 Connect the socket
359
360 @retval EFI_SUCCESS The application is running normally
361 @retval Other The user stopped the application
362 **/
363 EFI_STATUS
364 SocketConnect (
365 )
366 {
367 int ConnectStatus;
368 struct sockaddr_in * pRemoteAddress4;
369 struct sockaddr_in6 * pRemoteAddress6;
370 EFI_STATUS Status;
371
372 //
373 // Display the connecting message
374 //
375 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;
376 pRemoteAddress6 = &RemoteHostAddress;
377 if ( AF_INET == pRemoteAddress6->sin6_family ) {
378 Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",
379 pRemoteAddress4->sin_addr.s_addr & 0xff,
380 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
381 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
382 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
383 ntohs ( pRemoteAddress4->sin_port ));
384 }
385 else {
386 Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
387 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
388 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
389 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
390 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
391 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
392 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
393 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
394 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
395 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
396 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
397 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
398 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
399 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
400 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
401 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
402 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
403 ntohs ( pRemoteAddress6->sin6_port ));
404 }
405
406 //
407 // Connect to the remote system
408 //
409 Status = EFI_SUCCESS;
410 do {
411 //
412 // Check for user stop request
413 //
414 while ( !bTick ) {
415 Status = ControlCCheck ( );
416 if ( EFI_ERROR ( Status )) {
417 break;
418 }
419 }
420 bTick = FALSE;
421 if ( EFI_ERROR ( Status )) {
422 break;
423 }
424
425 //
426 // Connect to the remote system
427 //
428 ConnectStatus = connect ( Socket,
429 (struct sockaddr *)pRemoteAddress6,
430 pRemoteAddress6->sin6_len );
431 if ( -1 != ConnectStatus ) {
432 if ( AF_INET == pRemoteAddress6->sin6_family ) {
433 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
434 pRemoteAddress4->sin_addr.s_addr & 0xff,
435 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
436 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
437 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
438 ntohs ( pRemoteAddress4->sin_port ));
439 }
440 else {
441 Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
442 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
443 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
444 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
445 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
446 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
447 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
448 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
449 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
450 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
451 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
452 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
453 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
454 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
455 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
456 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
457 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
458 ntohs ( pRemoteAddress6->sin6_port ));
459 }
460 Print ( L"ConnectStatus: %d, Status: %r\r\n", ConnectStatus, Status );
461 }
462 else {
463 //
464 // Close the socket and try again
465 //
466 if ( EAGAIN != errno ) {
467 Status = EFI_NOT_STARTED;
468 break;
469 }
470 }
471 } while ( -1 == ConnectStatus );
472
473 //
474 // Return the operation status
475 //
476 Print ( L"SocketConnect returning Status: %r\r\n", Status );
477 return Status;
478 }
479
480
481 /**
482 Create the socket
483
484 @param [in] Family Network family, AF_INET or AF_INET6
485
486 @retval EFI_SUCCESS The application is running normally
487 @retval Other The user stopped the application
488 **/
489 EFI_STATUS
490 SocketNew (
491 sa_family_t Family
492 )
493 {
494 EFI_STATUS Status;
495
496 //
497 // Loop creating the socket
498 //
499 DEBUG (( DEBUG_INFO,
500 "Creating the socket\r\n" ));
501 do {
502 //
503 // Check for user stop request
504 //
505 Status = ControlCCheck ( );
506 if ( EFI_ERROR ( Status )) {
507 break;
508 }
509
510 //
511 // Attempt to create the socket
512 //
513 Socket = socket ( Family,
514 SOCK_STREAM,
515 IPPROTO_TCP );
516 if ( -1 != Socket ) {
517 DEBUG (( DEBUG_INFO,
518 "0x%08x: Socket created\r\n",
519 Socket ));
520 break;
521 }
522 } while ( -1 == Socket );
523
524 //
525 // Return the operation status
526 //
527 return Status;
528 }
529
530
531 /**
532 Send data over the socket
533
534 @retval EFI_SUCCESS The application is running normally
535 @retval Other The user stopped the application
536 **/
537 EFI_STATUS
538 SocketSend (
539 )
540 {
541 size_t BytesSent;
542 EFI_STATUS Status;
543 EFI_TPL TplPrevious;
544
545 //
546 // Restart the timer
547 //
548 TimerStart ( 1 * 1000 );
549
550 //
551 // Loop until the connection breaks or the user stops
552 //
553 do {
554 //
555 // Check for user stop request
556 //
557 Status = ControlCCheck ( );
558 if ( EFI_ERROR ( Status )) {
559 break;
560 }
561
562 //
563 // Send some bytes
564 //
565 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));
566 if ( -1 == BytesSent ) {
567 DEBUG (( DEBUG_INFO,
568 "ERROR: send failed, errno: %d\r\n",
569 errno ));
570 Print ( L"ERROR: send failed, errno: %d\r\n", errno );
571
572 //
573 // Try again
574 //
575 Status = EFI_SUCCESS;
576
577 //
578 // Exit now
579 //
580 Status = EFI_NOT_STARTED;
581 break;
582 }
583
584 //
585 // Synchronize with the TimerCallback routine
586 //
587 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
588
589 //
590 // Account for the data sent
591 //
592 TotalBytesSent += BytesSent;
593
594 //
595 // Release the TimerCallback routine synchronization
596 //
597 gBS->RestoreTPL ( TplPrevious );
598 } while ( !EFI_ERROR ( Status ));
599
600 //
601 // Return the operation status
602 //
603 return Status;
604 }
605
606
607 /**
608 Open the network connection and send the data.
609
610 @retval EFI_SUCCESS Continue looping
611 @retval other Stopped by user's Control-C input
612
613 **/
614 EFI_STATUS
615 SocketOpen (
616 )
617 {
618 EFI_STATUS Status;
619
620 //
621 // Use do/while and break instead of goto
622 //
623 do {
624 //
625 // Wait for the network layer to initialize
626 //
627 Status = SocketNew ( RemoteHostAddress.sin6_family );
628 if ( EFI_ERROR ( Status )) {
629 break;
630 }
631
632 //
633 // Wait for the remote network application to start
634 //
635 Status = SocketConnect ( );
636 Print ( L"Status: %r\r\n", Status );
637 if ( EFI_NOT_STARTED == Status ) {
638 Status = SocketClose ( );
639 continue;
640 }
641 else if ( EFI_SUCCESS != Status ) {
642 //
643 // Control-C
644 //
645 break;
646 }
647
648 //
649 // Send data until the connection breaks
650 //
651 Status = SocketSend ( );
652 if ( EFI_ERROR ( Status )) {
653 break;
654 }
655 } while ( FALSE );
656
657 //
658 // Return the operation status
659 //
660 Print ( L"Returning Status: %r\r\n", Status );
661 return Status;
662 }
663
664
665 /**
666 Close the TCP connection
667
668 @retval EFI_SUCCESS The application is running normally
669 @retval Other The user stopped the application
670 **/
671 EFI_STATUS
672 Tcp4Close (
673 )
674 {
675 UINTN Index;
676 UINT8 * pIpAddress;
677 EFI_STATUS Status;
678
679 //
680 // Close the port
681 //
682 if ( bTcp4Connected ) {
683 Tcp4CloseToken.AbortOnClose = TRUE;
684 Status = pTcp4Protocol->Close ( pTcp4Protocol,
685 &Tcp4CloseToken );
686 if ( EFI_ERROR ( Status )) {
687 DEBUG (( DEBUG_ERROR,
688 "ERROR - Failed to start the TCP port close, Status: %r\r\n",
689 Status ));
690 }
691 else {
692 Status = gBS->WaitForEvent ( 1,
693 &Tcp4CloseToken.CompletionToken.Event,
694 &Index );
695 if ( EFI_ERROR ( Status )) {
696 DEBUG (( DEBUG_ERROR,
697 "ERROR - Failed to wait for close event, Status: %r\r\n",
698 Status ));
699 }
700 else {
701 Status = Tcp4CloseToken.CompletionToken.Status;
702 if ( EFI_ERROR ( Status )) {
703 DEBUG (( DEBUG_ERROR,
704 "ERROR - Failed to close the TCP port, Status: %r\r\n",
705 Status ));
706 }
707 else {
708 DEBUG (( DEBUG_INFO,
709 "0x%08x: TCP port closed\r\n",
710 pTcp4Protocol ));
711 bTcp4Connected = FALSE;
712
713 //
714 // Display the port closed message
715 //
716 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
717 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",
718 pIpAddress[0],
719 pIpAddress[1],
720 pIpAddress[2],
721 pIpAddress[3],
722 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
723 }
724 }
725 }
726 }
727
728 //
729 // Release the events
730 //
731 if ( NULL != Tcp4TxToken.CompletionToken.Event ) {
732 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );
733 if ( !EFI_ERROR ( Status )) {
734 DEBUG (( DEBUG_INFO,
735 "0x%08x: TX event closed\r\n",
736 Tcp4TxToken.CompletionToken.Event ));
737 Tcp4TxToken.CompletionToken.Event = NULL;
738 }
739 else {
740 DEBUG (( DEBUG_ERROR,
741 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
742 Status ));
743 }
744 }
745
746 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {
747 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );
748 if ( !EFI_ERROR ( Status )) {
749 DEBUG (( DEBUG_INFO,
750 "0x%08x: Listen event closed\r\n",
751 Tcp4ListenToken.CompletionToken.Event ));
752 Tcp4ListenToken.CompletionToken.Event = NULL;
753 }
754 else {
755 DEBUG (( DEBUG_ERROR,
756 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
757 Status ));
758 }
759 }
760
761 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {
762 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );
763 if ( !EFI_ERROR ( Status )) {
764 DEBUG (( DEBUG_INFO,
765 "0x%08x: Connect event closed\r\n",
766 Tcp4ConnectToken.CompletionToken.Event ));
767 Tcp4ConnectToken.CompletionToken.Event = NULL;
768 }
769 else {
770 DEBUG (( DEBUG_ERROR,
771 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
772 Status ));
773 }
774 }
775
776 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {
777 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );
778 if ( !EFI_ERROR ( Status )) {
779 DEBUG (( DEBUG_INFO,
780 "0x%08x: Close event closed\r\n",
781 Tcp4CloseToken.CompletionToken.Event ));
782 Tcp4CloseToken.CompletionToken.Event = NULL;
783 }
784 else {
785 DEBUG (( DEBUG_ERROR,
786 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
787 Status ));
788 }
789 }
790
791 //
792 // Close the TCP protocol
793 //
794 if ( NULL != pTcp4Protocol ) {
795 Status = gBS->CloseProtocol ( Tcp4Handle,
796 &gEfiTcp4ProtocolGuid,
797 gImageHandle,
798 NULL );
799 if ( EFI_ERROR ( Status )) {
800 DEBUG (( DEBUG_ERROR,
801 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
802 Status ));
803 }
804 else {
805 DEBUG (( DEBUG_INFO,
806 "0x%08x: TCP4 protocol closed\r\n",
807 pTcp4Protocol ));
808 pTcp4Protocol = NULL;
809 }
810 }
811
812 //
813 // Done with the TCP service
814 //
815 if ( NULL != Tcp4Handle ) {
816 Status = pTcp4Service->DestroyChild ( pTcp4Service,
817 Tcp4Handle );
818 if ( EFI_ERROR ( Status )) {
819 DEBUG (( DEBUG_ERROR,
820 "ERROR - Failed to release TCP service handle, Status: %r\r\n",
821 Status ));
822 }
823 else {
824 DEBUG (( DEBUG_INFO,
825 "Ox%08x: TCP service closed\r\n",
826 Tcp4Handle ));
827 Tcp4Handle = NULL;
828 }
829 }
830
831 //
832 // Close the service protocol
833 //
834 if ( NULL != pTcp4Service ) {
835 Status = gBS->CloseProtocol ( Tcp4Controller,
836 &gEfiTcp4ServiceBindingProtocolGuid,
837 gImageHandle,
838 NULL );
839 if ( !EFI_ERROR ( Status )) {
840 DEBUG (( DEBUG_INFO,
841 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
842 Tcp4Controller ));
843 pTcp4Service = NULL;
844 }
845 else {
846 DEBUG (( DEBUG_ERROR,
847 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
848 Status ));
849 }
850 }
851 Tcp4Controller = NULL;
852 bTcp4Connecting = TRUE;
853
854 //
855 // Mark the connection as closed
856 //
857 Status = EFI_SUCCESS;
858
859 //
860 // Return the operation status
861 //
862 return Status;
863 }
864
865
866 /**
867 Locate TCP protocol
868
869 @retval EFI_SUCCESS Protocol found
870 @retval other Protocl not found
871 **/
872 EFI_STATUS
873 Tcp4Locate (
874 )
875 {
876 UINTN HandleCount;
877 EFI_HANDLE * pHandles;
878 UINT8 * pIpAddress;
879 EFI_STATUS Status;
880
881 //
882 // Use do/while and break instead of goto
883 //
884 do {
885 //
886 // Attempt to locate the next TCP adapter in the system
887 //
888 Status = gBS->LocateHandleBuffer ( ByProtocol,
889 &gEfiTcp4ServiceBindingProtocolGuid,
890 NULL,
891 &HandleCount,
892 &pHandles );
893 if ( EFI_ERROR ( Status )) {
894 DEBUG (( DEBUG_WARN,
895 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
896 Status ));
897 break;
898 }
899
900 //
901 // Wrap the index if necessary
902 //
903 if ( HandleCount <= Tcp4Index ) {
904 Tcp4Index = 0;
905
906 //
907 // Wait for the next timer tick
908 //
909 do {
910 } while ( !bTick );
911 bTick = FALSE;
912 }
913
914 //
915 // Display the connecting message
916 //
917 if ( bTcp4Connecting ) {
918 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
919 Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",
920 pIpAddress[0],
921 pIpAddress[1],
922 pIpAddress[2],
923 pIpAddress[3],
924 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
925 bTcp4Connecting = FALSE;
926 }
927
928 //
929 // Open the network controller's service protocol
930 //
931 Tcp4Controller = pHandles[ Tcp4Index++ ];
932 Status = gBS->OpenProtocol (
933 Tcp4Controller,
934 &gEfiTcp4ServiceBindingProtocolGuid,
935 (VOID **) &pTcp4Service,
936 gImageHandle,
937 NULL,
938 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
939 if ( EFI_ERROR ( Status )) {
940 DEBUG (( DEBUG_ERROR,
941 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
942 Tcp4Controller ));
943 Tcp4Controller = NULL;
944 break;
945 }
946 DEBUG (( DEBUG_INFO,
947 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
948 Tcp4Controller ));
949
950 //
951 // Connect to the TCP service
952 //
953 Status = pTcp4Service->CreateChild ( pTcp4Service,
954 &Tcp4Handle );
955 if ( EFI_ERROR ( Status )) {
956 DEBUG (( DEBUG_ERROR,
957 "ERROR - Failed to open TCP service, Status: %r\r\n",
958 Status ));
959 Tcp4Handle = NULL;
960 break;
961 }
962 DEBUG (( DEBUG_INFO,
963 "Ox%08x: TCP service opened\r\n",
964 Tcp4Handle ));
965
966 //
967 // Locate the TCP protcol
968 //
969 Status = gBS->OpenProtocol ( Tcp4Handle,
970 &gEfiTcp4ProtocolGuid,
971 (VOID **)&pTcp4Protocol,
972 gImageHandle,
973 NULL,
974 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
975 if ( EFI_ERROR ( Status )) {
976 DEBUG (( DEBUG_ERROR,
977 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",
978 Status ));
979 pTcp4Protocol = NULL;
980 break;
981 }
982 DEBUG (( DEBUG_INFO,
983 "0x%08x: TCP4 protocol opened\r\n",
984 pTcp4Protocol ));
985 }while ( FALSE );
986
987 //
988 // Release the handle buffer
989 //
990 gBS->FreePool ( pHandles );
991
992 //
993 // Return the operation status
994 //
995 return Status;
996 }
997
998
999 /**
1000 Send data over the TCP4 connection
1001
1002 @retval EFI_SUCCESS The application is running normally
1003 @retval Other The user stopped the application
1004 **/
1005 EFI_STATUS
1006 Tcp4Send (
1007 )
1008 {
1009 UINTN Index;
1010 EFI_TCP4_TRANSMIT_DATA Packet;
1011 EFI_STATUS Status;
1012 EFI_TPL TplPrevious;
1013
1014 //
1015 // Restart the timer
1016 //
1017 TimerStart ( 1 * 1000 );
1018
1019 //
1020 // Initialize the packet
1021 //
1022 Packet.DataLength = sizeof ( Buffer );
1023 Packet.FragmentCount = 1;
1024 Packet.Push = FALSE;
1025 Packet.Urgent = FALSE;
1026 Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];
1027 Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );
1028 Tcp4TxToken.Packet.TxData = &Packet;
1029
1030 //
1031 // Loop until the connection breaks or the user stops
1032 //
1033 do {
1034 //
1035 // Check for user stop request
1036 //
1037 Status = ControlCCheck ( );
1038 if ( EFI_ERROR ( Status )) {
1039 break;
1040 }
1041
1042 //
1043 // Send some bytes
1044 //
1045 Status = pTcp4Protocol->Transmit ( pTcp4Protocol,
1046 &Tcp4TxToken );
1047 if ( EFI_ERROR ( Status )) {
1048 DEBUG (( DEBUG_ERROR,
1049 "ERROR - Failed to start the transmit, Status: %r\r\n",
1050 Status ));
1051
1052 //
1053 // Try again
1054 //
1055 Status = EFI_SUCCESS;
1056 break;
1057 }
1058
1059 //
1060 // Wait for the transmit to complete
1061 //
1062 Status = gBS->WaitForEvent ( 1,
1063 &Tcp4TxToken.CompletionToken.Event,
1064 &Index );
1065 if ( EFI_ERROR ( Status )) {
1066 DEBUG (( DEBUG_ERROR,
1067 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
1068 Status ));
1069
1070 //
1071 // Try again
1072 //
1073 Status = EFI_SUCCESS;
1074 break;
1075 }
1076
1077 //
1078 // Get the transmit status
1079 //
1080 Status = Tcp4TxToken.CompletionToken.Status;
1081 if ( EFI_ERROR ( Status )) {
1082 DEBUG (( DEBUG_WARN,
1083 "WARNING - Failed the transmission, Status: %r\r\n",
1084 Status ));
1085
1086 //
1087 // Try again
1088 //
1089 Status = EFI_SUCCESS;
1090
1091 //
1092 // Exit now
1093 //
1094 Status = EFI_NOT_STARTED;
1095 break;
1096 }
1097
1098 //
1099 // Synchronize with the TimerCallback routine
1100 //
1101 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );
1102
1103 //
1104 // Account for the data sent
1105 //
1106 TotalBytesSent += Packet.DataLength;
1107
1108 //
1109 // Release the TimerCallback routine synchronization
1110 //
1111 gBS->RestoreTPL ( TplPrevious );
1112 } while ( !EFI_ERROR ( Status ));
1113
1114 //
1115 // Return the operation status
1116 //
1117 return Status;
1118 }
1119
1120
1121 /**
1122 Open the network connection and send the data.
1123
1124 @retval EFI_SUCCESS Continue looping
1125 @retval other Stopped by user's Control-C input
1126
1127 **/
1128 EFI_STATUS
1129 Tcp4Open (
1130 )
1131 {
1132 UINTN Index;
1133 UINT8 * pIpAddress;
1134 EFI_STATUS Status;
1135
1136 //
1137 // Use do/while and break instead of goto
1138 //
1139 do {
1140 //
1141 // Locate the TCP protocol
1142 //
1143 Status = Tcp4Locate ( );
1144 if ( EFI_ERROR ( Status )) {
1145 break;
1146 }
1147
1148 //
1149 // Create the necessary events
1150 //
1151 Status = gBS->CreateEvent ( 0,
1152 TPL_CALLBACK,
1153 NULL,
1154 NULL,
1155 &Tcp4CloseToken.CompletionToken.Event );
1156 if ( EFI_ERROR ( Status )) {
1157 DEBUG (( DEBUG_ERROR,
1158 "ERROR - Failed to create the close event, Status: %r\r\n",
1159 Status ));
1160 Tcp4CloseToken.CompletionToken.Event = NULL;
1161 break;
1162 }
1163 DEBUG (( DEBUG_INFO,
1164 "0x%08x: Close event open\r\n",
1165 Tcp4CloseToken.CompletionToken.Event ));
1166
1167 Status = gBS->CreateEvent ( 0,
1168 TPL_CALLBACK,
1169 NULL,
1170 NULL,
1171 &Tcp4ConnectToken.CompletionToken.Event );
1172 if ( EFI_ERROR ( Status )) {
1173 DEBUG (( DEBUG_ERROR,
1174 "ERROR - Failed to create the connect event, Status: %r\r\n",
1175 Status ));
1176 Tcp4ConnectToken.CompletionToken.Event = NULL;
1177 break;
1178 }
1179 DEBUG (( DEBUG_INFO,
1180 "0x%08x: Connect event open\r\n",
1181 Tcp4ConnectToken.CompletionToken.Event ));
1182
1183 Status = gBS->CreateEvent ( 0,
1184 TPL_CALLBACK,
1185 NULL,
1186 NULL,
1187 &Tcp4ListenToken.CompletionToken.Event );
1188 if ( EFI_ERROR ( Status )) {
1189 DEBUG (( DEBUG_ERROR,
1190 "ERROR - Failed to create the listen event, Status: %r\r\n",
1191 Status ));
1192 Tcp4ListenToken.CompletionToken.Event = NULL;
1193 break;
1194 }
1195 DEBUG (( DEBUG_INFO,
1196 "0x%08x: Listen event open\r\n",
1197 Tcp4ListenToken.CompletionToken.Event ));
1198
1199 Status = gBS->CreateEvent ( 0,
1200 TPL_CALLBACK,
1201 NULL,
1202 NULL,
1203 &Tcp4TxToken.CompletionToken.Event );
1204 if ( EFI_ERROR ( Status )) {
1205 DEBUG (( DEBUG_ERROR,
1206 "ERROR - Failed to create the TX event, Status: %r\r\n",
1207 Status ));
1208 Tcp4TxToken.CompletionToken.Event = NULL;
1209 break;
1210 }
1211 DEBUG (( DEBUG_INFO,
1212 "0x%08x: TX event open\r\n",
1213 Tcp4TxToken.CompletionToken.Event ));
1214
1215 //
1216 // Configure the local TCP port
1217 //
1218 Tcp4ConfigData.TimeToLive = 255;
1219 Tcp4ConfigData.TypeOfService = 0;
1220 Tcp4ConfigData.ControlOption = NULL;
1221 Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;
1222 Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;
1223 Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0;
1224 Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;
1225 Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;
1226 Tcp4ConfigData.AccessPoint.StationPort = 0;
1227 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
1228 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );
1229 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );
1230 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );
1231 Tcp4ConfigData.AccessPoint.RemotePort = ntohs (((struct sockaddr_in *)&RemoteHostAddress)->sin_port);
1232 Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;
1233 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;
1234 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;
1235 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;
1236 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;
1237 Status = pTcp4Protocol->Configure ( pTcp4Protocol,
1238 &Tcp4ConfigData );
1239 if ( EFI_ERROR ( Status )) {
1240 DEBUG (( DEBUG_ERROR,
1241 "ERROR - Failed to configure TCP port, Status: %r\r\n",
1242 Status ));
1243 break;
1244 }
1245 DEBUG (( DEBUG_INFO,
1246 "0x%08x: TCP4 port configured\r\n",
1247 pTcp4Protocol ));
1248
1249 //
1250 // Connect to the remote TCP port
1251 //
1252 Status = pTcp4Protocol->Connect ( pTcp4Protocol,
1253 &Tcp4ConnectToken );
1254 if ( EFI_ERROR ( Status )) {
1255 DEBUG (( DEBUG_ERROR,
1256 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
1257 Status ));
1258 break;
1259 }
1260 Status = gBS->WaitForEvent ( 1,
1261 &Tcp4ConnectToken.CompletionToken.Event,
1262 &Index );
1263 if ( EFI_ERROR ( Status )) {
1264 DEBUG (( DEBUG_ERROR,
1265 "ERROR - Failed to wait for the connection, Status: %r\r\n",
1266 Status ));
1267 break;
1268 }
1269 Status = Tcp4ConnectToken.CompletionToken.Status;
1270 if ( EFI_ERROR ( Status )) {
1271 DEBUG (( DEBUG_WARN,
1272 "WARNING - Failed to connect to the remote system, Status: %r\r\n",
1273 Status ));
1274 break;
1275 }
1276 DEBUG (( DEBUG_INFO,
1277 "0x%08x: TCP4 port connected\r\n",
1278 pTcp4Protocol ));
1279 bTcp4Connected = TRUE;
1280
1281 //
1282 // Display the connection
1283 //
1284 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;
1285 Print ( L"Connected to %d.%d.%d.%d:%d\r\n",
1286 pIpAddress[0],
1287 pIpAddress[1],
1288 pIpAddress[2],
1289 pIpAddress[3],
1290 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));
1291 } while ( 0 );
1292
1293 if ( EFI_ERROR ( Status )) {
1294 //
1295 // Try again
1296 //
1297 Status = EFI_SUCCESS;
1298 }
1299 else {
1300 //
1301 // Semd data until the connection breaks
1302 //
1303 Status = Tcp4Send ( );
1304 }
1305
1306 //
1307 // Return the operation status
1308 //
1309 return Status;
1310 }
1311
1312
1313 /**
1314 Handle the timer callback
1315
1316 @param [in] Event Event that caused this callback
1317 @param [in] pContext Context for this routine
1318 **/
1319 VOID
1320 EFIAPI
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 }