1/** @file 2 Data source for network testing. 3 4 Copyright (c) 2011-2012, Intel Corporation 5 All rights reserved. This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15#include <errno.h> 16#include <Uefi.h> 17 18#include <Library/BaseMemoryLib.h> 19#include <Library/DebugLib.h> 20#include <Library/PcdLib.h> 21#include <Library/UefiBootServicesTableLib.h> 22#include <Library/UefiLib.h> 23 24#include <netinet/in.h> 25 26#include <Protocol/ServiceBinding.h> 27#include <Protocol/Tcp4.h> 28 29#include <sys/EfiSysCall.h> 30#include <sys/poll.h> 31#include <sys/socket.h> 32 33#include <stdio.h> 34#include <string.h> 35 36 37#define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples 38#define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges 39#define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates 40#define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average 41#define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples 42 43#define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL 44 45#define PACKET_SIZE 1448 ///< Size of data packets 46#define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes 47 48 49// 50// Socket Data 51// 52int Socket = -1; 53 54// 55// TCP V4 Data 56// 57BOOLEAN bTcp4; ///< TRUE if TCP4 is being used 58BOOLEAN bTcp4Connected; ///< TRUE if connected to remote system 59BOOLEAN bTcp4Connecting; ///< TRUE while connection in progress 60UINTN Tcp4Index; ///< Index into handle array 61EFI_HANDLE Tcp4Controller; ///< Network controller handle 62EFI_HANDLE Tcp4Handle; ///< TCP4 port handle 63EFI_TCP4_PROTOCOL * pTcp4Protocol; ///< TCP4 protocol pointer 64EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service; ///< TCP4 Service binding 65EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///< TCP4 configuration data 66EFI_TCP4_OPTION Tcp4Option; ///< TCP4 port options 67EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///< Close control 68EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///< Connection control 69EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken; ///< Listen control 70EFI_TCP4_IO_TOKEN Tcp4TxToken; ///< Normal data token 71 72// 73// Timer Data 74// 75volatile BOOLEAN bTick; 76BOOLEAN bTimerRunning; 77EFI_EVENT pTimer; 78 79// 80// Remote IP Address Data 81// 82struct sockaddr_in6 RemoteHostAddress; 83CHAR8 * pRemoteHost; 84 85// 86// Traffic Data 87// 88UINT64 TotalBytesSent; 89UINT32 In; 90UINT32 Samples; 91UINT64 BytesSent[ DATA_SAMPLES ]; 92UINT8 Buffer[ DATA_BUFFER_SIZE ]; 93 94 95// 96// Forward routine declarations 97// 98EFI_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**/ 107EFI_STATUS 108ControlCCheck ( 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**/ 142CHAR8 * 143GetDigit ( 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**/ 189EFI_STATUS 190IpAddress ( 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**/ 326EFI_STATUS 327SocketClose ( 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**/ 369EFI_STATUS 370SocketConnect ( 371 ) 372{ 373 int ConnectStatus; 374 struct sockaddr_in * pRemoteAddress4; 375 struct sockaddr_in6 * pRemoteAddress6; 376 EFI_STATUS Status; 377 378 // 379 // Display the connecting message 380 // 381 pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress; 382 pRemoteAddress6 = &RemoteHostAddress; 383 if ( AF_INET == pRemoteAddress6->sin6_family ) { 384 Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n", 385 pRemoteAddress4->sin_addr.s_addr & 0xff, 386 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff, 387 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff, 388 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff, 389 ntohs ( pRemoteAddress4->sin_port )); 390 } 391 else { 392 Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", 393 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], 394 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], 395 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], 396 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], 397 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], 398 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], 399 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], 400 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], 401 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], 402 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], 403 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], 404 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], 405 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], 406 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], 407 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], 408 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], 409 ntohs ( pRemoteAddress6->sin6_port )); 410 } 411 412 // 413 // Connect to the remote system 414 // 415 Status = EFI_SUCCESS; 416 do { 417 // 418 // Check for user stop request 419 // 420 while ( !bTick ) { 421 Status = ControlCCheck ( ); 422 if ( EFI_ERROR ( Status )) { 423 break; 424 } 425 } 426 bTick = FALSE; 427 if ( EFI_ERROR ( Status )) { 428 break; 429 } 430 431 // 432 // Connect to the remote system 433 // 434 ConnectStatus = connect ( Socket, 435 (struct sockaddr *)pRemoteAddress6, 436 pRemoteAddress6->sin6_len ); 437 if ( -1 != ConnectStatus ) { 438 if ( AF_INET == pRemoteAddress6->sin6_family ) { 439 Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n", 440 pRemoteAddress4->sin_addr.s_addr & 0xff, 441 ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff, 442 ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff, 443 ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff, 444 ntohs ( pRemoteAddress4->sin_port )); 445 } 446 else { 447 Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", 448 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], 449 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], 450 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], 451 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], 452 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], 453 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], 454 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], 455 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], 456 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], 457 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], 458 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], 459 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], 460 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], 461 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], 462 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], 463 pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], 464 ntohs ( pRemoteAddress6->sin6_port )); 465 } 466Print ( L"ConnectStatus: %d, Status: %r\r\n", ConnectStatus, Status ); 467 } 468 else { 469 // 470 // Close the socket and try again 471 // 472 if ( EAGAIN != errno ) { 473 Status = EFI_NOT_STARTED; 474 break; 475 } 476 } 477 } while ( -1 == ConnectStatus ); 478 479 // 480 // Return the operation status 481 // 482Print ( L"SocketConnect returning Status: %r\r\n", Status ); 483 return Status; 484} 485 486 487/** 488 Create the socket 489 490 @param [in] Family Network family, AF_INET or AF_INET6 491 492 @retval EFI_SUCCESS The application is running normally 493 @retval Other The user stopped the application 494**/ 495EFI_STATUS 496SocketNew ( 497 sa_family_t Family 498 ) 499{ 500 EFI_STATUS Status; 501 502 // 503 // Loop creating the socket 504 // 505 DEBUG (( DEBUG_INFO, 506 "Creating the socket\r\n" )); 507 do { 508 // 509 // Check for user stop request 510 // 511 Status = ControlCCheck ( ); 512 if ( EFI_ERROR ( Status )) { 513 break; 514 } 515 516 // 517 // Attempt to create the socket 518 // 519 Socket = socket ( Family, 520 SOCK_STREAM, 521 IPPROTO_TCP ); 522 if ( -1 != Socket ) { 523 DEBUG (( DEBUG_INFO, 524 "0x%08x: Socket created\r\n", 525 Socket )); 526 break; 527 } 528 } while ( -1 == Socket ); 529 530 // 531 // Return the operation status 532 // 533 return Status; 534} 535 536 537/** 538 Send data over the socket 539 540 @retval EFI_SUCCESS The application is running normally 541 @retval Other The user stopped the application 542**/ 543EFI_STATUS 544SocketSend ( 545 ) 546{ 547 size_t BytesSent; 548 EFI_STATUS Status; 549 EFI_TPL TplPrevious; 550 551 // 552 // Restart the timer 553 // 554 TimerStart ( 1 * 1000 ); 555 556 // 557 // Loop until the connection breaks or the user stops 558 // 559 do { 560 // 561 // Check for user stop request 562 // 563 Status = ControlCCheck ( ); 564 if ( EFI_ERROR ( Status )) { 565 break; 566 } 567 568 // 569 // Send some bytes 570 // 571 BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer )); 572 if ( -1 == BytesSent ) { 573 DEBUG (( DEBUG_INFO, 574 "ERROR: send failed, errno: %d\r\n", 575 errno )); 576Print ( L"ERROR: send failed, errno: %d\r\n", errno ); 577 578 // 579 // Try again 580 // 581 Status = EFI_SUCCESS; 582 583// 584// Exit now 585// 586Status = EFI_NOT_STARTED; 587 break; 588 } 589 590 // 591 // Synchronize with the TimerCallback routine 592 // 593 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE ); 594 595 // 596 // Account for the data sent 597 // 598 TotalBytesSent += BytesSent; 599 600 // 601 // Release the TimerCallback routine synchronization 602 // 603 gBS->RestoreTPL ( TplPrevious ); 604 } while ( !EFI_ERROR ( Status )); 605 606 // 607 // Return the operation status 608 // 609 return Status; 610} 611 612 613/** 614 Open the network connection and send the data. 615 616 @retval EFI_SUCCESS Continue looping 617 @retval other Stopped by user's Control-C input 618 619**/ 620EFI_STATUS 621SocketOpen ( 622 ) 623{ 624 EFI_STATUS Status; 625 626 // 627 // Use do/while and break instead of goto 628 // 629 do { 630 // 631 // Wait for the network layer to initialize 632 // 633 Status = SocketNew ( RemoteHostAddress.sin6_family ); 634 if ( EFI_ERROR ( Status )) { 635 break; 636 } 637 638 // 639 // Wait for the remote network application to start 640 // 641 Status = SocketConnect ( ); 642Print ( L"Status: %r\r\n", Status ); 643 if ( EFI_NOT_STARTED == Status ) { 644 Status = SocketClose ( ); 645 continue; 646 } 647 else if ( EFI_SUCCESS != Status ) { 648 // 649 // Control-C 650 // 651 break; 652 } 653 654 // 655 // Send data until the connection breaks 656 // 657 Status = SocketSend ( ); 658 if ( EFI_ERROR ( Status )) { 659 break; 660 } 661 } while ( FALSE ); 662 663 // 664 // Return the operation status 665 // 666Print ( L"Returning Status: %r\r\n", Status ); 667 return Status; 668} 669 670 671/** 672 Close the TCP connection 673 674 @retval EFI_SUCCESS The application is running normally 675 @retval Other The user stopped the application 676**/ 677EFI_STATUS 678Tcp4Close ( 679 ) 680{ 681 UINTN Index; 682 UINT8 * pIpAddress; 683 EFI_STATUS Status; 684 685 // 686 // Close the port 687 // 688 if ( bTcp4Connected ) { 689 Tcp4CloseToken.AbortOnClose = TRUE; 690 Status = pTcp4Protocol->Close ( pTcp4Protocol, 691 &Tcp4CloseToken ); 692 if ( EFI_ERROR ( Status )) { 693 DEBUG (( DEBUG_ERROR, 694 "ERROR - Failed to start the TCP port close, Status: %r\r\n", 695 Status )); 696 } 697 else { 698 Status = gBS->WaitForEvent ( 1, 699 &Tcp4CloseToken.CompletionToken.Event, 700 &Index ); 701 if ( EFI_ERROR ( Status )) { 702 DEBUG (( DEBUG_ERROR, 703 "ERROR - Failed to wait for close event, Status: %r\r\n", 704 Status )); 705 } 706 else { 707 Status = Tcp4CloseToken.CompletionToken.Status; 708 if ( EFI_ERROR ( Status )) { 709 DEBUG (( DEBUG_ERROR, 710 "ERROR - Failed to close the TCP port, Status: %r\r\n", 711 Status )); 712 } 713 else { 714 DEBUG (( DEBUG_INFO, 715 "0x%08x: TCP port closed\r\n", 716 pTcp4Protocol )); 717 bTcp4Connected = FALSE; 718 719 // 720 // Display the port closed message 721 // 722 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr; 723 Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n", 724 pIpAddress[0], 725 pIpAddress[1], 726 pIpAddress[2], 727 pIpAddress[3], 728 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port )); 729 } 730 } 731 } 732 } 733 734 // 735 // Release the events 736 // 737 if ( NULL != Tcp4TxToken.CompletionToken.Event ) { 738 Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event ); 739 if ( !EFI_ERROR ( Status )) { 740 DEBUG (( DEBUG_INFO, 741 "0x%08x: TX event closed\r\n", 742 Tcp4TxToken.CompletionToken.Event )); 743 Tcp4TxToken.CompletionToken.Event = NULL; 744 } 745 else { 746 DEBUG (( DEBUG_ERROR, 747 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n", 748 Status )); 749 } 750 } 751 752 if ( NULL != Tcp4ListenToken.CompletionToken.Event ) { 753 Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event ); 754 if ( !EFI_ERROR ( Status )) { 755 DEBUG (( DEBUG_INFO, 756 "0x%08x: Listen event closed\r\n", 757 Tcp4ListenToken.CompletionToken.Event )); 758 Tcp4ListenToken.CompletionToken.Event = NULL; 759 } 760 else { 761 DEBUG (( DEBUG_ERROR, 762 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n", 763 Status )); 764 } 765 } 766 767 if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) { 768 Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event ); 769 if ( !EFI_ERROR ( Status )) { 770 DEBUG (( DEBUG_INFO, 771 "0x%08x: Connect event closed\r\n", 772 Tcp4ConnectToken.CompletionToken.Event )); 773 Tcp4ConnectToken.CompletionToken.Event = NULL; 774 } 775 else { 776 DEBUG (( DEBUG_ERROR, 777 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n", 778 Status )); 779 } 780 } 781 782 if ( NULL != Tcp4CloseToken.CompletionToken.Event ) { 783 Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event ); 784 if ( !EFI_ERROR ( Status )) { 785 DEBUG (( DEBUG_INFO, 786 "0x%08x: Close event closed\r\n", 787 Tcp4CloseToken.CompletionToken.Event )); 788 Tcp4CloseToken.CompletionToken.Event = NULL; 789 } 790 else { 791 DEBUG (( DEBUG_ERROR, 792 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n", 793 Status )); 794 } 795 } 796 797 // 798 // Close the TCP protocol 799 // 800 if ( NULL != pTcp4Protocol ) { 801 Status = gBS->CloseProtocol ( Tcp4Handle, 802 &gEfiTcp4ProtocolGuid, 803 gImageHandle, 804 NULL ); 805 if ( EFI_ERROR ( Status )) { 806 DEBUG (( DEBUG_ERROR, 807 "ERROR - Failed to close the TCP protocol, Status: %r\r\n", 808 Status )); 809 } 810 else { 811 DEBUG (( DEBUG_INFO, 812 "0x%08x: TCP4 protocol closed\r\n", 813 pTcp4Protocol )); 814 pTcp4Protocol = NULL; 815 } 816 } 817 818 // 819 // Done with the TCP service 820 // 821 if ( NULL != Tcp4Handle ) { 822 Status = pTcp4Service->DestroyChild ( pTcp4Service, 823 Tcp4Handle ); 824 if ( EFI_ERROR ( Status )) { 825 DEBUG (( DEBUG_ERROR, 826 "ERROR - Failed to release TCP service handle, Status: %r\r\n", 827 Status )); 828 } 829 else { 830 DEBUG (( DEBUG_INFO, 831 "Ox%08x: TCP service closed\r\n", 832 Tcp4Handle )); 833 Tcp4Handle = NULL; 834 } 835 } 836 837 // 838 // Close the service protocol 839 // 840 if ( NULL != pTcp4Service ) { 841 Status = gBS->CloseProtocol ( Tcp4Controller, 842 &gEfiTcp4ServiceBindingProtocolGuid, 843 gImageHandle, 844 NULL ); 845 if ( !EFI_ERROR ( Status )) { 846 DEBUG (( DEBUG_INFO, 847 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n", 848 Tcp4Controller )); 849 pTcp4Service = NULL; 850 } 851 else { 852 DEBUG (( DEBUG_ERROR, 853 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n", 854 Status )); 855 } 856 } 857 Tcp4Controller = NULL; 858 bTcp4Connecting = TRUE; 859 860 // 861 // Mark the connection as closed 862 // 863 Status = EFI_SUCCESS; 864 865 // 866 // Return the operation status 867 // 868 return Status; 869} 870 871 872/** 873 Locate TCP protocol 874 875 @retval EFI_SUCCESS Protocol found 876 @retval other Protocl not found 877**/ 878EFI_STATUS 879Tcp4Locate ( 880 ) 881{ 882 UINTN HandleCount; 883 EFI_HANDLE * pHandles; 884 UINT8 * pIpAddress; 885 EFI_STATUS Status; 886 887 // 888 // Use do/while and break instead of goto 889 // 890 do { 891 // 892 // Attempt to locate the next TCP adapter in the system 893 // 894 Status = gBS->LocateHandleBuffer ( ByProtocol, 895 &gEfiTcp4ServiceBindingProtocolGuid, 896 NULL, 897 &HandleCount, 898 &pHandles ); 899 if ( EFI_ERROR ( Status )) { 900 DEBUG (( DEBUG_WARN, 901 "WARNING - No network controllers or TCP4 available, Status: %r\r\n", 902 Status )); 903 break; 904 } 905 906 // 907 // Wrap the index if necessary 908 // 909 if ( HandleCount <= Tcp4Index ) { 910 Tcp4Index = 0; 911 912 // 913 // Wait for the next timer tick 914 // 915 do { 916 } while ( !bTick ); 917 bTick = FALSE; 918 } 919 920 // 921 // Display the connecting message 922 // 923 if ( bTcp4Connecting ) { 924 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr; 925 Print ( L"Connecting to %d.%d.%d.%d:%d\r\n", 926 pIpAddress[0], 927 pIpAddress[1], 928 pIpAddress[2], 929 pIpAddress[3], 930 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port )); 931 bTcp4Connecting = FALSE; 932 } 933 934 // 935 // Open the network controller's service protocol 936 // 937 Tcp4Controller = pHandles[ Tcp4Index++ ]; 938 Status = gBS->OpenProtocol ( 939 Tcp4Controller, 940 &gEfiTcp4ServiceBindingProtocolGuid, 941 (VOID **) &pTcp4Service, 942 gImageHandle, 943 NULL, 944 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ); 945 if ( EFI_ERROR ( Status )) { 946 DEBUG (( DEBUG_ERROR, 947 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n", 948 Tcp4Controller )); 949 Tcp4Controller = NULL; 950 break; 951 } 952 DEBUG (( DEBUG_INFO, 953 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n", 954 Tcp4Controller )); 955 956 // 957 // Connect to the TCP service 958 // 959 Status = pTcp4Service->CreateChild ( pTcp4Service, 960 &Tcp4Handle ); 961 if ( EFI_ERROR ( Status )) { 962 DEBUG (( DEBUG_ERROR, 963 "ERROR - Failed to open TCP service, Status: %r\r\n", 964 Status )); 965 Tcp4Handle = NULL; 966 break; 967 } 968 DEBUG (( DEBUG_INFO, 969 "Ox%08x: TCP service opened\r\n", 970 Tcp4Handle )); 971 972 // 973 // Locate the TCP protcol 974 // 975 Status = gBS->OpenProtocol ( Tcp4Handle, 976 &gEfiTcp4ProtocolGuid, 977 (VOID **)&pTcp4Protocol, 978 gImageHandle, 979 NULL, 980 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ); 981 if ( EFI_ERROR ( Status )) { 982 DEBUG (( DEBUG_ERROR, 983 "ERROR - Failed to open the TCP protocol, Status: %r\r\n", 984 Status )); 985 pTcp4Protocol = NULL; 986 break; 987 } 988 DEBUG (( DEBUG_INFO, 989 "0x%08x: TCP4 protocol opened\r\n", 990 pTcp4Protocol )); 991 }while ( FALSE ); 992 993 // 994 // Release the handle buffer 995 // 996 gBS->FreePool ( pHandles ); 997 998 // 999 // Return the operation status 1000 // 1001 return Status; 1002} 1003 1004 1005/** 1006 Send data over the TCP4 connection 1007 1008 @retval EFI_SUCCESS The application is running normally 1009 @retval Other The user stopped the application 1010**/ 1011EFI_STATUS 1012Tcp4Send ( 1013 ) 1014{ 1015 UINTN Index; 1016 EFI_TCP4_TRANSMIT_DATA Packet; 1017 EFI_STATUS Status; 1018 EFI_TPL TplPrevious; 1019 1020 // 1021 // Restart the timer 1022 // 1023 TimerStart ( 1 * 1000 ); 1024 1025 // 1026 // Initialize the packet 1027 // 1028 Packet.DataLength = sizeof ( Buffer ); 1029 Packet.FragmentCount = 1; 1030 Packet.Push = FALSE; 1031 Packet.Urgent = FALSE; 1032 Packet.FragmentTable[0].FragmentBuffer = &Buffer[0]; 1033 Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer ); 1034 Tcp4TxToken.Packet.TxData = &Packet; 1035 1036 // 1037 // Loop until the connection breaks or the user stops 1038 // 1039 do { 1040 // 1041 // Check for user stop request 1042 // 1043 Status = ControlCCheck ( ); 1044 if ( EFI_ERROR ( Status )) { 1045 break; 1046 } 1047 1048 // 1049 // Send some bytes 1050 // 1051 Status = pTcp4Protocol->Transmit ( pTcp4Protocol, 1052 &Tcp4TxToken ); 1053 if ( EFI_ERROR ( Status )) { 1054 DEBUG (( DEBUG_ERROR, 1055 "ERROR - Failed to start the transmit, Status: %r\r\n", 1056 Status )); 1057 1058 // 1059 // Try again 1060 // 1061 Status = EFI_SUCCESS; 1062 break; 1063 } 1064 1065 // 1066 // Wait for the transmit to complete 1067 // 1068 Status = gBS->WaitForEvent ( 1, 1069 &Tcp4TxToken.CompletionToken.Event, 1070 &Index ); 1071 if ( EFI_ERROR ( Status )) { 1072 DEBUG (( DEBUG_ERROR, 1073 "ERROR - Failed to wait for transmit completion, Status: %r\r\n", 1074 Status )); 1075 1076 // 1077 // Try again 1078 // 1079 Status = EFI_SUCCESS; 1080 break; 1081 } 1082 1083 // 1084 // Get the transmit status 1085 // 1086 Status = Tcp4TxToken.CompletionToken.Status; 1087 if ( EFI_ERROR ( Status )) { 1088 DEBUG (( DEBUG_WARN, 1089 "WARNING - Failed the transmission, Status: %r\r\n", 1090 Status )); 1091 1092 // 1093 // Try again 1094 // 1095 Status = EFI_SUCCESS; 1096 1097// 1098// Exit now 1099// 1100Status = EFI_NOT_STARTED; 1101 break; 1102 } 1103 1104 // 1105 // Synchronize with the TimerCallback routine 1106 // 1107 TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE ); 1108 1109 // 1110 // Account for the data sent 1111 // 1112 TotalBytesSent += Packet.DataLength; 1113 1114 // 1115 // Release the TimerCallback routine synchronization 1116 // 1117 gBS->RestoreTPL ( TplPrevious ); 1118 } while ( !EFI_ERROR ( Status )); 1119 1120 // 1121 // Return the operation status 1122 // 1123 return Status; 1124} 1125 1126 1127/** 1128 Open the network connection and send the data. 1129 1130 @retval EFI_SUCCESS Continue looping 1131 @retval other Stopped by user's Control-C input 1132 1133**/ 1134EFI_STATUS 1135Tcp4Open ( 1136 ) 1137{ 1138 UINTN Index; 1139 UINT8 * pIpAddress; 1140 EFI_STATUS Status; 1141 1142 // 1143 // Use do/while and break instead of goto 1144 // 1145 do { 1146 // 1147 // Locate the TCP protocol 1148 // 1149 Status = Tcp4Locate ( ); 1150 if ( EFI_ERROR ( Status )) { 1151 break; 1152 } 1153 1154 // 1155 // Create the necessary events 1156 // 1157 Status = gBS->CreateEvent ( 0, 1158 TPL_CALLBACK, 1159 NULL, 1160 NULL, 1161 &Tcp4CloseToken.CompletionToken.Event ); 1162 if ( EFI_ERROR ( Status )) { 1163 DEBUG (( DEBUG_ERROR, 1164 "ERROR - Failed to create the close event, Status: %r\r\n", 1165 Status )); 1166 Tcp4CloseToken.CompletionToken.Event = NULL; 1167 break; 1168 } 1169 DEBUG (( DEBUG_INFO, 1170 "0x%08x: Close event open\r\n", 1171 Tcp4CloseToken.CompletionToken.Event )); 1172 1173 Status = gBS->CreateEvent ( 0, 1174 TPL_CALLBACK, 1175 NULL, 1176 NULL, 1177 &Tcp4ConnectToken.CompletionToken.Event ); 1178 if ( EFI_ERROR ( Status )) { 1179 DEBUG (( DEBUG_ERROR, 1180 "ERROR - Failed to create the connect event, Status: %r\r\n", 1181 Status )); 1182 Tcp4ConnectToken.CompletionToken.Event = NULL; 1183 break; 1184 } 1185 DEBUG (( DEBUG_INFO, 1186 "0x%08x: Connect event open\r\n", 1187 Tcp4ConnectToken.CompletionToken.Event )); 1188 1189 Status = gBS->CreateEvent ( 0, 1190 TPL_CALLBACK, 1191 NULL, 1192 NULL, 1193 &Tcp4ListenToken.CompletionToken.Event ); 1194 if ( EFI_ERROR ( Status )) { 1195 DEBUG (( DEBUG_ERROR, 1196 "ERROR - Failed to create the listen event, Status: %r\r\n", 1197 Status )); 1198 Tcp4ListenToken.CompletionToken.Event = NULL; 1199 break; 1200 } 1201 DEBUG (( DEBUG_INFO, 1202 "0x%08x: Listen event open\r\n", 1203 Tcp4ListenToken.CompletionToken.Event )); 1204 1205 Status = gBS->CreateEvent ( 0, 1206 TPL_CALLBACK, 1207 NULL, 1208 NULL, 1209 &Tcp4TxToken.CompletionToken.Event ); 1210 if ( EFI_ERROR ( Status )) { 1211 DEBUG (( DEBUG_ERROR, 1212 "ERROR - Failed to create the TX event, Status: %r\r\n", 1213 Status )); 1214 Tcp4TxToken.CompletionToken.Event = NULL; 1215 break; 1216 } 1217 DEBUG (( DEBUG_INFO, 1218 "0x%08x: TX event open\r\n", 1219 Tcp4TxToken.CompletionToken.Event )); 1220 1221 // 1222 // Configure the local TCP port 1223 // 1224 Tcp4ConfigData.TimeToLive = 255; 1225 Tcp4ConfigData.TypeOfService = 0; 1226 Tcp4ConfigData.ControlOption = NULL; 1227 Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE; 1228 Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0; 1229 Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 0; 1230 Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0; 1231 Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0; 1232 Tcp4ConfigData.AccessPoint.StationPort = 0; 1233 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8) ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr; 1234 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 ); 1235 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 ); 1236 Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 ); 1237 Tcp4ConfigData.AccessPoint.RemotePort = ntohs (((struct sockaddr_in *)&RemoteHostAddress)->sin_port); 1238 Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE; 1239 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0; 1240 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0; 1241 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0; 1242 Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0; 1243 Status = pTcp4Protocol->Configure ( pTcp4Protocol, 1244 &Tcp4ConfigData ); 1245 if ( EFI_ERROR ( Status )) { 1246 DEBUG (( DEBUG_ERROR, 1247 "ERROR - Failed to configure TCP port, Status: %r\r\n", 1248 Status )); 1249 break; 1250 } 1251 DEBUG (( DEBUG_INFO, 1252 "0x%08x: TCP4 port configured\r\n", 1253 pTcp4Protocol )); 1254 1255 // 1256 // Connect to the remote TCP port 1257 // 1258 Status = pTcp4Protocol->Connect ( pTcp4Protocol, 1259 &Tcp4ConnectToken ); 1260 if ( EFI_ERROR ( Status )) { 1261 DEBUG (( DEBUG_ERROR, 1262 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n", 1263 Status )); 1264 break; 1265 } 1266 Status = gBS->WaitForEvent ( 1, 1267 &Tcp4ConnectToken.CompletionToken.Event, 1268 &Index ); 1269 if ( EFI_ERROR ( Status )) { 1270 DEBUG (( DEBUG_ERROR, 1271 "ERROR - Failed to wait for the connection, Status: %r\r\n", 1272 Status )); 1273 break; 1274 } 1275 Status = Tcp4ConnectToken.CompletionToken.Status; 1276 if ( EFI_ERROR ( Status )) { 1277 DEBUG (( DEBUG_WARN, 1278 "WARNING - Failed to connect to the remote system, Status: %r\r\n", 1279 Status )); 1280 break; 1281 } 1282 DEBUG (( DEBUG_INFO, 1283 "0x%08x: TCP4 port connected\r\n", 1284 pTcp4Protocol )); 1285 bTcp4Connected = TRUE; 1286 1287 // 1288 // Display the connection 1289 // 1290 pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr; 1291 Print ( L"Connected to %d.%d.%d.%d:%d\r\n", 1292 pIpAddress[0], 1293 pIpAddress[1], 1294 pIpAddress[2], 1295 pIpAddress[3], 1296 ntohs ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port )); 1297 } while ( 0 ); 1298 1299 if ( EFI_ERROR ( Status )) { 1300 // 1301 // Try again 1302 // 1303 Status = EFI_SUCCESS; 1304 } 1305 else { 1306 // 1307 // Semd data until the connection breaks 1308 // 1309 Status = Tcp4Send ( ); 1310 } 1311 1312 // 1313 // Return the operation status 1314 // 1315 return Status; 1316} 1317 1318 1319/** 1320 Handle the timer callback 1321 1322 @param [in] Event Event that caused this callback 1323 @param [in] pContext Context for this routine 1324**/ 1325VOID 1326EFIAPI 1327TimerCallback ( 1328 IN EFI_EVENT Event, 1329 IN VOID * pContext 1330 ) 1331{ 1332 UINT32 Average; 1333 UINT64 BitsPerSecond; 1334 UINT32 Index; 1335 UINT64 TotalBytes; 1336 1337 // 1338 // Notify the other code of the timer tick 1339 // 1340 bTick = TRUE; 1341 1342 // 1343 // Update the average bytes per second 1344 // 1345 if ( 0 != TotalBytesSent ) { 1346 BytesSent[ In ] = TotalBytesSent; 1347 TotalBytesSent = 0; 1348 In += 1; 1349 if ( DATA_SAMPLES <= In ) { 1350 In = 0; 1351 } 1352 1353 // 1354 // Separate the samples 1355 // 1356 if ( DATA_SAMPLES == Samples ) { 1357 Print ( L"---------- Stable average ----------\r\n" ); 1358 } 1359 Samples += 1; 1360 1361 // 1362 // Compute the data rate 1363 // 1364 TotalBytes = 0; 1365 for ( Index = 0; DATA_SAMPLES > Index; Index++ ) { 1366 TotalBytes += BytesSent[ Index ]; 1367 } 1368 Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT ); 1369 BitsPerSecond = Average * 8; 1370 1371 // 1372 // Display the data rate 1373 // 1374 if (( RANGE_SWITCH >> 10 ) > Average ) { 1375 Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n", 1376 Average, 1377 BitsPerSecond ); 1378 } 1379 else { 1380 BitsPerSecond /= 1000; 1381 if ( RANGE_SWITCH > Average ) { 1382 Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n", 1383 Average >> 10, 1384 (( Average & 0x3ff ) * 1000 ) >> 10, 1385 BitsPerSecond ); 1386 } 1387 else { 1388 BitsPerSecond /= 1000; 1389 Average >>= 10; 1390 if ( RANGE_SWITCH > Average ) { 1391 Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n", 1392 Average >> 10, 1393 (( Average & 0x3ff ) * 1000 ) >> 10, 1394 BitsPerSecond ); 1395 } 1396 else { 1397 BitsPerSecond /= 1000; 1398 Average >>= 10; 1399 if ( RANGE_SWITCH > Average ) { 1400 Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n", 1401 Average >> 10, 1402 (( Average & 0x3ff ) * 1000 ) >> 10, 1403 BitsPerSecond ); 1404 } 1405 else { 1406 BitsPerSecond /= 1000; 1407 Average >>= 10; 1408 if ( RANGE_SWITCH > Average ) { 1409 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n", 1410 Average >> 10, 1411 (( Average & 0x3ff ) * 1000 ) >> 10, 1412 BitsPerSecond ); 1413 } 1414 else { 1415 BitsPerSecond /= 1000; 1416 Average >>= 10; 1417 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n", 1418 Average >> 10, 1419 (( Average & 0x3ff ) * 1000 ) >> 10, 1420 BitsPerSecond ); 1421 } 1422 } 1423 } 1424 } 1425 } 1426 } 1427} 1428 1429 1430/** 1431 Create the timer 1432 1433 @retval EFI_SUCCESS The timer was successfully created 1434 @retval Other Timer initialization failed 1435**/ 1436EFI_STATUS 1437TimerCreate ( 1438 ) 1439{ 1440 EFI_STATUS Status; 1441 1442 // 1443 // Create the timer 1444 // 1445 Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, 1446 TPL_DATASOURCE, 1447 TimerCallback, 1448 NULL, 1449 &pTimer ); 1450 if ( EFI_ERROR ( Status )) { 1451 DEBUG (( DEBUG_ERROR, 1452 "ERROR - Failed to allocate the timer event, Status: %r\r\n", 1453 Status )); 1454 } 1455 else { 1456 DEBUG (( DEBUG_INFO, 1457 "0x%08x: Timer created\r\n", 1458 pTimer )); 1459 } 1460 1461 // 1462 // Return the operation status 1463 // 1464 return Status; 1465} 1466 1467 1468/** 1469 Stop the timer 1470 1471 @retval EFI_SUCCESS The timer was stopped successfully 1472 @retval Other The timer failed to stop 1473**/ 1474EFI_STATUS 1475TimerStop ( 1476 ) 1477{ 1478 EFI_STATUS Status; 1479 1480 // 1481 // Assume success 1482 // 1483 Status = EFI_SUCCESS; 1484 1485 // 1486 // Determine if the timer is running 1487 // 1488 if ( bTimerRunning ) { 1489 // 1490 // Stop the timer 1491 // 1492 Status = gBS->SetTimer ( pTimer, 1493 TimerCancel, 1494 0 ); 1495 if ( EFI_ERROR ( Status )) { 1496 DEBUG (( DEBUG_ERROR, 1497 "ERROR - Failed to stop the timer, Status: %r\r\n", 1498 Status )); 1499 } 1500 else { 1501 // 1502 // Timer timer is now stopped 1503 // 1504 bTimerRunning = FALSE; 1505 DEBUG (( DEBUG_INFO, 1506 "0x%08x: Timer stopped\r\n", 1507 pTimer )); 1508 } 1509 } 1510 1511 // 1512 // Return the operation status 1513 // 1514 return Status; 1515} 1516 1517 1518/** 1519 Start the timer 1520 1521 @param [in] Milliseconds The number of milliseconds between timer callbacks 1522 1523 @retval EFI_SUCCESS The timer was successfully created 1524 @retval Other Timer initialization failed 1525**/ 1526EFI_STATUS 1527TimerStart ( 1528 UINTN Milliseconds 1529 ) 1530{ 1531 EFI_STATUS Status; 1532 UINT64 TimeDelay; 1533 1534 // 1535 // Stop the timer if necessary 1536 // 1537 Status = EFI_SUCCESS; 1538 if ( bTimerRunning ) { 1539 Status = TimerStop ( ); 1540 } 1541 if ( !EFI_ERROR ( Status )) { 1542 // 1543 // Compute the new delay 1544 // 1545 TimeDelay = Milliseconds; 1546 TimeDelay *= 1000 * 10; 1547 1548 // 1549 // Start the timer 1550 // 1551 Status = gBS->SetTimer ( pTimer, 1552 TimerPeriodic, 1553 TimeDelay ); 1554 if ( EFI_ERROR ( Status )) { 1555 DEBUG (( DEBUG_ERROR, 1556 "ERROR - Failed to start the timer, Status: %r\r\n", 1557 Status )); 1558 } 1559 else { 1560 // 1561 // The timer is now running 1562 // 1563 bTimerRunning = TRUE; 1564 DEBUG (( DEBUG_INFO, 1565 "0x%08x: Timer running\r\n", 1566 pTimer )); 1567 } 1568 } 1569 1570 // 1571 // Return the operation status 1572 // 1573 return Status; 1574} 1575 1576 1577/** 1578 Destroy the timer 1579 1580 @retval EFI_SUCCESS The timer was destroyed successfully 1581 @retval Other Failed to destroy the timer 1582**/ 1583EFI_STATUS 1584TimerDestroy ( 1585 ) 1586{ 1587 EFI_STATUS Status; 1588 1589 // 1590 // Assume success 1591 // 1592 Status = EFI_SUCCESS; 1593 1594 // 1595 // Determine if the timer is running 1596 // 1597 if ( bTimerRunning ) { 1598 // 1599 // Stop the timer 1600 // 1601 Status = TimerStop ( ); 1602 } 1603 if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) { 1604 // 1605 // Done with this timer 1606 // 1607 Status = gBS->CloseEvent ( pTimer ); 1608 if ( EFI_ERROR ( Status )) { 1609 DEBUG (( DEBUG_ERROR, 1610 "ERROR - Failed to free the timer event, Status: %r\r\n", 1611 Status )); 1612 } 1613 else { 1614 DEBUG (( DEBUG_INFO, 1615 "0x%08x: Timer Destroyed\r\n", 1616 pTimer )); 1617 pTimer = NULL; 1618 } 1619 } 1620 1621 // 1622 // Return the operation status 1623 // 1624 return Status; 1625} 1626 1627 1628/** 1629 Send data to the DataSink program to test a network's bandwidth. 1630 1631 @param [in] Argc The number of arguments 1632 @param [in] Argv The argument value array 1633 1634 @retval 0 The application exited normally. 1635 @retval Other An error occurred. 1636**/ 1637int 1638main ( 1639 IN int Argc, 1640 IN char **Argv 1641 ) 1642{ 1643 EFI_STATUS (* pClose) (); 1644 EFI_STATUS (* pOpen) (); 1645 EFI_STATUS Status; 1646 1647 DEBUG (( DEBUG_INFO, 1648 "DataSource starting\r\n" )); 1649 1650 // 1651 // Validate the command line 1652 // 1653 if ( 2 > Argc ) { 1654 Print ( L"%s <remote IP address> [Use TCP]\r\n", Argv[0] ); 1655 return -1; 1656 } 1657 1658 // 1659 // Determine if TCP should be used 1660 // 1661 bTcp4 = (BOOLEAN)( 2 < Argc ); 1662 1663 // 1664 // Determine the support routines 1665 // 1666 if ( bTcp4 ) { 1667 pOpen = Tcp4Open; 1668 pClose = Tcp4Close; 1669 bTcp4Connecting = TRUE; 1670 } 1671 else { 1672 pOpen = SocketOpen; 1673 pClose = SocketClose; 1674 } 1675 1676 // 1677 // Use for/break instead of goto 1678 // 1679 for ( ; ; ) { 1680 // 1681 // No bytes sent so far 1682 // 1683 TotalBytesSent = 0; 1684 Samples = 0; 1685 memset ( &BytesSent, 0, sizeof ( BytesSent )); 1686 1687 // 1688 // Get the IP address 1689 // 1690 pRemoteHost = Argv[1]; 1691 Status = IpAddress ( ); 1692 if ( EFI_ERROR ( Status )) { 1693 break; 1694 } 1695 1696 // 1697 // Create the timer 1698 // 1699 bTick = TRUE; 1700 Status = TimerCreate ( ); 1701 if ( EFI_ERROR ( Status )) { 1702 break; 1703 } 1704 1705 // 1706 // Loop forever abusing the specified system 1707 // 1708 do { 1709 // 1710 // Start a timer to perform connection polling and display updates 1711 // 1712 Status = TimerStart ( 2 * 1000 ); 1713 if ( EFI_ERROR ( Status )) { 1714 break; 1715 } 1716 1717 // 1718 // Open the network connection and send the data 1719 // 1720 Status = pOpen ( ); 1721 if ( EFI_ERROR ( Status )) { 1722 break; 1723 } 1724 1725 // 1726 // Done with the network connection 1727 // 1728 Status = pClose ( ); 1729 } while ( !EFI_ERROR ( Status )); 1730 1731 // 1732 // Close the network connection if necessary 1733 // 1734 pClose ( ); 1735 1736 // 1737 // All done 1738 // 1739 break; 1740 } 1741 1742 // 1743 // Stop the timer if necessary 1744 // 1745 TimerStop ( ); 1746 TimerDestroy ( ); 1747 1748 // 1749 // Return the operation status 1750 // 1751 DEBUG (( DEBUG_INFO, 1752 "DataSource exiting, Status: %r\r\n", 1753 Status )); 1754 return Status; 1755} 1756