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