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