]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Merged socket development branch:
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 9 Feb 2012 19:18:06 +0000 (19:18 +0000)
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 9 Feb 2012 19:18:06 +0000 (19:18 +0000)
* Add TCPv6 support to DataSink
* Add TCPv6 support to DataSource
* Add GetAddrInfo test application
* Add GetNameInfo test application
* Fixed copyright date
* Completed TFTP server - now downloads files from local directory
* Added ports and exit pages to web server
* Made PCD values package specific

Signed-off-by: lpleahy
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13003 6f19259b-4bc3-4df7-8a09-765794883524

34 files changed:
AppPkg/AppPkg.dec [new file with mode: 0644]
AppPkg/Applications/Sockets/DataSink/DataSink.c
AppPkg/Applications/Sockets/DataSink/DataSink.inf
AppPkg/Applications/Sockets/DataSource/DataSource.c
AppPkg/Applications/Sockets/DataSource/DataSource.inf
AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf
AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf
AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf
AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf
AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf
AppPkg/Applications/Sockets/GetServByName/GetServByName.inf
AppPkg/Applications/Sockets/GetServByPort/GetServByPort.inf
AppPkg/Applications/Sockets/OobRx/OobRx.inf
AppPkg/Applications/Sockets/OobTx/OobTx.inf
AppPkg/Applications/Sockets/RawIp4Rx/RawIp4Rx.inf
AppPkg/Applications/Sockets/RawIp4Tx/RawIp4Tx.inf
AppPkg/Applications/Sockets/RecvDgram/RecvDgram.inf
AppPkg/Applications/Sockets/SetHostName/SetHostName.inf
AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.inf
AppPkg/Applications/Sockets/Sockets.inc
AppPkg/Applications/Sockets/TftpServer/TftpServer.c
AppPkg/Applications/Sockets/TftpServer/TftpServer.h
AppPkg/Applications/Sockets/TftpServer/TftpServer.inf
AppPkg/Applications/Sockets/WebServer/Exit.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/HTTP.c
AppPkg/Applications/Sockets/WebServer/PageList.c
AppPkg/Applications/Sockets/WebServer/Ports.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/WebServer.c
AppPkg/Applications/Sockets/WebServer/WebServer.h
AppPkg/Applications/Sockets/WebServer/WebServer.inf

diff --git a/AppPkg/AppPkg.dec b/AppPkg/AppPkg.dec
new file mode 100644 (file)
index 0000000..8aff19f
--- /dev/null
@@ -0,0 +1,36 @@
+## @file\r
+#   Declarations for the UDK Standard Libraries.\r
+#\r
+# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available under\r
+# the terms and conditions of the BSD License which accompanies this distribution.\r
+# The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+##\r
+\r
+\r
+[Defines]\r
+  DEC_SPECIFICATION              = 0x00010005\r
+  PACKAGE_NAME                   = AppPkg\r
+  PACKAGE_GUID                   = B3E3D3D5-D62B-4497-A175-264F489D127E\r
+  PACKAGE_VERSION                = 0.01\r
+\r
+\r
+[Guids]\r
+  gAppPkgTokenSpaceGuid          = { 0xe7e1efa6, 0x7607, 0x4a78, { 0xa7, 0xdd, 0x43, 0xe4, 0xbd, 0x72, 0xc0, 0x99 }}\r
+\r
+\r
+[PcdsFixedAtBuild]\r
+  gAppPkgTokenSpaceGuid.DataSource_Port|1234|UINT16|0\r
+  gAppPkgTokenSpaceGuid.Tftp_AckLogBase|4|UINT32|1\r
+  gAppPkgTokenSpaceGuid.Tftp_AckMultiplier|4|UINT32|2\r
+  gAppPkgTokenSpaceGuid.Tftp_Bandwidth|0|BOOLEAN|3\r
+  gAppPkgTokenSpaceGuid.Tftp_HighSpeed|0|BOOLEAN|4\r
+  gAppPkgTokenSpaceGuid.Tftp_MaxRetry|10|UINT32|5\r
+  gAppPkgTokenSpaceGuid.Tftp_MaxTimeoutInSec|3|UINT32|6\r
+  gAppPkgTokenSpaceGuid.WebServer_HttpPort|80|UINT16|7\r
+\r
index 8223ead118079e3b652eb7d7f32c7d4ea122a4c2..05added9c2d550f1aced1841e8e1bf37c886d03b 100644 (file)
 #include <sys/socket.h>\r
 \r
 \r
 #include <sys/socket.h>\r
 \r
 \r
-#define MAX_CONNECTIONS       ( 1 + 16 )  ///<  Maximum number of client connections\r
-#define RANGE_SWITCH                2048  ///<  Switch display ranges\r
-#define DATA_RATE_UPDATE_SHIFT      2     ///<  2n seconds between updates\r
+#define DATA_SAMPLE_SHIFT           5       ///<  Shift for number of samples\r
+#define MAX_CONNECTIONS       ( 1 + 16 )    ///<  Maximum number of client connections\r
+#define RANGE_SWITCH        ( 1024 * 1024 ) ///<  Switch display ranges\r
+#define DATA_RATE_UPDATE_SHIFT      2       ///<  2n seconds between updates\r
 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average\r
 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average\r
+#define DATA_SAMPLES        ( 1 << DATA_SAMPLE_SHIFT )      ///<  Number of samples\r
 \r
 #define TPL_DATASINK        TPL_CALLBACK  ///<  Synchronization TPL\r
 \r
 \r
 #define TPL_DATASINK        TPL_CALLBACK  ///<  Synchronization TPL\r
 \r
 #define DATA_BUFFER_SIZE    (( 65536 / PACKET_SIZE ) * PACKET_SIZE )  ///<  Buffer size in bytes\r
 \r
 typedef struct _DT_PORT {\r
 #define DATA_BUFFER_SIZE    (( 65536 / PACKET_SIZE ) * PACKET_SIZE )  ///<  Buffer size in bytes\r
 \r
 typedef struct _DT_PORT {\r
-  UINT64 BytesAverage;\r
-  UINT64 BytesPrevious;\r
   UINT64 BytesTotal;\r
   UINT64 BytesTotal;\r
-  struct sockaddr_in RemoteAddress;\r
-  UINT64 Samples;\r
+  struct sockaddr_in6 IpAddress;\r
+  UINT32 In;\r
+  UINT32 Samples;\r
+  UINT64 BytesReceived[ DATA_SAMPLES ];\r
 } DT_PORT;\r
 \r
 volatile BOOLEAN bTick;\r
 BOOLEAN bTimerRunning;\r
 } DT_PORT;\r
 \r
 volatile BOOLEAN bTick;\r
 BOOLEAN bTimerRunning;\r
-struct sockaddr_in LocalAddress;\r
+struct sockaddr_in6 LocalAddress;\r
 EFI_EVENT pTimer;\r
 int ListenSocket;\r
 UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
 EFI_EVENT pTimer;\r
 int ListenSocket;\r
 UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
@@ -120,7 +122,7 @@ SocketAccept (
   //\r
   SocketStatus = bind ( ListenSocket,\r
                         (struct sockaddr *) &LocalAddress,\r
   //\r
   SocketStatus = bind ( ListenSocket,\r
                         (struct sockaddr *) &LocalAddress,\r
-                        LocalAddress.sin_len );\r
+                        LocalAddress.sin6_len );\r
   if ( 0 == SocketStatus ) {\r
     //\r
     //  Start listening on the local socket\r
   if ( 0 == SocketStatus ) {\r
     //\r
     //  Start listening on the local socket\r
@@ -139,14 +141,7 @@ SocketAccept (
       PollFd[ Index ].fd = ListenSocket;\r
       PollFd[ Index ].events = POLLRDNORM | POLLHUP;\r
       PollFd[ Index ].revents = 0;\r
       PollFd[ Index ].fd = ListenSocket;\r
       PollFd[ Index ].events = POLLRDNORM | POLLHUP;\r
       PollFd[ Index ].revents = 0;\r
-      Port[ Index ].BytesAverage = 0;\r
-      Port[ Index ].BytesPrevious = 0;\r
-      Port[ Index ].BytesTotal = 0;\r
-      Port[ Index ].Samples = 0;\r
-      Port[ Index ].RemoteAddress.sin_len = 0;\r
-      Port[ Index ].RemoteAddress.sin_family = 0;\r
-      Port[ Index ].RemoteAddress.sin_port = 0;\r
-      Port[ Index ].RemoteAddress.sin_addr.s_addr= 0;\r
+      ZeroMem ( &Port[ Index ], sizeof ( Port[ Index ]));\r
     }\r
   }\r
 \r
     }\r
   }\r
 \r
@@ -203,11 +198,14 @@ SocketClose (
 /**\r
   Create the socket\r
 \r
 /**\r
   Create the socket\r
 \r
+  @param [in] Family    Network family, AF_INET or AF_INET6\r
+\r
   @retval  EFI_SUCCESS  The application is running normally\r
   @retval  Other        The user stopped the application\r
 **/\r
 EFI_STATUS\r
 SocketNew (\r
   @retval  EFI_SUCCESS  The application is running normally\r
   @retval  Other        The user stopped the application\r
 **/\r
 EFI_STATUS\r
 SocketNew (\r
+  sa_family_t Family\r
   )\r
 {\r
   EFI_STATUS Status;\r
   )\r
 {\r
   EFI_STATUS Status;\r
@@ -216,9 +214,9 @@ SocketNew (
   //  Get the port number\r
   //\r
   ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));\r
   //  Get the port number\r
   //\r
   ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));\r
-  LocalAddress.sin_len = sizeof ( LocalAddress );\r
-  LocalAddress.sin_family = AF_INET;\r
-  LocalAddress.sin_port = htons ( PcdGet16 ( DataSource_Port ));\r
+  LocalAddress.sin6_len = sizeof ( LocalAddress );\r
+  LocalAddress.sin6_family = Family;\r
+  LocalAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));\r
   \r
   //\r
   //  Loop creating the socket\r
   \r
   //\r
   //  Loop creating the socket\r
@@ -234,7 +232,7 @@ SocketNew (
     //\r
     //  Attempt to create the socket\r
     //\r
     //\r
     //  Attempt to create the socket\r
     //\r
-    ListenSocket = socket ( AF_INET,\r
+    ListenSocket = socket ( LocalAddress.sin6_family,\r
                             SOCK_STREAM,\r
                             IPPROTO_TCP );\r
     if ( -1 != ListenSocket ) {\r
                             SOCK_STREAM,\r
                             IPPROTO_TCP );\r
     if ( -1 != ListenSocket ) {\r
@@ -274,7 +272,11 @@ SocketPoll (
   int FdCount;\r
   nfds_t Index;\r
   socklen_t LengthInBytes;\r
   int FdCount;\r
   nfds_t Index;\r
   socklen_t LengthInBytes;\r
-  struct sockaddr_in RemoteAddress;\r
+  struct sockaddr_in * pPortIpAddress4;\r
+  struct sockaddr_in6 * pPortIpAddress6;\r
+  struct sockaddr_in * pRemoteAddress4;\r
+  struct sockaddr_in6 * pRemoteAddress6;\r
+  struct sockaddr_in6 RemoteAddress;\r
   int Socket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
   int Socket;\r
   EFI_STATUS Status;\r
   EFI_TPL TplPrevious;\r
@@ -282,6 +284,8 @@ SocketPoll (
   //\r
   //  Check for control-C\r
   //\r
   //\r
   //  Check for control-C\r
   //\r
+  pRemoteAddress4 = (struct sockaddr_in *)&RemoteAddress;\r
+  pRemoteAddress6 = (struct sockaddr_in6 *)&RemoteAddress;\r
   bListenError = FALSE;\r
   Status = ControlCCheck ( );\r
   if ( !EFI_ERROR ( Status )) {\r
   bListenError = FALSE;\r
   Status = ControlCCheck ( );\r
   if ( !EFI_ERROR ( Status )) {\r
@@ -311,6 +315,8 @@ SocketPoll (
         //\r
         //  Account for this descriptor\r
         //\r
         //\r
         //  Account for this descriptor\r
         //\r
+        pPortIpAddress4 = (struct sockaddr_in *)&Port[ Index ].IpAddress;\r
+        pPortIpAddress6 = (struct sockaddr_in6 *)&Port[ Index ].IpAddress;\r
         if ( 0 != PollFd[ Index ].revents ) {\r
           FdCount -= 1;\r
         }\r
         if ( 0 != PollFd[ Index ].revents ) {\r
           FdCount -= 1;\r
         }\r
@@ -327,14 +333,38 @@ SocketPoll (
                       errno ));\r
           }\r
           else {\r
                       errno ));\r
           }\r
           else {\r
-            DEBUG (( DEBUG_ERROR,\r
-                      "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",\r
-                      Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                      ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                      ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                      ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                      htons ( Port[ Index ].RemoteAddress.sin_port ),\r
-                      errno ));\r
+            if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+              DEBUG (( DEBUG_ERROR,\r
+                        "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",\r
+                        pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                        ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                        ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                        ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                        htons ( pPortIpAddress4->sin_port ),\r
+                        errno ));\r
+            }\r
+            else {\r
+              DEBUG (( DEBUG_ERROR,\r
+                        "ERROR - Network closed on socket [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                        pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                        htons ( pPortIpAddress6->sin6_port ),\r
+                        errno ));\r
+            }\r
 \r
             //\r
             //  Close the socket\r
 \r
             //\r
             //  Close the socket\r
@@ -342,25 +372,74 @@ SocketPoll (
             CloseStatus = close ( PollFd[ Index ].fd );\r
             if ( 0 == CloseStatus ) {\r
               bRemoveSocket = TRUE;\r
             CloseStatus = close ( PollFd[ Index ].fd );\r
             if ( 0 == CloseStatus ) {\r
               bRemoveSocket = TRUE;\r
-              DEBUG (( DEBUG_INFO,\r
-                        "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",\r
-                        PollFd[ Index ].fd,\r
-                        Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                        htons ( Port[ Index ].RemoteAddress.sin_port )));\r
+              if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+                DEBUG (( DEBUG_INFO,\r
+                          "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",\r
+                          PollFd[ Index ].fd,\r
+                          pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                          htons ( pPortIpAddress4->sin_port )));\r
+              }\r
+              else {\r
+                DEBUG (( DEBUG_INFO,\r
+                          "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                          PollFd[ Index ].fd,\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                          htons ( pPortIpAddress6->sin6_port )));\r
+              }\r
             }\r
             else {\r
             }\r
             else {\r
-              DEBUG (( DEBUG_ERROR,\r
-                        "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",\r
-                        PollFd[ Index ].fd,\r
-                        Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                        htons ( Port[ Index ].RemoteAddress.sin_port ),\r
-                        errno ));\r
+              if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+                DEBUG (( DEBUG_ERROR,\r
+                          "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",\r
+                          PollFd[ Index ].fd,\r
+                          pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                          htons ( pPortIpAddress4->sin_port ),\r
+                          errno ));\r
+              }\r
+              else {\r
+                DEBUG (( DEBUG_ERROR,\r
+                          "ERROR - Failed to close socket 0x%08x for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",\r
+                          PollFd[ Index ].fd,\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                          htons ( pPortIpAddress6->sin6_port ),\r
+                          errno ));\r
+              }\r
             }\r
           }\r
         }\r
             }\r
           }\r
         }\r
@@ -399,12 +478,34 @@ SocketPoll (
                 //\r
                 //  Display the connection\r
                 //\r
                 //\r
                 //  Display the connection\r
                 //\r
-                Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",\r
-                        RemoteAddress.sin_addr.s_addr & 0xff,\r
-                        ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                        ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                        ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                        htons ( RemoteAddress.sin_port ));\r
+                if ( AF_INET == pRemoteAddress4->sin_family ) {\r
+                  Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",\r
+                          pRemoteAddress4->sin_addr.s_addr & 0xff,\r
+                          ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                          ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                          ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                          htons ( pRemoteAddress4->sin_port ));\r
+                }\r
+                else {\r
+                  Print ( L"Rejecting connection to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                          htons ( pRemoteAddress6->sin6_port ));\r
+                }\r
 \r
                 //\r
                 //  No room for this connection\r
 \r
                 //\r
                 //  No room for this connection\r
@@ -413,14 +514,38 @@ SocketPoll (
                 CloseStatus = close ( Socket );\r
                 if ( 0 == CloseStatus ) {\r
                   bRemoveSocket = TRUE;\r
                 CloseStatus = close ( Socket );\r
                 if ( 0 == CloseStatus ) {\r
                   bRemoveSocket = TRUE;\r
-                  DEBUG (( DEBUG_INFO,\r
-                            "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",\r
-                            PollFd[ Index ].fd,\r
-                            RemoteAddress.sin_addr.s_addr & 0xff,\r
-                            ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                            ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                            ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                            htons ( RemoteAddress.sin_port )));\r
+                  if ( AF_INET == pRemoteAddress4->sin_family ) {\r
+                    DEBUG (( DEBUG_INFO,\r
+                              "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",\r
+                              PollFd[ Index ].fd,\r
+                              pRemoteAddress4->sin_addr.s_addr & 0xff,\r
+                              ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                              ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                              ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                              htons ( pRemoteAddress4->sin_port )));\r
+                  }\r
+                  else {\r
+                    DEBUG (( DEBUG_INFO,\r
+                              "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                              PollFd[ Index ].fd,\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                              pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                              htons ( pRemoteAddress6->sin6_port )));\r
+                  }\r
                 }\r
                 else {\r
                   DEBUG (( DEBUG_ERROR,\r
                 }\r
                 else {\r
                   DEBUG (( DEBUG_ERROR,\r
@@ -439,25 +564,41 @@ SocketPoll (
                 //\r
                 //  Display the connection\r
                 //\r
                 //\r
                 //  Display the connection\r
                 //\r
-                Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
-                        RemoteAddress.sin_addr.s_addr & 0xff,\r
-                        ( RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                        ( RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                        ( RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                        htons ( RemoteAddress.sin_port ));\r
+                if ( AF_INET == pRemoteAddress4->sin_family ) {\r
+                  Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
+                          pRemoteAddress4->sin_addr.s_addr & 0xff,\r
+                          ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                          ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                          ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                          htons ( pRemoteAddress4->sin_port ));\r
+                }\r
+                else {\r
+                  Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                          pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                          htons ( pRemoteAddress6->sin6_port ));\r
+                }\r
 \r
                 //\r
                 //  Allocate the client connection\r
                 //\r
                 Index = MaxPort++;\r
 \r
                 //\r
                 //  Allocate the client connection\r
                 //\r
                 Index = MaxPort++;\r
-                Port[ Index ].BytesAverage = 0;\r
-                Port[ Index ].BytesPrevious = 0;\r
-                Port[ Index ].BytesTotal = 0;\r
-                Port[ Index ].Samples = 0;\r
-                Port[ Index ].RemoteAddress.sin_len = RemoteAddress.sin_len;\r
-                Port[ Index ].RemoteAddress.sin_family = RemoteAddress.sin_family;\r
-                Port[ Index ].RemoteAddress.sin_port = RemoteAddress.sin_port;\r
-                Port[ Index ].RemoteAddress.sin_addr = RemoteAddress.sin_addr;\r
+                ZeroMem ( &Port[ Index ], sizeof ( Port[ Index ]));\r
+                CopyMem ( pPortIpAddress6, pRemoteAddress6, sizeof ( *pRemoteAddress6 ));\r
                 PollFd[ Index ].fd = Socket;\r
                 PollFd[ Index ].events = POLLRDNORM | POLLHUP;\r
                 PollFd[ Index ].revents = 0;\r
                 PollFd[ Index ].fd = Socket;\r
                 PollFd[ Index ].events = POLLRDNORM | POLLHUP;\r
                 PollFd[ Index ].revents = 0;\r
@@ -475,15 +616,40 @@ SocketPoll (
               //\r
               //  Display the amount of data received\r
               //\r
               //\r
               //  Display the amount of data received\r
               //\r
-              DEBUG (( DEBUG_INFO,\r
-                        "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",\r
-                        PollFd[ Index ].fd,\r
-                        BytesReceived,\r
-                        Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                        htons ( Port[ Index ].RemoteAddress.sin_port )));\r
+              if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+                DEBUG (( DEBUG_INFO,\r
+                          "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",\r
+                          PollFd[ Index ].fd,\r
+                          BytesReceived,\r
+                          pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                          htons ( pPortIpAddress4->sin_port )));\r
+              }\r
+              else {\r
+                DEBUG (( DEBUG_INFO,\r
+                          "0x%08x: Socket received 0x%08x bytes from [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                          PollFd[ Index ].fd,\r
+                          BytesReceived,\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                          htons ( pPortIpAddress6->sin6_port )));\r
+              }\r
 \r
               //\r
               //  Synchronize with the TimerCallback routine\r
 \r
               //\r
               //  Synchronize with the TimerCallback routine\r
@@ -504,36 +670,109 @@ SocketPoll (
               //\r
               //  Close the socket\r
               //\r
               //\r
               //  Close the socket\r
               //\r
-              DEBUG (( DEBUG_INFO,\r
-                        "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",\r
-                        Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                        ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                        htons ( Port[ Index ].RemoteAddress.sin_port ),\r
-                        errno ));\r
+              if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+                DEBUG (( DEBUG_INFO,\r
+                          "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",\r
+                          pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                          ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                          htons ( pPortIpAddress4->sin_port ),\r
+                          errno ));\r
+              }\r
+              else {\r
+                DEBUG (( DEBUG_INFO,\r
+                          "ERROR - Receive failure for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                          pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                          htons ( pPortIpAddress6->sin6_port ),\r
+                          errno ));\r
+              }\r
               CloseStatus = close ( PollFd[ Index ].fd );\r
               if ( 0 == CloseStatus ) {\r
                 bRemoveSocket = TRUE;\r
               CloseStatus = close ( PollFd[ Index ].fd );\r
               if ( 0 == CloseStatus ) {\r
                 bRemoveSocket = TRUE;\r
-                DEBUG (( DEBUG_INFO,\r
-                          "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",\r
-                          PollFd[ Index ].fd,\r
-                          Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                          ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                          ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                          ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                          htons ( Port[ Index ].RemoteAddress.sin_port )));\r
+                if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+                  DEBUG (( DEBUG_INFO,\r
+                            "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",\r
+                            PollFd[ Index ].fd,\r
+                            pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                            ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                            ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                            ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                            htons ( pPortIpAddress4->sin_port )));\r
+                }\r
+                else {\r
+                  DEBUG (( DEBUG_INFO,\r
+                            "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                            PollFd[ Index ].fd,\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                            htons ( pPortIpAddress6->sin6_port )));\r
+                }\r
               }\r
               else {\r
               }\r
               else {\r
-                DEBUG (( DEBUG_ERROR,\r
-                          "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",\r
-                          PollFd[ Index ].fd,\r
-                          Port[ Index ].RemoteAddress.sin_addr.s_addr & 0xff,\r
-                          ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                          ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                          ( Port[ Index ].RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                          htons ( Port[ Index ].RemoteAddress.sin_port ),\r
-                          errno ));\r
+                if ( AF_INET == pPortIpAddress4->sin_family ) {\r
+                  DEBUG (( DEBUG_ERROR,\r
+                            "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",\r
+                            PollFd[ Index ].fd,\r
+                            pPortIpAddress4->sin_addr.s_addr & 0xff,\r
+                            ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                            ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                            ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                            htons ( pPortIpAddress4->sin_port ),\r
+                            errno ));\r
+                }\r
+                else {\r
+                  DEBUG (( DEBUG_ERROR,\r
+                            "ERROR - Failed to close socket 0x%08x for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",\r
+                            PollFd[ Index ].fd,\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                            pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                            htons ( pPortIpAddress6->sin6_port ),\r
+                            errno ));\r
+                }\r
               }\r
             }\r
 \r
               }\r
             }\r
 \r
@@ -555,14 +794,9 @@ SocketPoll (
           MaxPort -= 1;\r
           for ( Entry = Index + 1; MaxPort >= Entry; Entry++ ) {\r
             EntryPrevious = Entry;\r
           MaxPort -= 1;\r
           for ( Entry = Index + 1; MaxPort >= Entry; Entry++ ) {\r
             EntryPrevious = Entry;\r
-            Port[ EntryPrevious ].BytesAverage = Port[ Entry ].BytesAverage;\r
-            Port[ EntryPrevious ].BytesPrevious = Port[ Entry ].BytesPrevious;\r
-            Port[ EntryPrevious ].BytesTotal = Port[ Entry ].BytesTotal;\r
-            Port[ EntryPrevious ].RemoteAddress.sin_len = Port[ Entry ].RemoteAddress.sin_len;\r
-            Port[ EntryPrevious ].RemoteAddress.sin_family = Port[ Entry ].RemoteAddress.sin_family;\r
-            Port[ EntryPrevious ].RemoteAddress.sin_port = Port[ Entry ].RemoteAddress.sin_port;\r
-            Port[ EntryPrevious ].RemoteAddress.sin_addr.s_addr = Port[ Entry ].RemoteAddress.sin_addr.s_addr;\r
-            Port[ EntryPrevious ].Samples = Port[ Entry ].Samples;\r
+            CopyMem ( &Port[ EntryPrevious ],\r
+                      &Port[ Entry ],\r
+                      sizeof ( Port[ Entry ]));\r
             PollFd[ EntryPrevious ].events = PollFd[ Entry ].events;\r
             PollFd[ EntryPrevious ].fd = PollFd[ Entry ].fd;\r
             PollFd[ EntryPrevious ].revents = PollFd[ Entry ].revents;\r
             PollFd[ EntryPrevious ].events = PollFd[ Entry ].events;\r
             PollFd[ EntryPrevious ].fd = PollFd[ Entry ].fd;\r
             PollFd[ EntryPrevious ].revents = PollFd[ Entry ].revents;\r
@@ -605,11 +839,12 @@ TimerCallback (
   IN VOID * pContext\r
   )\r
 {\r
   IN VOID * pContext\r
   )\r
 {\r
-  UINT64 Average;\r
+  UINT32 Average;\r
+  UINT64 BitsPerSecond;\r
   UINT64 BytesReceived;\r
   UINT64 BytesReceived;\r
-  UINT32 Delta;\r
-  UINT64 DeltaBytes;\r
+  UINT32 Count;\r
   nfds_t Index;\r
   nfds_t Index;\r
+  UINT64 TotalBytes;\r
 \r
   //\r
   //  Notify the other code of the timer tick\r
 \r
   //\r
   //  Notify the other code of the timer tick\r
@@ -627,65 +862,84 @@ TimerCallback (
     if (( ListenSocket != PollFd[ Index ].fd )\r
       && ( 0 != BytesReceived )) {\r
       //\r
     if (( ListenSocket != PollFd[ Index ].fd )\r
       && ( 0 != BytesReceived )) {\r
       //\r
-      //  Update the average bytes per second\r
+      //  Update the received data samples\r
       //\r
       //\r
-      DeltaBytes = Port[ Index ].BytesAverage >> AVERAGE_SHIFT_COUNT;\r
-      Port[ Index ].BytesAverage -= DeltaBytes;\r
-      DeltaBytes = BytesReceived - Port[ Index ].BytesPrevious;\r
-      Port[ Index ].BytesPrevious = BytesReceived;\r
-      Port[ Index ].BytesAverage += DeltaBytes;\r
-\r
+      Port[ Index ].BytesTotal = 0;\r
+      Port[ Index ].BytesReceived [ Port[ Index ].In ] = BytesReceived;\r
+      Port[ Index ].In += 1;\r
+      if ( DATA_SAMPLES <= Port[ Index ].In ) {\r
+        Port[ Index ].In = 0;\r
+      }\r
+      \r
       //\r
       //  Separate the samples\r
       //\r
       //\r
       //  Separate the samples\r
       //\r
-      if (( 2 << AVERAGE_SHIFT_COUNT ) == Port[ Index ].Samples ) {\r
+      if ( DATA_SAMPLES == Port[ Index ].Samples ) {\r
         Print ( L"---------- Stable average ----------\r\n" );\r
       }\r
       Port[ Index ].Samples += 1;\r
 \r
         Print ( L"---------- Stable average ----------\r\n" );\r
       }\r
       Port[ Index ].Samples += 1;\r
 \r
+      //\r
+      //  Compute the data rate\r
+      //\r
+      TotalBytes = 0;\r
+      for ( Count = 0; DATA_SAMPLES > Count; Count++ )\r
+      {\r
+          TotalBytes += Port[ Index ].BytesReceived[ Count ];\r
+      }\r
+      Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );\r
+      BitsPerSecond = Average * 8;\r
+\r
       //\r
       //  Display the data rate\r
       //\r
       //\r
       //  Display the data rate\r
       //\r
-      Delta = (UINT32)( DeltaBytes >> DATA_RATE_UPDATE_SHIFT );\r
-      Average = Port[ Index ].BytesAverage >> ( AVERAGE_SHIFT_COUNT + DATA_RATE_UPDATE_SHIFT );\r
-      if ( Average < RANGE_SWITCH ) {\r
-        Print ( L"%d Bytes/sec, Ave: %d Bytes/Sec\r\n",\r
-                Delta,\r
-                (UINT32) Average );\r
+      if (( RANGE_SWITCH >> 10 ) > Average ) {\r
+        Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",\r
+                Average,\r
+                BitsPerSecond );\r
       }\r
       else {\r
       }\r
       else {\r
-        Average >>= 10;\r
-        if ( Average < RANGE_SWITCH ) {\r
-          Print ( L"%d Bytes/sec, Ave: %d KiBytes/Sec\r\n",\r
-                  Delta,\r
-                  (UINT32) Average );\r
+        BitsPerSecond /= 1000;\r
+        if ( RANGE_SWITCH > Average ) {\r
+          Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",\r
+                  Average >> 10,\r
+                  (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                  BitsPerSecond );\r
         }\r
         else {\r
         }\r
         else {\r
+          BitsPerSecond /= 1000;\r
           Average >>= 10;\r
           Average >>= 10;\r
-          if ( Average < RANGE_SWITCH ) {\r
-            Print ( L"%d Bytes/sec, Ave: %d MiBytes/Sec\r\n",\r
-                    Delta,\r
-                    (UINT32) Average );\r
+          if ( RANGE_SWITCH > Average ) {\r
+            Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",\r
+                    Average >> 10,\r
+                    (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                    BitsPerSecond );\r
           }\r
           else {\r
           }\r
           else {\r
+            BitsPerSecond /= 1000;\r
             Average >>= 10;\r
             Average >>= 10;\r
-            if ( Average < RANGE_SWITCH ) {\r
-              Print ( L"%d Bytes/sec, Ave: %d GiBytes/Sec\r\n",\r
-                      Delta,\r
-                      (UINT32) Average );\r
+            if ( RANGE_SWITCH > Average ) {\r
+              Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",\r
+                      Average >> 10,\r
+                      (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                      BitsPerSecond );\r
             }\r
             else {\r
             }\r
             else {\r
+              BitsPerSecond /= 1000;\r
               Average >>= 10;\r
               Average >>= 10;\r
-              if ( Average < RANGE_SWITCH ) {\r
-                Print ( L"%d Bytes/sec, Ave: %d TiBytes/Sec\r\n",\r
-                        Delta,\r
-                        Average );\r
+              if ( RANGE_SWITCH > Average ) {\r
+                Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",\r
+                        Average >> 10,\r
+                        (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                        BitsPerSecond );\r
               }\r
               else {\r
               }\r
               else {\r
+                BitsPerSecond /= 1000;\r
                 Average >>= 10;\r
                 Average >>= 10;\r
-                Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",\r
-                        Delta,\r
-                        (UINT32) Average );\r
+                Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",\r
+                        Average >> 10,\r
+                        (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                        BitsPerSecond );\r
               }\r
             }\r
           }\r
               }\r
             }\r
           }\r
@@ -909,11 +1163,17 @@ main (
   IN char **Argv\r
   )\r
 {\r
   IN char **Argv\r
   )\r
 {\r
+  sa_family_t Family;\r
   EFI_STATUS Status;\r
 \r
   DEBUG (( DEBUG_INFO,\r
             "DataSink starting\r\n" ));\r
 \r
   EFI_STATUS Status;\r
 \r
   DEBUG (( DEBUG_INFO,\r
             "DataSink starting\r\n" ));\r
 \r
+  //\r
+  //  Determine the family to use\r
+  //\r
+  Family = ( 1 < Argc ) ? AF_INET6 : AF_INET;\r
+\r
   //\r
   //  Use for/break instead of goto\r
   //\r
   //\r
   //  Use for/break instead of goto\r
   //\r
@@ -966,7 +1226,7 @@ main (
       //\r
       //  Wait for the network layer to initialize\r
       //\r
       //\r
       //  Wait for the network layer to initialize\r
       //\r
-      Status = SocketNew ( );\r
+      Status = SocketNew ( Family );\r
       if ( EFI_ERROR ( Status )) {\r
         continue;\r
       }\r
       if ( EFI_ERROR ( Status )) {\r
         continue;\r
       }\r
@@ -987,7 +1247,7 @@ main (
       }\r
 \r
       //\r
       }\r
 \r
       //\r
-      //  Send data until the connection breaks\r
+      //  Receive data until the connection breaks\r
       //\r
       do {\r
         Status = SocketPoll ( );\r
       //\r
       do {\r
         Status = SocketPoll ( );\r
index 7c79ab28f8789dd1318d8984e34bf5f559c7efce..43a8e962f3460ad784d2cce210e5c53272cfa47b 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 \r
 \r
 [Pcd]\r
 \r
 \r
 [Pcd]\r
-  gStdLibTokenSpaceGuid.DataSource_Port\r
+  gAppPkgTokenSpaceGuid.DataSource_Port\r
 \r
 \r
 [Packages]\r
 \r
 \r
 [Packages]\r
+  AppPkg/AppPkg.dec\r
   MdePkg/MdePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   StdLib/StdLib.dec\r
   MdePkg/MdePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   StdLib/StdLib.dec\r
index 98a0c9f1209db132fa5d40b47ce5e139f746ccdc..31c38950a640ce3dd042be8a538fc7f9abd59577 100644 (file)
 #include <sys/poll.h>\r
 #include <sys/socket.h>\r
 \r
 #include <sys/poll.h>\r
 #include <sys/socket.h>\r
 \r
+#include <stdio.h>\r
 \r
 \r
-#define RANGE_SWITCH                2048  ///<  Switch display ranges\r
-#define DATA_RATE_UPDATE_SHIFT      2     ///<  2n seconds between updates\r
+\r
+#define DATA_SAMPLE_SHIFT           5       ///<  Shift for number of samples\r
+#define RANGE_SWITCH        ( 1024 * 1024 ) ///<  Switch display ranges\r
+#define DATA_RATE_UPDATE_SHIFT      2       ///<  2n seconds between updates\r
 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average\r
 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average\r
+#define DATA_SAMPLES        ( 1 << DATA_SAMPLE_SHIFT )      ///<  Number of samples\r
 \r
 #define TPL_DATASOURCE      TPL_CALLBACK  ///<  Synchronization TPL\r
 \r
 \r
 #define TPL_DATASOURCE      TPL_CALLBACK  ///<  Synchronization TPL\r
 \r
@@ -74,16 +78,16 @@ EFI_EVENT pTimer;
 //\r
 //  Remote IP Address Data\r
 //\r
 //\r
 //  Remote IP Address Data\r
 //\r
-struct sockaddr_in RemoteHostAddress;\r
+struct sockaddr_in6 RemoteHostAddress;\r
 CHAR8 * pRemoteHost;\r
 \r
 //\r
 //  Traffic Data\r
 //\r
 UINT64 TotalBytesSent;\r
 CHAR8 * pRemoteHost;\r
 \r
 //\r
 //  Traffic Data\r
 //\r
 UINT64 TotalBytesSent;\r
-UINT64 PreviousBytes;\r
-UINT64 AverageBytes;\r
-UINT64 Samples;\r
+UINT32 In;\r
+UINT32 Samples;\r
+UINT64 BytesSent[ DATA_SAMPLES ];\r
 UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
 \r
 \r
 UINT8 Buffer[ DATA_BUFFER_SIZE ];\r
 \r
 \r
@@ -185,48 +189,124 @@ EFI_STATUS
 IpAddress (\r
   )\r
 {\r
 IpAddress (\r
   )\r
 {\r
-  CHAR8 * pSeparator;\r
-  INT32 RemoteAddress;\r
+  struct sockaddr_in * pRemoteAddress4;\r
+  struct sockaddr_in6 * pRemoteAddress6;\r
+  UINT32 RemoteAddress;\r
   EFI_STATUS Status;\r
   UINT32 Value1;\r
   UINT32 Value2;\r
   UINT32 Value3;\r
   UINT32 Value4;\r
   EFI_STATUS Status;\r
   UINT32 Value1;\r
   UINT32 Value2;\r
   UINT32 Value3;\r
   UINT32 Value4;\r
+  UINT32 Value5;\r
+  UINT32 Value6;\r
+  UINT32 Value7;\r
+  UINT32 Value8;\r
 \r
   //\r
   //  Assume failure\r
   //\r
   Status = EFI_INVALID_PARAMETER;\r
 \r
 \r
   //\r
   //  Assume failure\r
   //\r
   Status = EFI_INVALID_PARAMETER;\r
 \r
+  //\r
+  //  Get the port number\r
+  //\r
+  ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));\r
+  RemoteHostAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));\r
+  pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
+  pRemoteAddress6 = &RemoteHostAddress;\r
+  \r
   //\r
   //  Convert the IP address from a string to a numeric value\r
   //\r
   //\r
   //  Convert the IP address from a string to a numeric value\r
   //\r
-  pSeparator = GetDigit ( pRemoteHost, &Value1 );\r
-  if (( 255 >= Value1 ) && ( '.' == *pSeparator )) {\r
-    pSeparator = GetDigit ( ++pSeparator, &Value2 );\r
-    if (( 255 >= Value2 ) && ( '.' == *pSeparator )) {\r
-      pSeparator = GetDigit ( ++pSeparator, &Value3 );\r
-      if (( 255 >= Value3 ) && ( '.' == *pSeparator )) {\r
-        pSeparator = GetDigit ( ++pSeparator, &Value4 );\r
-        if (( 255 >= Value4 ) && ( 0 == *pSeparator )) {\r
-          RemoteAddress = Value1\r
-                        | ( Value2 << 8 )\r
-                        | ( Value3 << 16 )\r
-                        | ( Value4 << 24 );\r
-          RemoteHostAddress.sin_addr.s_addr = (UINT32) RemoteAddress;\r
-          Status = EFI_SUCCESS;\r
-          DEBUG (( DEBUG_INFO,\r
-                    "%d.%d.%d.%d: Remote host IP address\r\n",\r
-                    Value1,\r
-                    Value2,\r
-                    Value3,\r
-                    Value4 ));\r
-        }\r
-      }\r
-    }\r
+  if (( 4 == sscanf ( pRemoteHost,\r
+                      "%d.%d.%d.%d",\r
+                      &Value1,\r
+                      &Value2,\r
+                      &Value3,\r
+                      &Value4 ))\r
+      && ( 255 >= Value1 )\r
+      && ( 255 >= Value2 )\r
+      && ( 255 >= Value3 )\r
+      && ( 255 >= Value4 )) {\r
+    //\r
+    //  Build the IPv4 address\r
+    //\r
+    pRemoteAddress4->sin_len = sizeof ( *pRemoteAddress4 );\r
+    pRemoteAddress4->sin_family = AF_INET;\r
+    RemoteAddress = Value1\r
+                  | ( Value2 << 8 )\r
+                  | ( Value3 << 16 )\r
+                  | ( Value4 << 24 );\r
+    pRemoteAddress4->sin_addr.s_addr = RemoteAddress;\r
+    Status = EFI_SUCCESS;\r
+\r
+    //\r
+    //  Display the IP address\r
+    //\r
+    DEBUG (( DEBUG_INFO,\r
+              "%d.%d.%d.%d: Remote host IP address\r\n",\r
+              Value1,\r
+              Value2,\r
+              Value3,\r
+              Value4 ));\r
   }\r
   }\r
-  if ( EFI_ERROR ( Status )) {\r
-    Print ( L"Invalid digit detected: %d\r\n", *pSeparator );\r
+  else if (( 8 == sscanf ( pRemoteHost,\r
+                           "%x:%x:%x:%x:%x:%x:%x:%x",\r
+                           &Value1,\r
+                           &Value2,\r
+                           &Value3,\r
+                           &Value4,\r
+                           &Value5,\r
+                           &Value6,\r
+                           &Value7,\r
+                           &Value8 ))\r
+            && ( 0xffff >= Value1 )\r
+            && ( 0xffff >= Value2 )\r
+            && ( 0xffff >= Value3 )\r
+            && ( 0xffff >= Value4 )\r
+            && ( 0xffff >= Value5 )\r
+            && ( 0xffff >= Value6 )\r
+            && ( 0xffff >= Value7 )\r
+            && ( 0xffff >= Value8 )) {\r
+    //\r
+    //  Build the IPv6 address\r
+    //\r
+    pRemoteAddress6->sin6_len = sizeof ( *pRemoteAddress6 );\r
+    pRemoteAddress6->sin6_family = AF_INET6;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ] = (UINT8)( Value1 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ] = (UINT8)Value1;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ] = (UINT8)( Value2 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ] = (UINT8)Value2;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ] = (UINT8)( Value3 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ] = (UINT8)Value3;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ] = (UINT8)( Value4 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ] = (UINT8)Value4;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ] = (UINT8)( Value5 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ] = (UINT8)Value5;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ] = (UINT8)( Value6 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ] = (UINT8)Value6;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ] = (UINT8)( Value7 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ] = (UINT8)Value7;\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ] = (UINT8)( Value8 >> 8 );\r
+    pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ] = (UINT8)Value8;\r
+    Status = EFI_SUCCESS;\r
+\r
+    //\r
+    //  Display the IP address\r
+    //\r
+    DEBUG (( DEBUG_INFO,\r
+              "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",\r
+              Value1,\r
+              Value2,\r
+              Value3,\r
+              Value4,\r
+              Value5,\r
+              Value6,\r
+              Value7,\r
+              Value8 ));\r
+  }\r
+  else {\r
+    Print ( L"ERROR - Invalid IP address!\r\n" );\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -290,19 +370,43 @@ SocketConnect (
   )\r
 {\r
   int ConnectStatus;\r
   )\r
 {\r
   int ConnectStatus;\r
-  UINT32 RemoteAddress;\r
+  struct sockaddr_in * pRemoteAddress4;\r
+  struct sockaddr_in6 * pRemoteAddress6;\r
   EFI_STATUS Status;\r
 \r
   //\r
   //  Display the connecting message\r
   //\r
   EFI_STATUS Status;\r
 \r
   //\r
   //  Display the connecting message\r
   //\r
-  RemoteAddress = RemoteHostAddress.sin_addr.s_addr;\r
-  Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",\r
-          RemoteAddress & 0xff,\r
-          ( RemoteAddress >> 8 ) & 0xff,\r
-          ( RemoteAddress >> 16 ) & 0xff,\r
-          ( RemoteAddress >> 24 ) & 0xff,\r
-          htons ( RemoteHostAddress.sin_port ));\r
+  pRemoteAddress4 = (struct sockaddr_in *)&RemoteHostAddress;\r
+  pRemoteAddress6 = &RemoteHostAddress;\r
+  if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
+    Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",\r
+            pRemoteAddress4->sin_addr.s_addr & 0xff,\r
+            ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+            ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+            ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+            htons ( pRemoteAddress4->sin_port ));\r
+  }\r
+  else {\r
+    Print ( L"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+            pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+            htons ( pRemoteAddress6->sin6_port ));\r
+  }\r
 \r
   //\r
   //  Connect to the remote system\r
 \r
   //\r
   //  Connect to the remote system\r
@@ -327,15 +431,37 @@ SocketConnect (
     //  Connect to the remote system\r
     //\r
     ConnectStatus = connect ( Socket,\r
     //  Connect to the remote system\r
     //\r
     ConnectStatus = connect ( Socket,\r
-                              (struct sockaddr *) &RemoteHostAddress,\r
-                              RemoteHostAddress.sin_len );\r
+                              (struct sockaddr *)pRemoteAddress6,\r
+                              pRemoteAddress6->sin6_len );\r
     if ( -1 != ConnectStatus ) {\r
     if ( -1 != ConnectStatus ) {\r
-      Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
-              RemoteAddress & 0xff,\r
-              ( RemoteAddress >> 8 ) & 0xff,\r
-              ( RemoteAddress >> 16 ) & 0xff,\r
-              ( RemoteAddress >> 24 ) & 0xff,\r
-              htons ( RemoteHostAddress.sin_port ));\r
+      if ( AF_INET == pRemoteAddress6->sin6_family ) {\r
+        Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",\r
+                pRemoteAddress4->sin_addr.s_addr & 0xff,\r
+                ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,\r
+                ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,\r
+                ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,\r
+                htons ( pRemoteAddress4->sin_port ));\r
+      }\r
+      else {\r
+        Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                htons ( pRemoteAddress6->sin6_port ));\r
+      }\r
     }\r
     else {\r
       //\r
     }\r
     else {\r
       //\r
@@ -358,11 +484,14 @@ SocketConnect (
 /**\r
   Create the socket\r
 \r
 /**\r
   Create the socket\r
 \r
+  @param [in] Family    Network family, AF_INET or AF_INET6\r
+\r
   @retval  EFI_SUCCESS  The application is running normally\r
   @retval  Other        The user stopped the application\r
 **/\r
 EFI_STATUS\r
 SocketNew (\r
   @retval  EFI_SUCCESS  The application is running normally\r
   @retval  Other        The user stopped the application\r
 **/\r
 EFI_STATUS\r
 SocketNew (\r
+  sa_family_t Family\r
   )\r
 {\r
   EFI_STATUS Status;\r
   )\r
 {\r
   EFI_STATUS Status;\r
@@ -384,7 +513,7 @@ SocketNew (
     //\r
     //  Attempt to create the socket\r
     //\r
     //\r
     //  Attempt to create the socket\r
     //\r
-    Socket = socket ( AF_INET,\r
+    Socket = socket ( Family,\r
                       SOCK_STREAM,\r
                       IPPROTO_TCP );\r
     if ( -1 != Socket ) {\r
                       SOCK_STREAM,\r
                       IPPROTO_TCP );\r
     if ( -1 != Socket ) {\r
@@ -419,7 +548,7 @@ SocketSend (
   //\r
   //  Restart the timer\r
   //\r
   //\r
   //  Restart the timer\r
   //\r
-  TimerStart ( 1000 << DATA_RATE_UPDATE_SHIFT );\r
+  TimerStart ( 1 * 1000 );\r
 \r
   //\r
   //  Loop until the connection breaks or the user stops\r
 \r
   //\r
   //  Loop until the connection breaks or the user stops\r
@@ -497,7 +626,7 @@ SocketOpen (
     //\r
     //  Wait for the network layer to initialize\r
     //\r
     //\r
     //  Wait for the network layer to initialize\r
     //\r
-    Status = SocketNew ( );\r
+    Status = SocketNew ( RemoteHostAddress.sin6_family );\r
     if ( EFI_ERROR ( Status )) {\r
       break;\r
     }\r
     if ( EFI_ERROR ( Status )) {\r
       break;\r
     }\r
@@ -584,13 +713,13 @@ Tcp4Close (
           //\r
           //  Display the port closed message\r
           //\r
           //\r
           //  Display the port closed message\r
           //\r
-          pIpAddress = (UINT8 *)&RemoteHostAddress.sin_addr.s_addr;\r
+          pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
           Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",\r
                   pIpAddress[0],\r
                   pIpAddress[1],\r
                   pIpAddress[2],\r
                   pIpAddress[3],\r
           Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",\r
                   pIpAddress[0],\r
                   pIpAddress[1],\r
                   pIpAddress[2],\r
                   pIpAddress[3],\r
-                  htons ( RemoteHostAddress.sin_port ));\r
+                  htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
         }\r
       }\r
     }\r
         }\r
       }\r
     }\r
@@ -786,13 +915,13 @@ Tcp4Locate (
     //  Display the connecting message\r
     //\r
     if ( bTcp4Connecting ) {\r
     //  Display the connecting message\r
     //\r
     if ( bTcp4Connecting ) {\r
-      pIpAddress = (UINT8 *)&RemoteHostAddress.sin_addr.s_addr;\r
+      pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
       Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",\r
               pIpAddress[0],\r
               pIpAddress[1],\r
               pIpAddress[2],\r
               pIpAddress[3],\r
       Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",\r
               pIpAddress[0],\r
               pIpAddress[1],\r
               pIpAddress[2],\r
               pIpAddress[3],\r
-              htons ( RemoteHostAddress.sin_port ));\r
+              htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
       bTcp4Connecting = FALSE;\r
     }\r
 \r
       bTcp4Connecting = FALSE;\r
     }\r
 \r
@@ -885,7 +1014,7 @@ Tcp4Send (
   //\r
   //  Restart the timer\r
   //\r
   //\r
   //  Restart the timer\r
   //\r
-  TimerStart ( 1000 << DATA_RATE_UPDATE_SHIFT );\r
+  TimerStart ( 1 * 1000 );\r
 \r
   //\r
   //  Initialize the packet\r
 \r
   //\r
   //  Initialize the packet\r
@@ -1095,11 +1224,11 @@ Tcp4Open (
     Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;\r
     Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;\r
     Tcp4ConfigData.AccessPoint.StationPort = 0;\r
     Tcp4ConfigData.AccessPoint.StationAddress.Addr[2] = 0;\r
     Tcp4ConfigData.AccessPoint.StationAddress.Addr[3] = 0;\r
     Tcp4ConfigData.AccessPoint.StationPort = 0;\r
-    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)  RemoteHostAddress.sin_addr.s_addr;\r
-    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 8 );\r
-    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 16 );\r
-    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 24 );\r
-    Tcp4ConfigData.AccessPoint.RemotePort = RemoteHostAddress.sin_port;\r
+    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)  ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
+    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 8 );\r
+    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 16 );\r
+    Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( ((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr >> 24 );\r
+    Tcp4ConfigData.AccessPoint.RemotePort = ((struct sockaddr_in *)&RemoteHostAddress)->sin_port;\r
     Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;\r
     Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
     Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
     Tcp4ConfigData.AccessPoint.UseDefaultAddress = TRUE;\r
     Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
     Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
@@ -1152,13 +1281,13 @@ Tcp4Open (
     //\r
     //  Display the connection\r
     //\r
     //\r
     //  Display the connection\r
     //\r
-    pIpAddress = (UINT8 *)&RemoteHostAddress.sin_addr.s_addr;\r
+    pIpAddress = (UINT8 *)&((struct sockaddr_in *)&RemoteHostAddress)->sin_addr.s_addr;\r
     Print ( L"Connected to %d.%d.%d.%d:%d\r\n",\r
             pIpAddress[0],\r
             pIpAddress[1],\r
             pIpAddress[2],\r
             pIpAddress[3],\r
     Print ( L"Connected to %d.%d.%d.%d:%d\r\n",\r
             pIpAddress[0],\r
             pIpAddress[1],\r
             pIpAddress[2],\r
             pIpAddress[3],\r
-            htons ( RemoteHostAddress.sin_port ));\r
+            htons ( ((struct sockaddr_in *)&RemoteHostAddress)->sin_port ));\r
   } while ( 0 );\r
 \r
   if ( EFI_ERROR ( Status )) {\r
   } while ( 0 );\r
 \r
   if ( EFI_ERROR ( Status )) {\r
@@ -1193,10 +1322,10 @@ TimerCallback (
   IN VOID * pContext\r
   )\r
 {\r
   IN VOID * pContext\r
   )\r
 {\r
-  UINT64 BytesSent;\r
-  UINT64 DeltaBytes;\r
-  UINT32 Delta;\r
-  UINT64 Average;\r
+  UINT32 Average;\r
+  UINT64 BitsPerSecond;\r
+  UINT32 Index;\r
+  UINT64 TotalBytes;\r
 \r
   //\r
   //  Notify the other code of the timer tick\r
 \r
   //\r
   //  Notify the other code of the timer tick\r
@@ -1206,65 +1335,82 @@ TimerCallback (
   //\r
   //  Update the average bytes per second\r
   //\r
   //\r
   //  Update the average bytes per second\r
   //\r
-  BytesSent = TotalBytesSent;\r
-  if ( 0 != BytesSent ) {\r
-    DeltaBytes = AverageBytes >> AVERAGE_SHIFT_COUNT;\r
-    AverageBytes -= DeltaBytes;\r
-    DeltaBytes = BytesSent - PreviousBytes;\r
-    PreviousBytes = BytesSent;\r
-    AverageBytes += DeltaBytes;\r
+  if ( 0 != TotalBytesSent ) {\r
+    BytesSent[ In ] = TotalBytesSent;\r
+    TotalBytesSent = 0;\r
+    In += 1;\r
+    if ( DATA_SAMPLES <= In ) {\r
+      In = 0;\r
+    }\r
 \r
     //\r
     //  Separate the samples\r
     //\r
 \r
     //\r
     //  Separate the samples\r
     //\r
-    if (( 2 << AVERAGE_SHIFT_COUNT ) == Samples ) {\r
+    if ( DATA_SAMPLES == Samples ) {\r
       Print ( L"---------- Stable average ----------\r\n" );\r
     }\r
     Samples += 1;\r
 \r
       Print ( L"---------- Stable average ----------\r\n" );\r
     }\r
     Samples += 1;\r
 \r
+    //\r
+    //  Compute the data rate\r
+    //\r
+    TotalBytes = 0;\r
+    for ( Index = 0; DATA_SAMPLES > Index; Index++ ) {\r
+      TotalBytes += BytesSent[ Index ];\r
+    }\r
+    Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );\r
+    BitsPerSecond = Average * 8;\r
+\r
     //\r
     //  Display the data rate\r
     //\r
     //\r
     //  Display the data rate\r
     //\r
-    Delta = (UINT32)( DeltaBytes >> DATA_RATE_UPDATE_SHIFT );\r
-    Average = AverageBytes >> ( AVERAGE_SHIFT_COUNT + DATA_RATE_UPDATE_SHIFT );\r
-    if ( Average < RANGE_SWITCH ) {\r
-      Print ( L"%d Bytes/sec, Ave: %d Bytes/Sec\r\n",\r
-              Delta,\r
-              (UINT32) Average );\r
+    if (( RANGE_SWITCH >> 10 ) > Average ) {\r
+      Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",\r
+              Average,\r
+              BitsPerSecond );\r
     }\r
     else {\r
     }\r
     else {\r
-      Average >>= 10;\r
-      if ( Average < RANGE_SWITCH ) {\r
-        Print ( L"%d Bytes/sec, Ave: %d KiBytes/Sec\r\n",\r
-                Delta,\r
-                (UINT32) Average );\r
+      BitsPerSecond /= 1000;\r
+      if ( RANGE_SWITCH > Average ) {\r
+        Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",\r
+                Average >> 10,\r
+                (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                BitsPerSecond );\r
       }\r
       else {\r
       }\r
       else {\r
+        BitsPerSecond /= 1000;\r
         Average >>= 10;\r
         Average >>= 10;\r
-        if ( Average < RANGE_SWITCH ) {\r
-          Print ( L"%d Bytes/sec, Ave: %d MiBytes/Sec\r\n",\r
-                  Delta,\r
-                  (UINT32) Average );\r
+        if ( RANGE_SWITCH > Average ) {\r
+          Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",\r
+                  Average >> 10,\r
+                  (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                  BitsPerSecond );\r
         }\r
         else {\r
         }\r
         else {\r
+          BitsPerSecond /= 1000;\r
           Average >>= 10;\r
           Average >>= 10;\r
-          if ( Average < RANGE_SWITCH ) {\r
-            Print ( L"%d Bytes/sec, Ave: %d GiBytes/Sec\r\n",\r
-                    Delta,\r
-                    (UINT32) Average );\r
+          if ( RANGE_SWITCH > Average ) {\r
+            Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",\r
+                    Average >> 10,\r
+                    (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                    BitsPerSecond );\r
           }\r
           else {\r
           }\r
           else {\r
+            BitsPerSecond /= 1000;\r
             Average >>= 10;\r
             Average >>= 10;\r
-            if ( Average < RANGE_SWITCH ) {\r
-              Print ( L"%d Bytes/sec, Ave: %d TiBytes/Sec\r\n",\r
-                      Delta,\r
-                      Average );\r
+            if ( RANGE_SWITCH > Average ) {\r
+              Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",\r
+                      Average >> 10,\r
+                      (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                      BitsPerSecond );\r
             }\r
             else {\r
             }\r
             else {\r
+              BitsPerSecond /= 1000;\r
               Average >>= 10;\r
               Average >>= 10;\r
-              Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",\r
-                      Delta,\r
-                      (UINT32) Average );\r
+              Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",\r
+                      Average >> 10,\r
+                      (( Average & 0x3ff ) * 1000 ) >> 10,\r
+                      BitsPerSecond );\r
             }\r
           }\r
         }\r
             }\r
           }\r
         }\r
@@ -1528,17 +1674,8 @@ main (
     //  No bytes sent so far\r
     //\r
     TotalBytesSent = 0;\r
     //  No bytes sent so far\r
     //\r
     TotalBytesSent = 0;\r
-    AverageBytes = 0;\r
-    PreviousBytes = 0;\r
     Samples = 0;\r
     Samples = 0;\r
-\r
-    //\r
-    //  Get the port number\r
-    //\r
-    ZeroMem ( &RemoteHostAddress, sizeof ( RemoteHostAddress ));\r
-    RemoteHostAddress.sin_len = sizeof ( RemoteHostAddress );\r
-    RemoteHostAddress.sin_family = AF_INET;\r
-    RemoteHostAddress.sin_port = htons ( PcdGet16 ( DataSource_Port ));\r
+    memset ( &BytesSent, 0, sizeof ( BytesSent ));\r
 \r
     //\r
     //  Get the IP address\r
 \r
     //\r
     //  Get the IP address\r
index ec9cf6c185db9032a65f0d1ee996ea5d2bc8d174..8353041ddf83a8a5eb7e3f281e43d9f23d18576a 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 \r
 \r
 [Pcd]\r
 \r
 \r
 [Pcd]\r
-  gStdLibTokenSpaceGuid.DataSource_Port\r
+  gAppPkgTokenSpaceGuid.DataSource_Port\r
 \r
 \r
 [Packages]\r
 \r
 \r
 [Packages]\r
+  AppPkg/AppPkg.dec\r
   MdePkg/MdePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   StdLib/StdLib.dec\r
   MdePkg/MdePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   StdLib/StdLib.dec\r
diff --git a/AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.c b/AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.c
new file mode 100644 (file)
index 0000000..3db71ba
--- /dev/null
@@ -0,0 +1,120 @@
+/** @file\r
+  Test the getaddrinfo API\r
+\r
+  Copyright (c) 2011, Intel Corporation\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <errno.h>\r
+#include <netdb.h>\r
+#include <string.h>\r
+#include <stdio.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <netinet/in.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer[65536];\r
+\r
+\r
+/**\r
+  Test the getaddrinfo API\r
+\r
+  @param [in] Argc  The number of arguments\r
+  @param [in] Argv  The argument value array\r
+\r
+  @retval  0        The application exited normally.\r
+  @retval  Other    An error occurred.\r
+**/\r
+int\r
+main (\r
+  IN int Argc,\r
+  IN char **Argv\r
+  )\r
+{\r
+  int AppStatus;\r
+  int Index;\r
+  int MaxLen;\r
+  struct addrinfo * pAddrInfo;\r
+  char * pHostName;\r
+  struct addrinfo * pInfo;\r
+  char * pServerName;\r
+\r
+  //\r
+  //  Determine if the host name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 == Argc ) {\r
+    printf ( "%s  <host name>  <server name>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the host name\r
+    //\r
+    pHostName = Argv[1];\r
+    pServerName = NULL;\r
+    if ( 2 < Argc ) {\r
+      pServerName = Argv[2];\r
+    }\r
+    AppStatus = getaddrinfo ( pHostName,\r
+                              pServerName,\r
+                              NULL,\r
+                              &pAddrInfo );\r
+    if ( 0 != AppStatus ) {\r
+      printf ( "ERROR - address info not found, errno: %d\r\n", AppStatus );\r
+    }\r
+    if ( NULL == pAddrInfo ) {\r
+      printf ( "ERROR - No address info structure allocated\r\n" );\r
+    }\r
+    else {\r
+      //\r
+      //  Walk the list of addresses\r
+      //\r
+      pInfo = pAddrInfo;\r
+      while ( NULL != pInfo ) {\r
+        //\r
+        //  Display this entry\r
+        //\r
+        printf ( "0x%08x: ai_flags\r\n", pInfo->ai_flags );\r
+        printf ( "0x%08x: ai_family\r\n", pInfo->ai_family );\r
+        printf ( "0x%08x: ai_socktype\r\n", pInfo->ai_socktype );\r
+        printf ( "0x%08x: ai_protocol\r\n", pInfo->ai_protocol );\r
+        printf ( "0x%08x: ai_addrlen\r\n", pInfo->ai_addrlen );\r
+        printf ( "%s: ai_canonname\r\n", pInfo->ai_canonname );\r
+        printf ( "      0x%02x: ai_addr->sa_len\r\n", (UINT8)pInfo->ai_addr->sa_len );\r
+        printf ( "      0x%02x: ai_addr->sa_family\r\n", (UINT8)pInfo->ai_addr->sa_family );\r
+        MaxLen = pInfo->ai_addr->sa_len;\r
+        if ( sizeof ( struct sockaddr_in6 ) < MaxLen ) {\r
+          MaxLen = sizeof ( struct sockaddr_in6 );\r
+        }\r
+        for ( Index = 0; ( MaxLen - 2 ) > Index; Index++ ) {\r
+          printf ( "      0x%02x: ai_addr->sa_data[%02d]\r\n", (UINT8)pInfo->ai_addr->sa_data [ Index ], Index );\r
+        }\r
+\r
+        //\r
+        //  Set the next entry\r
+        //\r
+        pInfo = pInfo->ai_next;\r
+      }\r
+\r
+      //\r
+      //  Done with this structures\r
+      //\r
+      freeaddrinfo ( pAddrInfo );\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return AppStatus;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.inf b/AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.inf
new file mode 100644 (file)
index 0000000..c0d5c29
--- /dev/null
@@ -0,0 +1,63 @@
+#/** @file\r
+#  GetAddrInfo Application\r
+#\r
+# This file contains an 'Intel Peripheral Driver' and is      \r
+# licensed for Intel CPUs and chipsets under the terms of your\r
+# license agreement with Intel or your vendor.  This file may \r
+# be modified by the user, subject to additional terms of the \r
+# license agreement                                           \r
+#\r
+#\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
+# This software and associated documentation (if any) is furnished\r
+# under a license and may only be used or copied in accordance\r
+# with the terms of the license. Except as permitted by such\r
+# license, no part of this software or documentation may be\r
+# reproduced, stored in a retrieval system, or transmitted in any\r
+# form or by any means without the express written consent of\r
+# Intel Corporation.\r
+#\r
+##\r
+\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = GetAddrInfo\r
+  FILE_GUID                      = 4C26DF71-EBE7-4dea-B5E2-0B5980433908\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = ShellCEntryLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  GetAddrInfo.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  StdLib/StdLib.dec\r
+\r
+\r
+[LibraryClasses]\r
+  BaseMemoryLib\r
+  BsdSocketLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+#  UseSocketDxe\r
+\r
+[BuildOptions]\r
+  INTEL:*_*_*_CC_FLAGS = /Qdiag-disable:181,186\r
+   MSFT:*_*_*_CC_FLAGS = /Od\r
+    GCC:*_*_*_CC_FLAGS = -O0 -Wno-unused-variable\r
+\r
index f31b8278ddd040037cb6d8997cb48cf08750e876..e2aee9e48984568e440ef03bf100a636527c9a66 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 417eb5e228a0395504587e2919b4196e2e60b9d3..a69e1ffcd92c113f17edc28e62e0f563b95c7216 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 48beb2a26f7688c3ceabbe5bc2d6e1447b985001..84dc8507b7e47dd18768719e0a99aed1460753f4 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
diff --git a/AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.c b/AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.c
new file mode 100644 (file)
index 0000000..c9292e1
--- /dev/null
@@ -0,0 +1,120 @@
+/** @file\r
+  Test the getnameinfo API\r
+\r
+  Copyright (c) 2011, Intel Corporation\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <errno.h>\r
+#include <netdb.h>\r
+#include <string.h>\r
+#include <stdio.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <netinet/in.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer[65536];\r
+char mHostName[256];\r
+char mServiceName[256];\r
+\r
+/**\r
+  Test the getnameinfo API\r
+\r
+  @param [in] Argc  The number of arguments\r
+  @param [in] Argv  The argument value array\r
+\r
+  @retval  0        The application exited normally.\r
+  @retval  Other    An error occurred.\r
+**/\r
+int\r
+main (\r
+  IN int Argc,\r
+  IN char **Argv\r
+  )\r
+{\r
+  int AppStatus;\r
+  struct addrinfo * pAddrInfo;\r
+  char * pHostName;\r
+  struct addrinfo * pInfo;\r
+  char * pServerName;\r
+\r
+  //\r
+  //  Determine if the host name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 == Argc ) {\r
+    printf ( "%s  <host address>  <server name>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the host name\r
+    //\r
+    pHostName = Argv[1];\r
+    pServerName = NULL;\r
+    if ( 2 < Argc ) {\r
+      pServerName = Argv[2];\r
+    }\r
+    AppStatus = getaddrinfo ( pHostName,\r
+                              pServerName,\r
+                              NULL,\r
+                              &pAddrInfo );\r
+    if ( 0 != AppStatus ) {\r
+      printf ( "ERROR - address info not found, errno: %d\r\n", AppStatus );\r
+    }\r
+    if ( NULL == pAddrInfo ) {\r
+      printf ( "ERROR - No address info structure allocated\r\n" );\r
+    }\r
+    else {\r
+      //\r
+      //  Walk the list of names\r
+      //\r
+      pInfo = pAddrInfo;\r
+      while ( NULL != pInfo ) {\r
+        //\r
+        //  Get the name info\r
+        //\r
+        AppStatus = getnameinfo ((struct sockaddr *)pInfo->ai_addr,\r
+                                  pInfo->ai_addrlen,\r
+                                  &mHostName[0],\r
+                                  sizeof ( mHostName ),\r
+                                  &mServiceName[0],\r
+                                  sizeof ( mServiceName ),\r
+                                  0 );\r
+        if ( 0 != AppStatus ) {\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Display this entry\r
+        //\r
+        printf ( "%s: HostName\r\n", mHostName[0]);\r
+        printf ( "%s: Service Name\r\n", &mServiceName[0]);\r
+\r
+        //\r
+        //  Set the next entry\r
+        //\r
+        pInfo = pInfo->ai_next;\r
+      }\r
+\r
+      //\r
+      //  Done with this structures\r
+      //\r
+      freeaddrinfo ( pAddrInfo );\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return AppStatus;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.inf b/AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.inf
new file mode 100644 (file)
index 0000000..0b9ceb5
--- /dev/null
@@ -0,0 +1,63 @@
+#/** @file\r
+#  GetNameInfo Application\r
+#\r
+# This file contains an 'Intel Peripheral Driver' and is      \r
+# licensed for Intel CPUs and chipsets under the terms of your\r
+# license agreement with Intel or your vendor.  This file may \r
+# be modified by the user, subject to additional terms of the \r
+# license agreement                                           \r
+#\r
+#\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
+# This software and associated documentation (if any) is furnished\r
+# under a license and may only be used or copied in accordance\r
+# with the terms of the license. Except as permitted by such\r
+# license, no part of this software or documentation may be\r
+# reproduced, stored in a retrieval system, or transmitted in any\r
+# form or by any means without the express written consent of\r
+# Intel Corporation.\r
+#\r
+##\r
+\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = GetNameInfo\r
+  FILE_GUID                      = 553087F6-BAAC-4d7f-97B4-31D8179AAE15\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = ShellCEntryLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  GetNameInfo.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  StdLib/StdLib.dec\r
+\r
+\r
+[LibraryClasses]\r
+  BaseMemoryLib\r
+  BsdSocketLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+#  UseSocketDxe\r
+\r
+[BuildOptions]\r
+  INTEL:*_*_*_CC_FLAGS = /Qdiag-disable:181,186\r
+   MSFT:*_*_*_CC_FLAGS = /Od\r
+    GCC:*_*_*_CC_FLAGS = -O0 -Wno-unused-variable\r
+\r
index c280d186f1f9249e976ac5dad3c1f02abee3584f..2bc1836f4850a71f82b8528f2a5c83f69431b18a 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 1b9764e54bd6d2d2de3bc233d3d2481bc7f06c5b..8c706ba9470ede3dcbcef49db7112a0f738ece6f 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 290d15e9382c8db81920c2871a1205e0e000afd8..7af2f6c532e7370100629a93e8e6e4f5ef978b6f 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 1a232c0aad92143970113397c6fb296c5b91d2c6..ef902c4a3bf7e914f3820340bcdd98773d57f5ef 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 516f7cc215c0f89d39e5f1dd8aa48cc23219a134..fd137dd2321d44966adf521e7cdb9cb79a6273de 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index cc9c2b583e5c35b3c629193c2199b61c144b84f0..7f7c091b096d27ae6189f26c78331613c4a81374 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 4eba247f3474e884a124220737365863b2584186..b543f294ef3b49c9f28d16eaa0ba82becd3737fa 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 5452df08f621c1ad97def7855499e2c984b5289d..8852f148c883dfc11c9c0804685df5eb1e10d6cf 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index bef842ad54ea32b3a33772c0c76ecbf32ab89f74..6e51317a7a26baabdd546140c17fafec521f3501 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 2b0bdc7914b80ce9ef757df1c0b039ff2fc8fe60..539a315e4871f5e7913b9311e57da365c00b1d61 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index 835e1ebb61ab9be4704f80175dce3cb01580dd23..4de51338012ef51ff6cff2f4d2a022aa023667f6 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
index c1bd8bcc4ec4fbd6db55f37cb349232076d09b69..8b6bf8ed659f2c4a5e96880588160b599a440842 100644 (file)
@@ -6,9 +6,11 @@
 [Components]\r
   AppPkg/Applications/Sockets/DataSink/DataSink.inf\r
   AppPkg/Applications/Sockets/DataSource/DataSource.inf\r
 [Components]\r
   AppPkg/Applications/Sockets/DataSink/DataSink.inf\r
   AppPkg/Applications/Sockets/DataSource/DataSource.inf\r
+  AppPkg/Applications/Sockets/GetAddrInfo/GetAddrInfo.inf\r
   AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf\r
   AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf\r
   AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf\r
   AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf\r
   AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf\r
   AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf\r
+  AppPkg/Applications/Sockets/GetNameInfo/GetNameInfo.inf\r
   AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf\r
   AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf\r
   AppPkg/Applications/Sockets/GetServByName/GetServByName.inf\r
   AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf\r
   AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf\r
   AppPkg/Applications/Sockets/GetServByName/GetServByName.inf\r
index 1da3c250d56693672762deda02d8d91fbe3fb705..e9ab0dee5f059537d37dc1257a27273ed66a9dbb 100644 (file)
-/*++\r
-  This file contains an 'Intel UEFI Application' and is\r
-  licensed for Intel CPUs and chipsets under the terms of your\r
-  license agreement with Intel or your vendor.  This file may\r
-  be modified by the user, subject to additional terms of the\r
-  license agreement\r
---*/\r
-/*++\r
-\r
-Copyright (c)  2011 Intel Corporation. All rights reserved\r
-This software and associated documentation (if any) is furnished\r
-under a license and may only be used or copied in accordance\r
-with the terms of the license. Except as permitted by such\r
-license, no part of this software or documentation may be\r
-reproduced, stored in a retrieval system, or transmitted in any\r
-form or by any means without the express written consent of\r
-Intel Corporation.\r
-\r
---*/\r
-\r
 /** @file\r
   This is a simple TFTP server application\r
 \r
 /** @file\r
   This is a simple TFTP server application\r
 \r
+  Copyright (c) 2011, 2012, Intel Corporation\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
 **/\r
 \r
 #include <TftpServer.h>\r
 \r
 **/\r
 \r
 #include <TftpServer.h>\r
 \r
-TSDT_TFTP_SERVER mTftpServer; ///<  TFTP server's control structure\r
+TSDT_TFTP_SERVER mTftpServer;       ///<  TFTP server's control structure\r
+volatile BOOLEAN mbTftpServerExit;  ///<  Set TRUE to cause TFTP server to exit\r
 \r
 \r
 /**\r
 \r
 \r
 /**\r
-  Add a connection context to the list of connection contexts.\r
+  Read file data into a buffer\r
 \r
 \r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
+  @param [in] pContext    Connection context structure address\r
 \r
 \r
-  @retval Context structure address, NULL if allocation fails\r
+  @retval TRUE if a read error occurred\r
 \r
 **/\r
 \r
 **/\r
-TSDT_CONNECTION_CONTEXT *\r
-ContextAdd (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+BOOLEAN\r
+BufferFill (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
   )\r
 {\r
   )\r
 {\r
-  size_t LengthInBytes;\r
-  TSDT_CONNECTION_CONTEXT * pContext;\r
-  EFI_STATUS Status;\r
+  BOOLEAN bReadError;\r
+  size_t BytesRead;\r
+  UINT64 LengthInBytes;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Use for/break instead of goto\r
+  //  Use break instead of goto\r
   //\r
   //\r
+  bReadError = FALSE;\r
   for ( ; ; ) {\r
     //\r
   for ( ; ; ) {\r
     //\r
-    //  Allocate a new context\r
-    //\r
-    LengthInBytes = sizeof ( *pContext );\r
-    Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
-                                 LengthInBytes,\r
-                                 (VOID **)&pContext );\r
-    if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
-                "ERROR - Failed to allocate the context, Status: %r\r\n",\r
-                Status ));\r
-      pContext = NULL;\r
+    //  Determine if there is any work to do\r
+    //\r
+    LengthInBytes = DIM ( pContext->FileData ) >> 1;\r
+    if (( pContext->ValidBytes > LengthInBytes )\r
+      || ( 0 == pContext->BytesRemaining )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Determine the number of bytes to read\r
+    //\r
+    if ( LengthInBytes > pContext->BytesRemaining ) {\r
+      LengthInBytes = pContext->BytesRemaining;\r
+    }\r
+\r
+    //\r
+    //  Read in the next portion of the file\r
+    //\r
+    BytesRead = fread ( pContext->pFill,\r
+                        1,\r
+                        (size_t)LengthInBytes,\r
+                        pContext->File );\r
+    if ( -1 == BytesRead ) {\r
+      bReadError = TRUE;\r
       break;\r
     }\r
 \r
       break;\r
     }\r
 \r
+    //\r
+    //  Account for the file data read\r
+    //\r
+    pContext->BytesRemaining -= BytesRead;\r
+    pContext->ValidBytes += BytesRead;\r
+    DEBUG (( DEBUG_FILE_BUFFER,\r
+              "0x%08x: Buffer filled with %Ld bytes, %Ld bytes ramaining\r\n",\r
+              pContext->pFill,\r
+              BytesRead,\r
+              pContext->BytesRemaining ));\r
+\r
+    //\r
+    //  Set the next buffer location\r
+    //\r
+    pContext->pFill += BytesRead;\r
+    if ( pContext->pEnd <= pContext->pFill ) {\r
+      pContext->pFill = &pContext->FileData[ 0 ];\r
+    }\r
+\r
+    //\r
+    //  Verify that the end of the buffer is reached\r
+    //\r
+    ASSERT ( 0 == ( DIM ( pContext->FileData ) & 1 ));\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the read status\r
+  //\r
+  DBG_EXIT ( );\r
+  return bReadError;\r
+}\r
+\r
+\r
+/**\r
+  Add a connection context to the list of connection contexts.\r
+\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] SocketFd      Socket file descriptor\r
+\r
+  @retval Context structure address, NULL if allocation fails\r
+\r
+**/\r
+TSDT_CONNECTION_CONTEXT *\r
+ContextAdd (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN int SocketFd\r
+  )\r
+{\r
+  TSDT_CONNECTION_CONTEXT * pContext;\r
+  TFTP_PACKET * pEnd;\r
+  TFTP_PACKET * pPacket;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Allocate a new context\r
+  //\r
+  pContext = (TSDT_CONNECTION_CONTEXT *)AllocateZeroPool ( sizeof ( *pContext ));\r
+  if ( NULL != pContext ) {\r
     //\r
     //  Initialize the context\r
     //\r
     //\r
     //  Initialize the context\r
     //\r
-    ZeroMem ( pContext, LengthInBytes );\r
+    pContext->SocketFd = SocketFd;\r
     CopyMem ( &pContext->RemoteAddress,\r
               &pTftpServer->RemoteAddress,\r
               sizeof ( pContext->RemoteAddress ));\r
     CopyMem ( &pContext->RemoteAddress,\r
               &pTftpServer->RemoteAddress,\r
               sizeof ( pContext->RemoteAddress ));\r
-    pContext->BlockSize = TFTP_MAX_BLOCK_SIZE;\r
-    pContext->pBuffer = &pContext->FileData[0];\r
-    pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )];\r
-    pContext->MaxTransferSize = 0;\r
-    pContext->MaxTransferSize -= 1;\r
+    pContext->BlockSize = 512;\r
+\r
+    //\r
+    //  Buffer management\r
+    //\r
+    pContext->pFill = &pContext->FileData[ 0 ];\r
+    pContext->pEnd = &pContext->FileData[ sizeof ( pContext->FileData )];\r
+    pContext->pBuffer = pContext->pFill;\r
+\r
+    //\r
+    //  Window management\r
+    //\r
+    pContext->MaxTimeout = MultU64x32 ( PcdGet32 ( Tftp_MaxTimeoutInSec ),\r
+                                        2 * 1000 * 1000 * 1000 );\r
+    pContext->Rtt2x = pContext->MaxTimeout;\r
+    pContext->WindowSize = MAX_PACKETS;\r
+    WindowTimeout ( pContext );\r
+\r
+    //\r
+    //  Place the packets on the free list\r
+    //\r
+    pPacket = &pContext->Tx[ 0 ];\r
+    pEnd = &pPacket[ DIM ( pContext->Tx )];\r
+    while ( pEnd > pPacket ) {\r
+      PacketFree ( pContext, pPacket );\r
+      pPacket += 1;\r
+    }\r
 \r
     //\r
     //  Display the new context\r
     //\r
 \r
     //\r
     //  Display the new context\r
     //\r
-    DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,\r
-              "0x%08x: Context for %d.%d.%d.%d:%d\r\n",\r
-              pContext,\r
-              (UINT8)pContext->RemoteAddress.sin_addr.s_addr,\r
-              (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ),\r
-              (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ),\r
-              (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ),\r
-              htons ( pContext->RemoteAddress.sin_port )));\r
+    if ( AF_INET == pTftpServer->RemoteAddress.v4.sin_family ) {\r
+      DEBUG (( DEBUG_PORT_WORK,\r
+                "0x%08x: Context for %d.%d.%d.%d:%d\r\n",\r
+                pContext,\r
+                (UINT8)pTftpServer->RemoteAddress.v4.sin_addr.s_addr,\r
+                (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 8 ),\r
+                (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 16 ),\r
+                (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 24 ),\r
+                htons ( pTftpServer->RemoteAddress.v4.sin_port )));\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_PORT_WORK,\r
+                "0x%08x: Context for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                pContext,\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                htons ( pTftpServer->RemoteAddress.v6.sin6_port )));\r
+    }\r
 \r
     //\r
     //  Add the context to the context list\r
     //\r
     pContext->pNext = pTftpServer->pContextList;\r
     pTftpServer->pContextList = pContext;\r
 \r
     //\r
     //  Add the context to the context list\r
     //\r
     pContext->pNext = pTftpServer->pContextList;\r
     pTftpServer->pContextList = pContext;\r
-\r
-    //\r
-    //  All done\r
-    //\r
-    break;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -114,10 +219,8 @@ ContextAdd (
 /**\r
   Locate a remote connection context.\r
 \r
 /**\r
   Locate a remote connection context.\r
 \r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
-\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
   @param [in] pIpAddress    The start of the remote IP address in network order\r
   @param [in] pIpAddress    The start of the remote IP address in network order\r
-\r
   @param [in] Port          The remote port number\r
 \r
   @retval Context structure address, NULL if not found\r
   @param [in] Port          The remote port number\r
 \r
   @retval Context structure address, NULL if not found\r
@@ -140,8 +243,9 @@ ContextFind (
     //\r
     //  Attempt to locate the remote network connection\r
     //\r
     //\r
     //  Attempt to locate the remote network connection\r
     //\r
-    if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr )\r
-      && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) {\r
+    if ( 0 == memcmp ( &pTftpServer->RemoteAddress,\r
+                       &pContext->RemoteAddress,\r
+                       pTftpServer->RemoteAddress.v6.sin6_len )) {\r
       //\r
       //  The connection was found\r
       //\r
       //\r
       //  The connection was found\r
       //\r
@@ -168,9 +272,8 @@ ContextFind (
 /**\r
   Remove a context from the list.\r
 \r
 /**\r
   Remove a context from the list.\r
 \r
-  @param [in] pTftpServer    The TFTP server control structure address.\r
-\r
-  @param [in] pContext       The context structure address.\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext      Address of a ::TSDT_CONNECTION_CONTEXT structure\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
@@ -228,297 +331,900 @@ ContextRemove (
 \r
 \r
 /**\r
 \r
 \r
 /**\r
-  Process the work for the sockets.\r
+  Queue data packets for transmission\r
+\r
+  @param [in] pContext    Connection context structure address\r
 \r
 \r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
+  @retval TRUE if a read error occurred\r
 \r
 **/\r
 \r
 **/\r
-VOID\r
-PortWork (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+BOOLEAN\r
+PacketFill (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
   )\r
 {\r
   )\r
 {\r
-  TSDT_CONNECTION_CONTEXT * pContext;\r
-  socklen_t RemoteAddressLength;\r
+  BOOLEAN bReadError;\r
+  UINT64 LengthInBytes;\r
+  UINT8 * pBuffer;\r
+  TFTP_PACKET * pPacket;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Handle input events\r
+  //  Use break instead of goto\r
   //\r
   //\r
-  if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) {\r
+  bReadError = FALSE;\r
+  for ( ; ; ) {\r
     //\r
     //\r
-    //  Receive the message from the remote system\r
+    //  Fill the buffer if necessary\r
     //\r
     //\r
-    RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );\r
-    pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd,\r
-                                      &pTftpServer->RxBuffer[0],\r
-                                      sizeof ( pTftpServer->RxBuffer ),\r
-                                      0,\r
-                                      (struct sockaddr *) &pTftpServer->RemoteAddress,\r
-                                      &RemoteAddressLength );\r
-    if ( -1 != pTftpServer->RxBytes ) {\r
-      pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength;\r
-      DEBUG (( DEBUG_TFTP_PORT,\r
-                 "Received %d bytes from %d.%d.%d.%d:%d\r\n",\r
-                 pTftpServer->RxBytes,\r
-                 pTftpServer->RemoteAddress.sin_addr.s_addr & 0xff,\r
-                 ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
-                 ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
-                 ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
-                 htons ( pTftpServer->RemoteAddress.sin_port )));\r
-\r
+    bReadError = BufferFill ( pContext );\r
+    if ( bReadError ) {\r
       //\r
       //\r
-      //  Lookup connection context using the remote system address and port\r
-      //  to determine if an existing connection to this remote\r
-      //  system exists\r
+      //  File access mode not supported\r
       //\r
       //\r
-      pContext = ContextFind ( pTftpServer );\r
+      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
+                "ERROR - File read failure!\r\n" ));\r
 \r
       //\r
 \r
       //\r
-      //  Process the received message\r
+      //  Tell the client of the error\r
       //\r
       //\r
-      TftpProcessRequest ( pTftpServer, pContext );\r
+      SendError ( pContext,\r
+                  TFTP_ERROR_SEE_MSG,\r
+                  (UINT8 *)"Read failure" );\r
+      break;\r
     }\r
     }\r
-    else {\r
+\r
+    //\r
+    //  Determine if any packets can be filled\r
+    //\r
+    if ( pContext->bEofSent\r
+      || ( NULL == pContext->pFreeList )) {\r
       //\r
       //\r
-      //  Receive error on the TFTP server port\r
-      //  Close the server socket\r
+      //  All of the packets are filled\r
       //\r
       //\r
-      DEBUG (( DEBUG_ERROR,\r
-                "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",\r
-                errno ));\r
-      pTftpServer->TftpPort.revents |= POLLHUP;\r
+      break;\r
     }\r
     }\r
-  }\r
 \r
 \r
-  //\r
-  //  Handle the close event\r
-  //\r
-  if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) {\r
     //\r
     //\r
-    //  Close the port\r
+    //  Set the TFTP opcode and block number\r
+    //\r
+    pPacket = PacketGet ( pContext );\r
+    pBuffer = &pPacket->TxBuffer[ 0 ];\r
+    *pBuffer++ = 0;\r
+    *pBuffer++ = TFTP_OP_DATA;\r
+    *pBuffer++ = (UINT8)( pContext->BlockNumber >> 8 );\r
+    *pBuffer++ = (UINT8)pContext->BlockNumber;\r
+\r
+    //\r
+    //  Determine how much data needs to be sent\r
+    //\r
+    LengthInBytes = pContext->BlockSize;\r
+    if (( pContext->BytesToSend < TFTP_MAX_BLOCK_SIZE )\r
+      && ( LengthInBytes > pContext->BytesToSend )) {\r
+      LengthInBytes = pContext->BytesToSend;\r
+      pContext->bEofSent = TRUE;\r
+    }\r
+    DEBUG (( DEBUG_TX_PACKET,\r
+              "0x%08x: Packet, Block %d filled with %d bytes\r\n",\r
+              pPacket,\r
+              pContext->BlockNumber,\r
+              (UINT32)LengthInBytes ));\r
+    \r
+    //\r
+    //  Copy the file data into the packet\r
+    //\r
+    pPacket->TxBytes = (ssize_t)( 2 + 2 + LengthInBytes );\r
+    if ( 0 < LengthInBytes ) {\r
+      CopyMem ( pBuffer,\r
+                pContext->pBuffer,\r
+                (UINTN)LengthInBytes );\r
+      DEBUG (( DEBUG_FILE_BUFFER,\r
+                "0x%08x: Buffer consumed %d bytes of file data\r\n",\r
+                pContext->pBuffer,\r
+                LengthInBytes ));\r
+\r
+      //\r
+      //  Account for the file data consumed\r
+      //\r
+      pContext->ValidBytes -= LengthInBytes;\r
+      pContext->BytesToSend -= LengthInBytes;\r
+      pContext->pBuffer += LengthInBytes;\r
+      if ( pContext->pEnd <= pContext->pBuffer ) {\r
+        pContext->pBuffer = &pContext->FileData[ 0 ];\r
+      }\r
+    }\r
+    \r
+    //\r
+    //  Queue the packet for transmission\r
     //\r
     //\r
-    close ( pTftpServer->TftpPort.fd );\r
-    pTftpServer->TftpPort.fd = -1;\r
+    PacketQueue ( pContext, pPacket );\r
   }\r
 \r
   }\r
 \r
+  //\r
+  //  Return the read status\r
+  //\r
   DBG_EXIT ( );\r
   DBG_EXIT ( );\r
+  return bReadError;\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Scan the list of sockets and process any pending work\r
+  Free the packet\r
 \r
 \r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
-SocketPoll (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+PacketFree(\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
   )\r
 {\r
   )\r
 {\r
-  int FDCount;\r
-\r
-  DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));\r
+  DBG_ENTER ( );\r
 \r
   //\r
 \r
   //\r
-  //  Determine if any ports are active\r
+  //  Don't free the error packet\r
   //\r
   //\r
-  FDCount = poll ( &pTftpServer->TftpPort,\r
-                   1,\r
-                   CLIENT_POLL_DELAY );\r
-  if ( -1 == FDCount ) {\r
-    DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL,\r
-              "ERROR - errno: %d\r\n",\r
-              errno ));\r
-  }\r
-\r
-  if ( 0 < FDCount ) {\r
+  if ( pPacket != &pContext->ErrorPacket ) {\r
     //\r
     //\r
-    //  Process this port\r
+    //  Place the packet on the free list\r
     //\r
     //\r
-    PortWork ( pTftpServer );\r
-    pTftpServer->TftpPort.revents = 0;\r
+    pPacket->pNext = pContext->pFreeList;\r
+    pContext->pFreeList = pPacket;\r
+    DEBUG (( DEBUG_TX_PACKET,\r
+              "0x%08x: Packet queued to free list\r\n",\r
+              pPacket ));\r
   }\r
 \r
   }\r
 \r
-  DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));\r
+  DBG_EXIT ( );\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Convert a character to lower case\r
+  Get a packet from the free list for transmission\r
 \r
 \r
-  @param [in] Character The character to convert\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
 \r
 \r
-  @return   The lower case equivalent of the character\r
+  @retval Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
 \r
 **/\r
-int\r
-tolower (\r
-  int Character\r
+TFTP_PACKET *\r
+PacketGet (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
   )\r
 {\r
   )\r
 {\r
+  TFTP_PACKET * pPacket;\r
+\r
+  DBG_ENTER ( );\r
+\r
   //\r
   //\r
-  //  Determine if the character is upper case\r
+  //  Get the next packet from the free list\r
   //\r
   //\r
-  if (( 'A' <= Character ) && ( 'Z' >= Character )) {\r
-    //\r
-    //  Convert the character to lower caes\r
-    //\r
-    Character += 'a' - 'A';\r
+  pPacket = pContext->pFreeList;\r
+  if ( NULL != pPacket ) {\r
+    pContext->pFreeList = pPacket->pNext;\r
+    pPacket->RetryCount = 0;\r
+    DEBUG (( DEBUG_TX_PACKET,\r
+              "0x%08x: Packet removed from free list\r\n",\r
+              pPacket ));\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  //  Return the converted character\r
+  //  Return the packet\r
   //\r
   //\r
-  return Character;\r
+  DBG_EXIT_HEX ( pPacket );\r
+  return pPacket;\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Case independent string comparison\r
+  Queue the packet for transmission\r
 \r
 \r
-  @param [in] pString1  Zero terminated string address\r
-  @param [in] pString2  Zero terminated string address\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 \r
-  @return     Returns the first character difference between string 1\r
-              and string 2.\r
+  @retval TRUE if a transmission error has occurred\r
 \r
 **/\r
 \r
 **/\r
-int\r
-stricmp (\r
-  char * pString1,\r
-  char * pString2\r
+BOOLEAN\r
+PacketQueue (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
   )\r
 {\r
   )\r
 {\r
-  int Char1;\r
-  int Char2;\r
-  int Difference;\r
+  BOOLEAN bTransmitError;\r
+  TFTP_PACKET * pTail;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
 \r
   //\r
 \r
   //\r
-  //  Walk the length of the strings\r
+  //  Account for this data block\r
   //\r
   //\r
-  do {\r
-    //\r
-    //  Get the next characters\r
-    //\r
-    Char1 = (UINT8)*pString1++;\r
-    Char2 = (UINT8)*pString2++;\r
+  pPacket->BlockNumber = pContext->BlockNumber;\r
+  pContext->BlockNumber += 1;\r
 \r
 \r
-    //\r
-    //  Convert them to lower case\r
-    //\r
-    Char1 = tolower ( Char1 );\r
-    Char2 = tolower ( Char2 );\r
+  //\r
+  //  Queue the packet for transmission\r
+  //\r
+  pTail = pContext->pTxTail;\r
+  if ( NULL == pTail ) {\r
+    pContext->pTxHead = pPacket;\r
+  }\r
+  else {\r
+    pTail->pNext = pPacket;\r
+  }\r
+  pContext->pTxTail = pPacket;\r
+  pPacket->pNext = NULL;\r
+  DEBUG (( DEBUG_TX_PACKET,\r
+            "0x%08x: Packet queued to TX list\r\n",\r
+            pPacket ));\r
 \r
 \r
-    //\r
-    //  Done when the characters differ\r
-    //\r
-    Difference = Char1 - Char2;\r
-    if ( 0 != Difference ) {\r
-      break;\r
+  //\r
+  //  Start the transmission if necessary\r
+  //\r
+  bTransmitError = FALSE;\r
+  if ( pContext->PacketsInWindow < pContext->WindowSize ) {\r
+    Status = PacketTx ( pContext, pPacket );\r
+    bTransmitError = (BOOLEAN)( EFI_ERROR ( Status ));\r
+  }\r
+\r
+  //\r
+  //  Return the transmit status\r
+  //\r
+  DBG_EXIT_TF ( bTransmitError );\r
+  return bTransmitError;\r
+}\r
+\r
+\r
+/**\r
+  Remove a packet from the transmit queue\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+\r
+**/\r
+TFTP_PACKET *\r
+PacketRemove(\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
+  )\r
+{\r
+  TFTP_PACKET * pNext;\r
+  TFTP_PACKET * pPacket;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Remove a packet from the transmit queue\r
+  //\r
+  //\r
+  pPacket = pContext->pTxHead;\r
+  if ( NULL != pPacket ) {\r
+    pNext = pPacket->pNext;\r
+    pContext->pTxHead = pNext;\r
+    if ( NULL == pNext ) {\r
+      pContext->pTxTail = NULL;\r
     }\r
     }\r
+    DEBUG (( DEBUG_TX_PACKET,\r
+              "0x%08x: Packet removed from TX list\r\n",\r
+              pPacket ));\r
 \r
     //\r
 \r
     //\r
-    //  Done at the end of the string\r
+    //  Remove this packet from the window\r
     //\r
     //\r
-  } while ( 0 != Char1 );\r
+    pContext->PacketsInWindow -= 1;\r
+  }\r
 \r
   //\r
 \r
   //\r
-  //  Return the difference\r
+  //  Return the packet\r
   //\r
   //\r
-  return Difference;\r
+  DBG_EXIT_HEX ( pPacket );\r
+  return pPacket;\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Get the next TFTP option\r
+  Transmit the packet\r
 \r
 \r
-  @param [in] pOption       Address of a zero terminated option string\r
-  @param [in] pEnd          End of buffer address\r
-  @param [in] ppNextOption  Address to receive the address of the next\r
-                            zero terminated option string\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
   @retval EFI_SUCCESS   Message processed successfully\r
 \r
 **/\r
 EFI_STATUS\r
 \r
   @retval EFI_SUCCESS   Message processed successfully\r
 \r
 **/\r
 EFI_STATUS\r
-TftpOptionGet (\r
-  IN UINT8 * pOption,\r
-  IN UINT8 * pEnd,\r
-  IN UINT8 ** ppNextOption\r
+PacketTx (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
   )\r
 {\r
   )\r
 {\r
-  UINT8 * pNextOption;\r
+  ssize_t LengthInBytes;\r
   EFI_STATUS Status;\r
 \r
   EFI_STATUS Status;\r
 \r
+  DBG_ENTER ( );\r
+\r
   //\r
   //\r
-  //  Locate the end of the option\r
+  //  Assume success\r
   //\r
   //\r
-  pNextOption = pOption;\r
-  while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {\r
-    pNextOption += 1;\r
-  }\r
-  if ( pEnd <= pNextOption ) {\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Determine if this packet should be transmitted\r
+  //\r
+  if ( PcdGet32 ( Tftp_MaxRetry ) >= pPacket->RetryCount ) {\r
+    pPacket->RetryCount += 1;\r
+\r
     //\r
     //\r
-    //  Error - end of buffer reached\r
+    //  Display the operation\r
     //\r
     //\r
-    DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
-              "ERROR - Option without zero termination received!\r\n" ));\r
-    Status = EFI_INVALID_PARAMETER;\r
-  }\r
-  else {\r
+    DEBUG (( DEBUG_TX_PACKET,\r
+              "0x%08x: Packet transmiting\r\n",\r
+              pPacket ));\r
+    DEBUG (( DEBUG_TX,\r
+              "0x%08x: pContext sending 0x%08x bytes\r\n",\r
+              pContext,\r
+              pPacket->TxBytes ));\r
+\r
     //\r
     //\r
-    //  Zero terminated option found\r
+    //  Keep track of when the packet was transmitted\r
     //\r
     //\r
-    pNextOption += 1;\r
+    if ( PcdGetBool ( Tftp_HighSpeed )) {\r
+      pPacket->TxTime = GetPerformanceCounter ( );\r
+    }\r
 \r
     //\r
 \r
     //\r
-    //  Display the zero terminated ASCII option string\r
+    //  Send the TFTP packet\r
     //\r
     //\r
-    DEBUG (( DEBUG_TFTP_REQUEST,\r
-              "Option: %a\r\n",\r
-              pOption ));\r
-    Status = EFI_SUCCESS;\r
+    pContext->PacketsInWindow += 1;\r
+    LengthInBytes = sendto ( pContext->SocketFd,\r
+                             &pPacket->TxBuffer[ 0 ],\r
+                             pPacket->TxBytes,\r
+                             0,\r
+                             (struct sockaddr *)&pContext->RemoteAddress,\r
+                             pContext->RemoteAddress.sin6_len );\r
+    if ( -1 == LengthInBytes ) {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_TX,\r
+                "ERROR - Transmit failure, errno: 0x%08x\r\n",\r
+                errno ));\r
+      pContext->PacketsInWindow -= 1;\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+  else {\r
+    //\r
+    //  Too many retries\r
+    //\r
+    Status = EFI_NO_RESPONSE;\r
+    DEBUG (( DEBUG_WARN | DEBUG_WINDOW,\r
+              "WARNING - No response from TFTP client\r\n" ));\r
   }\r
   }\r
-\r
-  //\r
-  //  Return the next option address\r
-  //\r
-  *ppNextOption = pNextOption;\r
 \r
   //\r
   //  Return the operation status\r
   //\r
 \r
   //\r
   //  Return the operation status\r
   //\r
+  DBG_EXIT_STATUS ( Status );\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Place an option value into the option acknowledgement\r
-\r
-  @param [in] pOack     Option acknowledgement address\r
-  @param [in] Value     Value to translate into ASCII decimal\r
+  Process the work for the sockets.\r
 \r
 \r
-  @return               Option acknowledgement address\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pIndex        Address of an index into the pollfd array\r
 \r
 **/\r
 \r
 **/\r
-UINT8 *\r
-TftpOptionSet (\r
-  IN UINT8 * pOack,\r
-  IN UINT64 Value\r
+VOID\r
+PortWork (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN int * pIndex\r
   )\r
 {\r
   )\r
 {\r
-  UINT64 NextValue;\r
+  int Index;\r
+  TSDT_CONNECTION_CONTEXT * pContext;\r
+  struct pollfd * pTftpPort;\r
+  socklen_t RemoteAddressLength;\r
+  int revents;\r
 \r
 \r
-  //\r
-  //  Determine the next value\r
-  //\r
-  NextValue = Value / 10;\r
+  DBG_ENTER ( );\r
 \r
   //\r
 \r
   //\r
-  //  Supress leading zeros\r
+  //  Locate the port\r
+  //\r
+  Index = *pIndex;\r
+  if ( -1 != Index ) {\r
+    pTftpPort = &pTftpServer->TftpPort[ *pIndex ];\r
+\r
+    //\r
+    //  Handle input events\r
+    //\r
+    revents = pTftpPort->revents;\r
+    pTftpPort->revents = 0;\r
+    if ( 0 != ( revents & POLLRDNORM )) {\r
+      //\r
+      //  Receive the message from the remote system\r
+      //\r
+      RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );\r
+      pTftpServer->RxBytes = recvfrom ( pTftpPort->fd,\r
+                                        &pTftpServer->RxBuffer[ 0 ],\r
+                                        sizeof ( pTftpServer->RxBuffer ),\r
+                                        0,\r
+                                        (struct sockaddr *) &pTftpServer->RemoteAddress,\r
+                                        &RemoteAddressLength );\r
+      if ( -1 != pTftpServer->RxBytes ) {\r
+        if ( PcdGetBool ( Tftp_HighSpeed )) {\r
+          pTftpServer->RxTime = GetPerformanceCounter ( );\r
+        }\r
+        if ( AF_INET == pTftpServer->RemoteAddress.v4.sin_family ) {\r
+          DEBUG (( DEBUG_TFTP_PORT,\r
+                   "Received %d bytes from %d.%d.%d.%d:%d\r\n",\r
+                   pTftpServer->RxBytes,\r
+                   pTftpServer->RemoteAddress.v4.sin_addr.s_addr & 0xff,\r
+                   ( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 8 ) & 0xff,\r
+                   ( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 16 ) & 0xff,\r
+                   ( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 24 ) & 0xff,\r
+                   htons ( pTftpServer->RemoteAddress.v4.sin_port )));\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_TFTP_PORT,\r
+                   "Received %d bytes from [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                   pTftpServer->RxBytes,\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                   pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                   htons ( pTftpServer->RemoteAddress.v6.sin6_port )));\r
+        }\r
+\r
+        //\r
+        //  Lookup connection context using the remote system address and port\r
+        //  to determine if an existing connection to this remote\r
+        //  system exists\r
+        //\r
+        pContext = ContextFind ( pTftpServer );\r
+\r
+        //\r
+        //  Process the received message\r
+        //\r
+        TftpProcessRequest ( pTftpServer, pContext, pTftpPort->fd );\r
+      }\r
+      else {\r
+        //\r
+        //  Receive error on the TFTP server port\r
+        //  Close the server socket\r
+        //\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",\r
+                  errno ));\r
+        revents |= POLLHUP;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Handle the close event\r
+    //\r
+    if ( 0 != ( revents & POLLHUP )) {\r
+      //\r
+      //  Close the port\r
+      //\r
+      close ( pTftpPort->fd );\r
+      pTftpPort->fd = -1;\r
+      *pIndex = -1;\r
+      pTftpServer->Entries -= 1;\r
+      ASSERT ( 0 <= pTftpServer->Entries );\r
+    }\r
+  }\r
+\r
+  DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+  Build and send an error packet\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] Error       Error number for the packet\r
+  @param [in] pError      Zero terminated error string address\r
+\r
+  @retval EFI_SUCCESS     Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+SendError (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN UINT16 Error,\r
+  IN UINT8 * pError\r
+  )\r
+{\r
+  UINT8 Character;\r
+  UINT8 * pBuffer;\r
+  TFTP_PACKET * pPacket;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Build the error packet\r
+  //\r
+  pPacket = &pContext->ErrorPacket;\r
+  pBuffer = &pPacket->TxBuffer[ 0 ];\r
+  pBuffer[ 0 ] = 0;\r
+  pBuffer[ 1 ] = TFTP_OP_ERROR;\r
+  pBuffer[ 2 ] = (UINT8)( Error >> 8 );\r
+  pBuffer[ 3 ] = (UINT8)Error;\r
+\r
+  //\r
+  //  Copy the zero terminated string into the buffer\r
+  //\r
+  pBuffer += 4;\r
+  do {\r
+    Character = *pError++;\r
+    *pBuffer++ = Character;\r
+  } while ( 0 != Character );\r
+\r
+  //\r
+  //  Send the error message\r
+  //\r
+  pPacket->TxBytes = pBuffer - &pPacket->TxBuffer[ 0 ];\r
+  Status = PacketTx ( pContext, pPacket );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Scan the list of sockets and process any pending work\r
+\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
+\r
+**/\r
+VOID\r
+SocketPoll (\r
+  IN TSDT_TFTP_SERVER * pTftpServer\r
+  )\r
+{\r
+  int FDCount;\r
+\r
+  DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));\r
+\r
+  //\r
+  //  Determine if any ports are active\r
+  //\r
+  if ( 0 != pTftpServer->Entries ) {\r
+    FDCount = poll ( &pTftpServer->TftpPort[ 0 ],\r
+                     pTftpServer->Entries,\r
+                     CLIENT_POLL_DELAY );\r
+    if ( 0 < FDCount ) {\r
+      //\r
+      //  Process this port\r
+      //\r
+      PortWork ( pTftpServer, &pTftpServer->Udpv4Index );\r
+      PortWork ( pTftpServer, &pTftpServer->Udpv6Index );\r
+    }\r
+  }\r
+\r
+  DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));\r
+}\r
+\r
+\r
+/**\r
+  Process the ACK\r
+\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Connection context structure address\r
+\r
+  @retval TRUE if the context should be closed\r
+\r
+**/\r
+BOOLEAN\r
+TftpAck (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
+  )\r
+{\r
+  INTN AckNumber;\r
+  BOOLEAN bCloseContext;\r
+  UINT16 BlockNumber;\r
+  UINT8 * pBuffer;\r
+  TFTP_PACKET * pPacket;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Use break instead of goto\r
+  //\r
+  bCloseContext = FALSE;\r
+  for ( ; ; ) {\r
+    //\r
+    //  Validate the parameters\r
+    //\r
+    if ( NULL == pContext ) {\r
+      if ( AF_INET == pTftpServer->RemoteAddress.v4.sin_family ) {\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
+                  (UINT8)pTftpServer->RemoteAddress.v4.sin_addr.s_addr,\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 8 ),\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 16 ),\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 24 ),\r
+                  htons ( pTftpServer->RemoteAddress.v4.sin_port )));\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - File not open for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                  htons ( pTftpServer->RemoteAddress.v6.sin6_port )));\r
+      }\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Verify that the ACK was expected\r
+    //\r
+    pPacket = pContext->pTxHead;\r
+    if ( NULL == pPacket ) {\r
+      //\r
+      //  ACK not expected!\r
+      //\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",\r
+                pContext ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Get the ACKed block number\r
+    //\r
+    pBuffer = &pTftpServer->RxBuffer[ 0 ];\r
+    BlockNumber = HTONS ( *(UINT16 *)&pBuffer[ 2 ]);\r
+\r
+    //\r
+    //  Determine if this is the correct ACK\r
+    //\r
+    DEBUG (( DEBUG_TFTP_ACK,\r
+              "ACK for block 0x%04x received\r\n",\r
+              BlockNumber ));\r
+    AckNumber = BlockNumber - pPacket->BlockNumber;\r
+    if (( 0 > AckNumber ) || ( AckNumber >= (INTN)pContext->PacketsInWindow )){\r
+      DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK,\r
+                "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",\r
+                pPacket->BlockNumber,\r
+                BlockNumber ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Release the ACKed packets\r
+    //\r
+    do {\r
+      //\r
+      //  Remove the packet from the transmit list and window\r
+      //\r
+      pPacket = PacketRemove ( pContext );\r
+\r
+      //\r
+      //  Get the block number of this packet\r
+      //\r
+      AckNumber = pPacket->BlockNumber;\r
+\r
+      //\r
+      //  Increase the size of the transmit window\r
+      //\r
+      if ( PcdGetBool ( Tftp_HighSpeed )\r
+        && ( AckNumber == BlockNumber )) {\r
+        WindowAck ( pTftpServer, pContext, pPacket );\r
+      }\r
+\r
+      //\r
+      //  Free this packet\r
+      //\r
+      PacketFree ( pContext, pPacket );\r
+    } while (( NULL != pContext->pTxHead ) && ( AckNumber != BlockNumber ));\r
+\r
+    //\r
+    //  Fill the window with packets\r
+    //\r
+    pPacket = pContext->pTxHead;\r
+    while (( NULL != pPacket )\r
+      && ( pContext->PacketsInWindow < pContext->WindowSize )\r
+      && ( !bCloseContext )) {\r
+      Status = PacketTx ( pContext, pPacket );\r
+      bCloseContext = (BOOLEAN)( EFI_ERROR ( Status ));\r
+      pPacket = pPacket->pNext;\r
+    }\r
+    \r
+    //\r
+    //  Get more packets ready for transmission\r
+    //\r
+    PacketFill ( pContext );\r
+\r
+    //\r
+    //  Close the context when the last packet is ACKed\r
+    //\r
+    if ( 0 == pContext->PacketsInWindow ) {\r
+      bCloseContext = TRUE;\r
+\r
+      //\r
+      //  Display the bandwidth\r
+      //\r
+      if ( PcdGetBool ( Tftp_Bandwidth )) {\r
+        UINT64 Bandwidth;\r
+        UINT64 DeltaTime;\r
+        UINT64 NanoSeconds;\r
+        UINT32 Value;\r
+\r
+        //\r
+        //  Compute the download time\r
+        //\r
+        DeltaTime = GetPerformanceCounter ( );\r
+        if ( pTftpServer->Time2 > pTftpServer->Time1 ) {\r
+          DeltaTime = DeltaTime - pContext->TimeStart;\r
+        }\r
+        else {\r
+          DeltaTime = pContext->TimeStart - DeltaTime;\r
+        }\r
+        NanoSeconds = GetTimeInNanoSecond ( DeltaTime );\r
+        Bandwidth = pContext->LengthInBytes;\r
+        DEBUG (( DEBUG_WINDOW,\r
+                  "File Length %Ld, Transfer Time: %d.%03d Sec\r\n",\r
+                  Bandwidth,\r
+                  DivU64x32 ( NanoSeconds, 1000 * 1000 * 1000 ),\r
+                  ((UINT32)DivU64x32 ( NanoSeconds, 1000 * 1000 )) % 1000 ));\r
+\r
+        //\r
+        //  Display the round trip time\r
+        //\r
+        Bandwidth = MultU64x32 ( Bandwidth, 8 * 1000 * 1000 );\r
+        Bandwidth /= NanoSeconds;\r
+        if ( 1000 > Bandwidth ) {\r
+          Value = (UINT32)Bandwidth;\r
+          Print ( L"Bandwidth: %d Kbits/Sec\r\n",\r
+                  Value );\r
+        }\r
+        else if (( 1000 * 1000 ) > Bandwidth ) {\r
+          Value = (UINT32)Bandwidth;\r
+          Print ( L"Bandwidth: %d.%03d Mbits/Sec\r\n",\r
+                  Value / 1000,\r
+                  Value % 1000 );\r
+        }\r
+        else {\r
+          Value = (UINT32)DivU64x32 ( Bandwidth, 1000 );\r
+          Print ( L"Bandwidth: %d.%03d Gbits/Sec\r\n",\r
+                  Value / 1000,\r
+                  Value % 1000 );\r
+        }\r
+      }\r
+    }\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT ( );\r
+  return bCloseContext;\r
+}\r
+\r
+\r
+/**\r
+  Get the next TFTP option\r
+\r
+  @param [in] pOption       Address of a zero terminated option string\r
+  @param [in] pEnd          End of buffer address\r
+  @param [in] ppNextOption  Address to receive the address of the next\r
+                            zero terminated option string\r
+\r
+  @retval EFI_SUCCESS   Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+TftpOptionGet (\r
+  IN UINT8 * pOption,\r
+  IN UINT8 * pEnd,\r
+  IN UINT8 ** ppNextOption\r
+  )\r
+{\r
+  UINT8 * pNextOption;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Locate the end of the option\r
+  //\r
+  pNextOption = pOption;\r
+  while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {\r
+    pNextOption += 1;\r
+  }\r
+  if ( pEnd <= pNextOption ) {\r
+    //\r
+    //  Error - end of buffer reached\r
+    //\r
+    DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
+              "ERROR - Option without zero termination received!\r\n" ));\r
+    Status = EFI_INVALID_PARAMETER;\r
+  }\r
+  else {\r
+    //\r
+    //  Zero terminated option found\r
+    //\r
+    pNextOption += 1;\r
+\r
+    //\r
+    //  Display the zero terminated ASCII option string\r
+    //\r
+    DEBUG (( DEBUG_TFTP_REQUEST,\r
+              "Option: %a\r\n",\r
+              pOption ));\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  //  Return the next option address\r
+  //\r
+  *ppNextOption = pNextOption;\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Place an option value into the option acknowledgement\r
+\r
+  @param [in] pOack     Option acknowledgement address\r
+  @param [in] Value     Value to translate into ASCII decimal\r
+\r
+  @return               Option acknowledgement address\r
+\r
+**/\r
+UINT8 *\r
+TftpOptionSet (\r
+  IN UINT8 * pOack,\r
+  IN UINT64 Value\r
+  )\r
+{\r
+  UINT64 NextValue;\r
+\r
+  //\r
+  //  Determine the next value\r
+  //\r
+  NextValue = Value / 10;\r
+\r
+  //\r
+  //  Supress leading zeros\r
   //\r
   if ( 0 != NextValue ) {\r
     pOack = TftpOptionSet ( pOack, NextValue );\r
   //\r
   if ( 0 != NextValue ) {\r
     pOack = TftpOptionSet ( pOack, NextValue );\r
@@ -539,7 +1245,7 @@ TftpOptionSet (
 /**\r
   Process the TFTP request\r
 \r
 /**\r
   Process the TFTP request\r
 \r
-  @param [in] pContext  The context structure address.\r
+  @param [in] pContext  Address of a ::TSDT_CONNECTION_CONTEXT structure\r
   @param [in] pOption   Address of the first zero terminated option string\r
   @param [in] pEnd      End of buffer address\r
 \r
   @param [in] pOption   Address of the first zero terminated option string\r
   @param [in] pEnd      End of buffer address\r
 \r
@@ -553,20 +1259,27 @@ TftpOptions (
 {\r
   UINT8 * pNextOption;\r
   UINT8 * pOack;\r
 {\r
   UINT8 * pNextOption;\r
   UINT8 * pOack;\r
+  TFTP_PACKET * pPacket;\r
   UINT8 * pTemp;\r
   UINT8 * pValue;\r
   EFI_STATUS Status;\r
   INT32 Value;\r
 \r
   UINT8 * pTemp;\r
   UINT8 * pValue;\r
   EFI_STATUS Status;\r
   INT32 Value;\r
 \r
+  //\r
+  //  Get a packet\r
+  //\r
+  pPacket = PacketGet ( pContext );\r
+\r
   //\r
   //  Start the OACK packet\r
   //  Let the OACK handle the parsing errors\r
   //  See http://tools.ietf.org/html/rfc2347\r
   //\r
   //\r
   //  Start the OACK packet\r
   //  Let the OACK handle the parsing errors\r
   //  See http://tools.ietf.org/html/rfc2347\r
   //\r
-  pOack = &pContext->TxBuffer[0];\r
+  pOack = &pPacket->TxBuffer[ 0 ];\r
   *pOack++ = 0;\r
   *pOack++ = TFTP_OP_OACK;\r
   *pOack++ = 0;\r
   *pOack++ = TFTP_OP_OACK;\r
-  pContext->TxBytes = 2;\r
+  pPacket->TxBytes = 2;\r
+  pPacket->BlockNumber = 0;\r
 \r
   //\r
   //  Walk the list of options\r
 \r
   //\r
   //  Walk the list of options\r
@@ -585,7 +1298,7 @@ TftpOptions (
       //  blksize - See http://tools.ietf.org/html/rfc2348\r
       //\r
       pValue = pNextOption;\r
       //  blksize - See http://tools.ietf.org/html/rfc2348\r
       //\r
       pValue = pNextOption;\r
-      if ( 0 == stricmp ((char *)pOption, "blksize" )) {\r
+      if ( 0 == strcasecmp ((char *)pOption, "blksize" )) {\r
         //\r
         //  Get the value\r
         //\r
         //\r
         //  Get the value\r
         //\r
@@ -625,7 +1338,7 @@ TftpOptions (
             *pOack++ = 0;\r
             pOack = TftpOptionSet ( pOack, pContext->BlockSize );\r
             *pOack++ = 0;\r
             *pOack++ = 0;\r
             pOack = TftpOptionSet ( pOack, pContext->BlockSize );\r
             *pOack++ = 0;\r
-            pContext->TxBytes += pOack - pTemp;\r
+            pPacket->TxBytes += pOack - pTemp;\r
           }\r
         }\r
       }\r
           }\r
         }\r
       }\r
@@ -633,7 +1346,7 @@ TftpOptions (
       //\r
       //  timeout - See http://tools.ietf.org/html/rfc2349\r
       //\r
       //\r
       //  timeout - See http://tools.ietf.org/html/rfc2349\r
       //\r
-      else if ( 0 == stricmp ((char *)pOption, "timeout" )) {\r
+      else if ( 0 == strcasecmp ((char *)pOption, "timeout" )) {\r
         //\r
         //  Get the value\r
         //\r
         //\r
         //  Get the value\r
         //\r
@@ -644,10 +1357,10 @@ TftpOptions (
             //\r
             //  Set the timeout value\r
             //\r
             //\r
             //  Set the timeout value\r
             //\r
-            pContext->Timeout = Value;\r
+            pContext->MaxTimeout = Value;\r
             DEBUG (( DEBUG_TFTP_REQUEST,\r
                       "Using timeout of %d seconds\r\n",\r
             DEBUG (( DEBUG_TFTP_REQUEST,\r
                       "Using timeout of %d seconds\r\n",\r
-                      pContext->Timeout ));\r
+                      pContext->MaxTimeout ));\r
 \r
             //\r
             //  Update the OACK\r
 \r
             //\r
             //  Update the OACK\r
@@ -661,9 +1374,9 @@ TftpOptions (
             *pOack++ = 'u';\r
             *pOack++ = 't';\r
             *pOack++ = 0;\r
             *pOack++ = 'u';\r
             *pOack++ = 't';\r
             *pOack++ = 0;\r
-            pOack = TftpOptionSet ( pOack, pContext->Timeout );\r
+            pOack = TftpOptionSet ( pOack, pContext->MaxTimeout );\r
             *pOack++ = 0;\r
             *pOack++ = 0;\r
-            pContext->TxBytes += pOack - pTemp;\r
+            pPacket->TxBytes += pOack - pTemp;\r
           }\r
         }\r
       }\r
           }\r
         }\r
       }\r
@@ -671,7 +1384,7 @@ TftpOptions (
       //\r
       //  tsize - See http://tools.ietf.org/html/rfc2349\r
       //\r
       //\r
       //  tsize - See http://tools.ietf.org/html/rfc2349\r
       //\r
-      else if ( 0 == stricmp ((char *)pOption, "tsize" )) {\r
+      else if ( 0 == strcasecmp ((char *)pOption, "tsize" )) {\r
         //\r
         //  Get the value\r
         //\r
         //\r
         //  Get the value\r
         //\r
@@ -698,7 +1411,7 @@ TftpOptions (
             *pOack++ = 0;\r
             pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );\r
             *pOack++ = 0;\r
             *pOack++ = 0;\r
             pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );\r
             *pOack++ = 0;\r
-            pContext->TxBytes += pOack - pTemp;\r
+            pPacket->TxBytes += pOack - pTemp;\r
           }\r
         }\r
       }\r
           }\r
         }\r
       }\r
@@ -717,6 +1430,16 @@ TftpOptions (
     //\r
     pOption = pNextOption;\r
   } while ( pEnd > pOption );\r
     //\r
     pOption = pNextOption;\r
   } while ( pEnd > pOption );\r
+\r
+  //\r
+  //  Transmit the OACK if necessary\r
+  //\r
+  if ( 2 < pPacket->TxBytes ) {\r
+    PacketQueue ( pContext, pPacket );\r
+  }\r
+  else {\r
+    PacketFree ( pContext, pPacket );\r
+  }\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -781,69 +1504,91 @@ TftpOptionValue (
 /**\r
   Process the TFTP request\r
 \r
 /**\r
   Process the TFTP request\r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    Connection context structure address\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] SocketFd    Socket file descriptor\r
 \r
 **/\r
 VOID\r
 TftpProcessRequest (\r
   IN TSDT_TFTP_SERVER * pTftpServer,\r
 \r
 **/\r
 VOID\r
 TftpProcessRequest (\r
   IN TSDT_TFTP_SERVER * pTftpServer,\r
-  IN TSDT_CONNECTION_CONTEXT * pContext\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN int SocketFd\r
   )\r
 {\r
   BOOLEAN bCloseContext;\r
   )\r
 {\r
   BOOLEAN bCloseContext;\r
-  BOOLEAN bIgnorePacket;\r
-  UINT16 BlockNumber;\r
   UINT16 Opcode;\r
   UINT16 Opcode;\r
-  UINT8 * pBuffer;\r
-  UINT8 * pEnd;\r
-  UINT8 * pFileName;\r
-  UINT8 * pMode;\r
-  UINT8 * pOption;\r
-  EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
   //  Get the opcode\r
   //\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
   //  Get the opcode\r
   //\r
-  pBuffer = &pTftpServer->RxBuffer[0];\r
-  Opcode = HTONS ( *(UINT16 *)&pBuffer[0]);\r
-Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode );\r
+  Opcode = HTONS ( *(UINT16 *)&pTftpServer->RxBuffer[ 0 ]);\r
+  DEBUG (( DEBUG_TFTP_REQUEST,\r
+            "TFTP Opcode: 0x%08x\r\n",\r
+            Opcode ));\r
 \r
   //\r
   //  Validate the parameters\r
   //\r
   bCloseContext = FALSE;\r
 \r
   //\r
   //  Validate the parameters\r
   //\r
   bCloseContext = FALSE;\r
-  bIgnorePacket = FALSE;\r
   switch ( Opcode ) {\r
   default:\r
     DEBUG (( DEBUG_TFTP_REQUEST,\r
               "ERROR - Unknown TFTP opcode: %d\r\n",\r
               Opcode ));\r
   switch ( Opcode ) {\r
   default:\r
     DEBUG (( DEBUG_TFTP_REQUEST,\r
               "ERROR - Unknown TFTP opcode: %d\r\n",\r
               Opcode ));\r
-    bIgnorePacket = TRUE;\r
+    break;\r
+\r
+  case TFTP_OP_ACK:\r
+    bCloseContext = TftpAck ( pTftpServer, pContext );\r
     break;\r
 \r
   case TFTP_OP_READ_REQUEST:\r
     break;\r
 \r
   case TFTP_OP_READ_REQUEST:\r
+    bCloseContext = TftpRead ( pTftpServer, pContext, SocketFd );\r
     break;\r
 \r
     break;\r
 \r
+\r
+\r
+  \r
   case TFTP_OP_DATA:\r
     if ( NULL == pContext ) {\r
   case TFTP_OP_DATA:\r
     if ( NULL == pContext ) {\r
-      DEBUG (( DEBUG_ERROR,\r
-                "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
-                (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),\r
-                htons ( pTftpServer->RemoteAddress.sin_port )));\r
-      bIgnorePacket = TRUE;\r
+      if ( AF_INET == pTftpServer->RemoteAddress.v4.sin_family ) {\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
+                  (UINT8)pTftpServer->RemoteAddress.v4.sin_addr.s_addr,\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 8 ),\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 16 ),\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 24 ),\r
+                  htons ( pTftpServer->RemoteAddress.v4.sin_port )));\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - File not open for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                  htons ( pTftpServer->RemoteAddress.v6.sin6_port )));\r
+      }\r
       break;\r
     }\r
       break;\r
     }\r
-    if ( pContext->bExpectAck ) {\r
+    if ( 0 != pContext->PacketsInWindow ) {\r
       DEBUG (( DEBUG_ERROR,\r
                 "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",\r
                 pContext ));\r
       DEBUG (( DEBUG_ERROR,\r
                 "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",\r
                 pContext ));\r
-      bIgnorePacket = TRUE;\r
       break;\r
     }\r
     if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 )) {\r
       break;\r
     }\r
     if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 )) {\r
@@ -852,229 +1597,44 @@ Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode );
                 pTftpServer->RxBytes - 2 - 2,\r
                 pContext->BlockSize,\r
                 pContext ));\r
                 pTftpServer->RxBytes - 2 - 2,\r
                 pContext->BlockSize,\r
                 pContext ));\r
-      bIgnorePacket = TRUE;\r
-      break;\r
-    }\r
-    break;\r
-\r
-  case TFTP_OP_ACK:\r
-    if ( NULL == pContext ) {\r
-      DEBUG (( DEBUG_ERROR,\r
-                "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
-                (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),\r
-                htons ( pTftpServer->RemoteAddress.sin_port )));\r
-      bIgnorePacket = TRUE;\r
-    }\r
-    if ( !pContext->bExpectAck ) {\r
-      DEBUG (( DEBUG_ERROR,\r
-                "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",\r
-                pContext ));\r
-      bIgnorePacket = TRUE;\r
       break;\r
     }\r
     break;\r
 \r
   case TFTP_OP_ERROR:\r
     if ( NULL == pContext ) {\r
       break;\r
     }\r
     break;\r
 \r
   case TFTP_OP_ERROR:\r
     if ( NULL == pContext ) {\r
-      DEBUG (( DEBUG_ERROR,\r
-                "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
-                (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),\r
-                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),\r
-                htons ( pTftpServer->RemoteAddress.sin_port )));\r
-      bIgnorePacket = TRUE;\r
-    }\r
-    break;\r
-  }\r
-  if ( !bIgnorePacket ) {\r
-    //\r
-    //  Process the request\r
-    //\r
-    switch ( Opcode ) {\r
-    default:\r
-      DEBUG (( DEBUG_TFTP_REQUEST,\r
-                "ERROR - Unable to process TFTP opcode: %d\r\n",\r
-                Opcode ));\r
-      break;\r
-\r
-    case TFTP_OP_READ_REQUEST:\r
-\r
-      //\r
-      //  Close the context if necessary\r
-      //\r
-      if ( NULL != pContext ) {\r
-        ContextRemove ( pTftpServer, pContext );\r
-      }\r
-\r
-      //\r
-      //  Create the connection context\r
-      //\r
-      pContext = ContextAdd ( pTftpServer );\r
-      if ( NULL == pContext ) {\r
-        break;\r
-      }\r
-\r
-      //\r
-      //  Locate the mode\r
-      //\r
-      pFileName = &pBuffer[2];\r
-      pEnd = &pBuffer[pTftpServer->RxBytes];\r
-      pMode = pFileName;\r
-      while (( pEnd > pMode ) && ( 0 != *pMode )) {\r
-        pMode += 1;\r
-      }\r
-      if ( pEnd <= pMode ) {\r
-        //\r
-        //  Mode not found\r
-        //\r
-        DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
-                  "ERROR - File mode not found\r\n" ));\r
-        //\r
-        //  Tell the client of the error\r
-        //\r
-        TftpSendError ( pTftpServer,\r
-                        pContext,\r
-                        0,\r
-                        (UINT8 *)"File open mode not found" );\r
-        break;\r
-      }\r
-      pMode += 1;\r
-      DEBUG (( DEBUG_TFTP_REQUEST,\r
-                "TFTP - FileName: %a\n",\r
-                pFileName ));\r
-\r
-      //\r
-      //  Locate the options\r
-      //\r
-      pOption = pMode;\r
-      while (( pEnd > pOption ) && ( 0 != *pOption )) {\r
-        pOption += 1;\r
-      }\r
-      if ( pEnd <= pOption ) {\r
-        //\r
-        //  End of mode not found\r
-        //\r
-        DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
-                  "ERROR - File mode not valid\r\n" ));\r
-        //\r
-        //  Tell the client of the error\r
-        //\r
-        TftpSendError ( pTftpServer,\r
-                        pContext,\r
-                        0,\r
-                        (UINT8 *)"File open mode not valid" );\r
-        break;\r
-      }\r
-      pOption += 1;\r
-      DEBUG (( DEBUG_TFTP_REQUEST,\r
-                "TFTP - Mode: %a\r\n",\r
-                pMode ));\r
-\r
-      //\r
-      //  Verify the mode is supported\r
-      //\r
-      if ( 0 != stricmp ((char *)pMode, "octet" )) {\r
-        //\r
-        //  File access mode not supported\r
-        //\r
-        DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
-                  "ERROR - File mode %a not supported\r\n",\r
-                  pMode ));\r
-\r
-        //\r
-        //  Tell the client of the error\r
-        //\r
-        TftpSendError ( pTftpServer,\r
-                        pContext,\r
-                        0,\r
-                        (UINT8 *)"File open mode not supported" );\r
-        break;\r
-      }\r
-\r
-      //\r
-      //  Open the file, close the context on error\r
-      //\r
-// TODO: Remove the following line\r
-pContext->File = (EFI_HANDLE)1;\r
-\r
-      //\r
-      //  Determine the file length\r
-      //\r
-//fstat\r
-\r
-      //\r
-      //  Process the options\r
-      //\r
-      TftpOptions ( pContext, pOption, pEnd );\r
-\r
-      //\r
-      //  Read in the first portion of the file\r
-      //\r
-\r
-      //\r
-      //  Send the first block\r
-      //\r
-      pContext->bExpectAck = TRUE;\r
-      if ( 2 < pContext->TxBytes ) {\r
-        //\r
-        //  Send the OACK\r
-        //\r
-        Status = TftpTxPacket ( pTftpServer, pContext );\r
+      if ( AF_INET == pTftpServer->RemoteAddress.v4.sin_family ) {\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
+                  (UINT8)pTftpServer->RemoteAddress.v4.sin_addr.s_addr,\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 8 ),\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 16 ),\r
+                  (UINT8)( pTftpServer->RemoteAddress.v4.sin_addr.s_addr >> 24 ),\r
+                  htons ( pTftpServer->RemoteAddress.v4.sin_port )));\r
       }\r
       else {\r
       }\r
       else {\r
-        //\r
-        //  Send the first block of data\r
-        //\r
-        Status = TftpSendNextBlock ( pTftpServer, pContext );\r
-      }\r
-      break;\r
-\r
-    case TFTP_OP_ACK:\r
-      //\r
-      //  Get the block number that is being ACKed\r
-      //\r
-      BlockNumber = pTftpServer->RxBuffer[2];\r
-      BlockNumber <<= 8;\r
-      BlockNumber |= pTftpServer->RxBuffer[3];\r
-\r
-      //\r
-      //  Determine if this is the correct ACK\r
-      //\r
-      DEBUG (( DEBUG_TFTP_ACK,\r
-                "ACK for block 0x%04x received\r\n",\r
-                BlockNumber ));\r
-      if (( !pContext->bExpectAck )\r
-        || ( BlockNumber != pContext->AckNext )) {\r
-        DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK,\r
-                  "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",\r
-                  pContext->AckNext,\r
-                  BlockNumber ));\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - File not open for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 0 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 1 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 2 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 3 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 4 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 5 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 6 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 7 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 8 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 9 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 10 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 11 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 12 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 13 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 14 ],\r
+                  pTftpServer->RemoteAddress.v6.sin6_addr.__u6_addr.__u6_addr8[ 15 ],\r
+                  htons ( pTftpServer->RemoteAddress.v6.sin6_port )));\r
       }\r
       }\r
-      else {\r
-        //\r
-        //  Process the expected ACK\r
-        //\r
-        if ( pContext->bEofSent ) {\r
-          bCloseContext = TRUE;\r
-        }\r
-        else {\r
-          //\r
-          //  Set the next expected ACK\r
-          //\r
-          pContext->AckNext += 1;\r
-\r
-          //\r
-          //  Send the next packet of data\r
-          //\r
-          Status = TftpSendNextBlock ( pTftpServer, pContext );\r
-        }\r
-      }\r
-      break;\r
     }\r
     }\r
+    break;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -1089,119 +1649,229 @@ pContext->File = (EFI_HANDLE)1;
 \r
 \r
 /**\r
 \r
 \r
 /**\r
-  Build and send an error packet\r
+  Process the read request\r
 \r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    The context structure address.\r
-  @param [in] Error       Error number for the packet\r
-  @param [in] pError      Zero terminated error string address\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] SocketFd    Socket file descriptor\r
 \r
 \r
-  @retval EFI_SUCCESS     Message processed successfully\r
+  @retval TRUE if the context should be closed\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpSendError (\r
+BOOLEAN\r
+TftpRead (\r
   IN TSDT_TFTP_SERVER * pTftpServer,\r
   IN TSDT_CONNECTION_CONTEXT * pContext,\r
   IN TSDT_TFTP_SERVER * pTftpServer,\r
   IN TSDT_CONNECTION_CONTEXT * pContext,\r
-  IN UINT16 Error,\r
-  IN UINT8 * pError\r
+  IN int SocketFd\r
   )\r
 {\r
   )\r
 {\r
-  UINT8 Character;\r
+  BOOLEAN bCloseContext;\r
+  struct stat FileStatus;\r
   UINT8 * pBuffer;\r
   UINT8 * pBuffer;\r
-  EFI_STATUS Status;\r
+  UINT8 * pEnd;\r
+  UINT8 * pFileName;\r
+  UINT8 * pMode;\r
+  UINT8 * pOption;\r
+  CHAR8 * pReadMode;\r
+  UINT64 TimeStart;\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
 \r
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Build the error packet\r
+  //  Log the receive time\r
   //\r
   //\r
-  pBuffer = &pContext->TxBuffer[0];\r
-  pBuffer[0] = 0;\r
-  pBuffer[1] = TFTP_OP_ERROR;\r
-  pBuffer[2] = (UINT8)( Error >> 8 );\r
-  pBuffer[3] = (UINT8)Error;\r
+  TimeStart = 0;\r
+  if ( PcdGetBool ( Tftp_Bandwidth )) {\r
+    TimeStart = GetPerformanceCounter ( );\r
+  }\r
 \r
   //\r
 \r
   //\r
-  //  Copy the zero terminated string into the buffer\r
+  //  Close the context if necessary\r
   //\r
   //\r
-  pBuffer += 4;\r
-  do {\r
-    Character = *pError++;\r
-    *pBuffer++ = Character;\r
-  } while ( 0 != Character );\r
+  bCloseContext = FALSE;\r
+  if ( NULL != pContext ) {\r
+    ContextRemove ( pTftpServer, pContext );\r
+  }\r
 \r
   //\r
 \r
   //\r
-  //  Send the error message\r
+  //  Use break instead of goto\r
   //\r
   //\r
-  pContext->TxBytes = pBuffer - &pContext->TxBuffer[0];\r
-  Status = TftpTxPacket ( pTftpServer, pContext );\r
+  for ( ; ; ) {\r
+    //\r
+    //  Create the connection context\r
+    //\r
+    pContext = ContextAdd ( pTftpServer, SocketFd );\r
+    if ( NULL == pContext ) {\r
+      break;\r
+    }\r
 \r
 \r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
+    //\r
+    //  Set the start time\r
+    //\r
+    if ( PcdGetBool ( Tftp_Bandwidth )) {\r
+      pContext->TimeStart = TimeStart;\r
+    }\r
 \r
 \r
+    //\r
+    //  Locate the mode\r
+    //\r
+    pBuffer = &pTftpServer->RxBuffer[ 0 ];\r
+    pEnd = &pBuffer[ pTftpServer->RxBytes ];\r
+    pFileName = &pBuffer[ 2 ];\r
+    pMode = pFileName;\r
+    while (( pEnd > pMode ) && ( 0 != *pMode )) {\r
+      pMode += 1;\r
+    }\r
+    if ( pEnd <= pMode ) {\r
+      //\r
+      //  Mode not found\r
+      //\r
+      DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
+                "ERROR - File mode not found\r\n" ));\r
+      //\r
+      //  Tell the client of the error\r
+      //\r
+      SendError ( pContext,\r
+                  TFTP_ERROR_SEE_MSG,\r
+                  (UINT8 *)"File open mode not found" );\r
+      break;\r
+    }\r
+    pMode += 1;\r
+    DEBUG (( DEBUG_TFTP_REQUEST,\r
+              "TFTP - FileName: %a\r\n",\r
+              pFileName ));\r
 \r
 \r
-/**\r
-  Send the next block of file system data\r
+    //\r
+    //  Locate the options\r
+    //\r
+    pOption = pMode;\r
+    while (( pEnd > pOption ) && ( 0 != *pOption )) {\r
+      pOption += 1;\r
+    }\r
+    if ( pEnd <= pOption ) {\r
+      //\r
+      //  End of mode not found\r
+      //\r
+      DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
+                "ERROR - File mode not valid\r\n" ));\r
+      //\r
+      //  Tell the client of the error\r
+      //\r
+      SendError ( pContext,\r
+                  TFTP_ERROR_SEE_MSG,\r
+                  (UINT8 *)"File open mode not valid" );\r
+      break;\r
+    }\r
+    pOption += 1;\r
+    DEBUG (( DEBUG_TFTP_REQUEST,\r
+              "TFTP - Mode: %a\r\n",\r
+              pMode ));\r
 \r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    The context structure address.\r
+    //\r
+    //  Verify the mode is supported\r
+    //\r
+    pReadMode = "r";\r
+    if ( 0 == strcasecmp ((char *)pMode, "octet" )) {\r
+      //\r
+      //  Read the file as binary input\r
+      //\r
+      pReadMode = "rb";\r
+    }\r
 \r
 \r
-  @retval EFI_SUCCESS   Message processed successfully\r
+    //\r
+    //  Determine the file length\r
+    //\r
+    pContext->File = fopen ( pFileName, pReadMode );\r
+    if (( NULL == pContext->File )\r
+        || ( -1 == stat ( pFileName, &FileStatus ))) {\r
+      //\r
+      //  File not found\r
+      //\r
+      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
+                ( NULL == pContext->File )\r
+                ? "ERROR - File not found!\r\n"\r
+                : "ERROR - Unable to determine file %a size!\r\n",\r
+                pFileName ));\r
 \r
 \r
-**/\r
-EFI_STATUS\r
-TftpSendNextBlock (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
-  IN TSDT_CONNECTION_CONTEXT * pContext\r
-  )\r
-{\r
-  ssize_t LengthInBytes;\r
-  UINT8 * pBuffer;\r
-  EFI_STATUS Status;\r
+      //\r
+      //  Tell the client of the error\r
+      //\r
+      SendError ( pContext,\r
+                  TFTP_ERROR_NOT_FOUND,\r
+                  (UINT8 *)"File not found" );\r
+      break;\r
+    }\r
+    pContext->LengthInBytes = FileStatus.st_size;\r
+    pContext->BytesRemaining = pContext->LengthInBytes;\r
+    pContext->BytesToSend = pContext->LengthInBytes;\r
 \r
 \r
-  //\r
-  //  Determine how much data needs to be sent\r
-  //\r
-  LengthInBytes = pContext->BlockSize;\r
-  if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE )\r
-    || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) {\r
-    LengthInBytes = (ssize_t)pContext->LengthInBytes;\r
-    pContext->bEofSent = TRUE;\r
-  }\r
+    //\r
+    //  Display the file size\r
+    //\r
+    DEBUG_CODE_BEGIN ( );\r
+    UINT32 Value;\r
+\r
+    if ( 1024 > pContext->LengthInBytes ) {\r
+      Value = (UINT32)pContext->LengthInBytes;\r
+      DEBUG (( DEBUG_FILE_BUFFER,\r
+                "%a size: %d Bytes\r\n",\r
+                pFileName,\r
+                Value ));\r
+    }\r
+    else if (( 1024 * 1024 ) > pContext->LengthInBytes ) {\r
+      Value = (UINT32)pContext->LengthInBytes;\r
+      DEBUG (( DEBUG_FILE_BUFFER,\r
+                "%a size: %d.%03d KiBytes (%Ld Bytes)\r\n",\r
+                pFileName,\r
+                Value / 1024,\r
+                (( Value % 1024 ) * 1000 ) / 1024,\r
+                pContext->LengthInBytes ));\r
+    }\r
+    else if (( 1024 * 1024 * 1024 ) > pContext->LengthInBytes ) {\r
+      Value = (UINT32)DivU64x32 ( pContext->LengthInBytes, 1024 );\r
+      DEBUG (( DEBUG_FILE_BUFFER,\r
+                "%a size: %d.%03d MiBytes (%Ld Bytes)\r\n",\r
+                pFileName,\r
+                Value / 1024,\r
+                (( Value % 1024 ) * 1000 ) / 1024,\r
+                pContext->LengthInBytes ));\r
+    }\r
+    else {\r
+      Value = (UINT32)DivU64x32 ( pContext->LengthInBytes, 1024 * 1024 );\r
+      DEBUG (( DEBUG_FILE_BUFFER,\r
+                "%a size: %d.%03d GiBytes (%Ld Bytes)\r\n",\r
+                pFileName,\r
+                Value / 1024,\r
+                (( Value % 1024 ) * 1000 ) / 1024,\r
+                pContext->LengthInBytes ));\r
+    }\r
+    DEBUG_CODE_END ( );\r
 \r
 \r
-  //\r
-  //  Set the TFTP opcode and block number\r
-  //\r
-  pBuffer = &pContext->TxBuffer[0];\r
-  *pBuffer++ = 0;\r
-  *pBuffer++ = TFTP_OP_DATA;\r
-  *pBuffer++ = (UINT8)( pContext->AckNext >> 8 );\r
-  *pBuffer++ = (UINT8)pContext->AckNext;\r
+    //\r
+    //  Process the options\r
+    //\r
+    if ( pEnd > pOption ) {\r
+      TftpOptions ( pContext, pOption, pEnd );\r
+    }\r
+    else {\r
+      //\r
+      //  Skip the open ACK\r
+      //\r
+      pContext->BlockNumber = 1;\r
+    }\r
 \r
 \r
-  //\r
-  //  Copy the file data into the transmit buffer\r
-  //\r
-  pContext->TxBytes = 2 + 2 + LengthInBytes;\r
-  if ( 0 < LengthInBytes ) {\r
-    CopyMem ( &pBuffer,\r
-              pContext->pBuffer,\r
-              LengthInBytes );\r
+    //\r
+    //  Send the first packet (OACK or data block)\r
+    //\r
+    bCloseContext = PacketFill ( pContext );\r
+    break;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  //  Send the next block\r
-  //\r
-  Status = TftpTxPacket ( pTftpServer, pContext );\r
-\r
-  //\r
-  //  Return the operation status\r
+  //  Return the close status\r
   //\r
   //\r
-  return Status;\r
+  DBG_EXIT ( );\r
+  return bCloseContext;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -1213,241 +1883,314 @@ TftpSendNextBlock (
   some time to get the IP address and initialize the upper layers of\r
   the network stack.\r
 \r
   some time to get the IP address and initialize the upper layers of\r
   the network stack.\r
 \r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  @param [in] pTftpServer   Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] AddressFamily The address family to use for the conection.\r
+  @param [in] pIndex        Address of the index into the port array\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
-TftpServerTimer (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+TftpServerSocket (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN sa_family_t AddressFamily,\r
+  IN int * pIndex\r
   )\r
 {\r
   )\r
 {\r
-  UINT16 TftpPort;\r
   int SocketStatus;\r
   int SocketStatus;\r
-  EFI_STATUS Status;\r
+  struct pollfd * pTftpPort;\r
+  UINT16 TftpPort;\r
+  union {\r
+    struct sockaddr_in v4;\r
+    struct sockaddr_in6 v6;\r
+  } TftpServerAddress;\r
 \r
 \r
-  DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" ));\r
+  DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerListen\r\n" ));\r
 \r
   //\r
 \r
   //\r
-  //  Open the TFTP port on the server\r
+  //  Determine if the socket is already initialized\r
   //\r
   //\r
-  do {\r
-    do {\r
-      //\r
-      //  Wait for a while\r
-      //\r
-      Status = gBS->CheckEvent ( pTftpServer->TimerEvent );\r
-    } while ( EFI_SUCCESS != Status );\r
-\r
+  if ( -1 == *pIndex ) {\r
     //\r
     //  Attempt to create the socket for the TFTP server\r
     //\r
     //\r
     //  Attempt to create the socket for the TFTP server\r
     //\r
-    pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP;\r
-    pTftpServer->TftpPort.revents = 0;\r
-    pTftpServer->TftpPort.fd = socket ( AF_INET,\r
-                                        SOCK_DGRAM,\r
-                                        IPPROTO_UDP );\r
-    if ( -1 != pTftpServer->TftpPort.fd ) {\r
+    pTftpPort = &pTftpServer->TftpPort[ pTftpServer->Entries ];\r
+    pTftpPort->fd = socket ( AddressFamily,\r
+                             SOCK_DGRAM,\r
+                             IPPROTO_UDP );\r
+    if ( -1 != pTftpPort->fd ) {\r
+      //\r
+      //  Initialize the poll structure\r
+      //\r
+      pTftpPort->events = POLLRDNORM | POLLHUP;\r
+      pTftpPort->revents = 0;\r
+\r
       //\r
       //  Set the socket address\r
       //\r
       //\r
       //  Set the socket address\r
       //\r
-      ZeroMem ( &pTftpServer->TftpServerAddress,\r
-                sizeof ( pTftpServer->TftpServerAddress ));\r
       TftpPort = 69;\r
       TftpPort = 69;\r
-      DEBUG (( DEBUG_TFTP_PORT,\r
-                "TFTP Port: %d\r\n",\r
-                TftpPort ));\r
-      pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress );\r
-      pTftpServer->TftpServerAddress.sin_family = AF_INET;\r
-      pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY;\r
-      pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort );\r
+      ZeroMem ( &TftpServerAddress, sizeof ( TftpServerAddress ));\r
+      TftpServerAddress.v4.sin_port = htons ( TftpPort );\r
+      if ( AF_INET == AddressFamily ) {\r
+        TftpServerAddress.v4.sin_len = sizeof ( TftpServerAddress.v4 );\r
+        TftpServerAddress.v4.sin_family = AF_INET;\r
+      }\r
+      else {\r
+        TftpServerAddress.v6.sin6_len = sizeof ( TftpServerAddress.v6 );\r
+        TftpServerAddress.v6.sin6_family = AF_INET6;\r
+      }\r
 \r
       //\r
       //  Bind the socket to the TFTP port\r
       //\r
 \r
       //\r
       //  Bind the socket to the TFTP port\r
       //\r
-      SocketStatus = bind ( pTftpServer->TftpPort.fd,\r
-                            (struct sockaddr *) &pTftpServer->TftpServerAddress,\r
-                            pTftpServer->TftpServerAddress.sin_len );\r
+      SocketStatus = bind ( pTftpPort->fd,\r
+                            (struct sockaddr *) &TftpServerAddress,\r
+                            TftpServerAddress.v6.sin6_len );\r
       if ( -1 != SocketStatus ) {\r
         DEBUG (( DEBUG_TFTP_PORT,\r
                   "0x%08x: Socket bound to port %d\r\n",\r
       if ( -1 != SocketStatus ) {\r
         DEBUG (( DEBUG_TFTP_PORT,\r
                   "0x%08x: Socket bound to port %d\r\n",\r
-                  pTftpServer->TftpPort.fd,\r
+                  pTftpPort->fd,\r
                   TftpPort ));\r
                   TftpPort ));\r
+\r
+        //\r
+        //  Account for this connection\r
+        //\r
+        *pIndex = pTftpServer->Entries;\r
+        pTftpServer->Entries += 1;\r
+        ASSERT ( DIM ( pTftpServer->TftpPort ) >= pTftpServer->Entries );\r
       }\r
 \r
       //\r
       //  Release the socket if necessary\r
       //\r
       if ( -1 == SocketStatus ) {\r
       }\r
 \r
       //\r
       //  Release the socket if necessary\r
       //\r
       if ( -1 == SocketStatus ) {\r
-        close ( pTftpServer->TftpPort.fd );\r
-        pTftpServer->TftpPort.fd = -1;\r
+        close ( pTftpPort->fd );\r
+        pTftpPort->fd = -1;\r
       }\r
     }\r
       }\r
     }\r
+  }\r
 \r
 \r
-    //\r
-    //  Wait until the socket is open\r
-    //\r
-  }while ( -1 == pTftpServer->TftpPort.fd );\r
-\r
-  DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" ));\r
+  DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerListen\r\n" ));\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Start the TFTP server port creation timer\r
+  Update the window due to the ACK\r
 \r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-\r
-  @retval EFI_SUCCESS         The timer was successfully started.\r
-  @retval EFI_ALREADY_STARTED The timer is already running.\r
-  @retval Other               The timer failed to start.\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpServerTimerStart (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+VOID\r
+WindowAck (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
   )\r
 {\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  UINT64 TriggerTime;\r
+  if ( PcdGetBool ( Tftp_HighSpeed )) {\r
+    UINT64 DeltaTime;\r
+    UINT64 NanoSeconds;\r
 \r
 \r
-  DBG_ENTER ( );\r
+    DBG_ENTER ( );\r
 \r
 \r
-  //\r
-  //  Assume the timer is already running\r
-  //\r
-  Status = EFI_ALREADY_STARTED;\r
-  if ( !pTftpServer->bTimerRunning ) {\r
     //\r
     //\r
-    //  Compute the poll interval\r
+    //  Compute the round trip time\r
     //\r
     //\r
-    TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );\r
-    Status = gBS->SetTimer ( pTftpServer->TimerEvent,\r
-                             TimerPeriodic,\r
-                             TriggerTime );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));\r
-\r
-      //\r
-      //  Mark the timer running\r
-      //\r
-      pTftpServer->bTimerRunning = TRUE;\r
+    if ( pTftpServer->Time2 > pTftpServer->Time1 ) {\r
+      DeltaTime = pTftpServer->RxTime - pPacket->TxTime;\r
     }\r
     else {\r
     }\r
     else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,\r
-                "ERROR - Failed to start TFTP port timer, Status: %r\r\n",\r
-                Status ));\r
+      DeltaTime = pPacket->TxTime - pTftpServer->RxTime;\r
     }\r
     }\r
-  }\r
 \r
 \r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
+    //\r
+    //  Adjust the round trip time\r
+    //\r
+    NanoSeconds = GetTimeInNanoSecond ( DeltaTime );\r
+    DeltaTime = RShiftU64 ( pContext->Rtt2x, ACK_SHIFT );\r
+    pContext->Rtt2x += NanoSeconds + NanoSeconds - DeltaTime;\r
+    if ( pContext->Rtt2x > pContext->MaxTimeout ) {\r
+      pContext->Rtt2x = pContext->MaxTimeout;\r
+    }\r
+\r
+    //\r
+    //  Account for the ACK\r
+    //\r
+    if ( pContext->WindowSize < MAX_PACKETS ) {\r
+      pContext->AckCount -= 1;\r
+      if ( 0 == pContext->AckCount ) {\r
+        //\r
+        //  Increase the window\r
+        //\r
+        pContext->WindowSize += 1;\r
+\r
+        //\r
+        //  Set the ACK count\r
+        //\r
+        if ( pContext->WindowSize < pContext->Threshold ) {\r
+          pContext->AckCount = pContext->WindowSize * PcdGet32 ( Tftp_AckMultiplier );\r
+        }\r
+        else {\r
+          pContext->AckCount = PcdGet32 ( Tftp_AckLogBase ) << pContext->WindowSize;\r
+        }\r
+\r
+        //\r
+        //  Display the round trip time\r
+        //\r
+        DEBUG_CODE_BEGIN ( );\r
+        UINT32 Value;\r
+        \r
+        DeltaTime = RShiftU64 ( pContext->Rtt2x, 1 );\r
+        if ( 1000 > DeltaTime ) {\r
+          DEBUG (( DEBUG_WINDOW,\r
+                    "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %Ld nSec\r\n",\r
+                    pContext->WindowSize,\r
+                    pContext->Threshold,\r
+                    pContext->AckCount,\r
+                    DeltaTime ));\r
+        }\r
+        else if (( 1000 * 1000 ) > DeltaTime ) {\r
+          Value = (UINT32)DeltaTime;\r
+          DEBUG (( DEBUG_WINDOW,\r
+                    "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %d.%03d uSec\r\n",\r
+                    pContext->WindowSize,\r
+                    pContext->Threshold,\r
+                    pContext->AckCount,\r
+                    Value / 1000,\r
+                    Value % 1000 ));\r
+        }\r
+        else if (( 1000 * 1000 * 1000 ) > DeltaTime ) {\r
+          Value = (UINT32)DivU64x32 ( DeltaTime, 1000 );\r
+          DEBUG (( DEBUG_WINDOW,\r
+                    "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %d.%03d mSec\r\n",\r
+                    pContext->WindowSize,\r
+                    pContext->Threshold,\r
+                    pContext->AckCount,\r
+                    Value / 1000,\r
+                    Value % 1000 ));\r
+        }\r
+        else {\r
+          Value = (UINT32)DivU64x32 ( DeltaTime, 1000 * 1000 );\r
+          DEBUG (( DEBUG_WINDOW,\r
+                    "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %d.%03d Sec\r\n",\r
+                    pContext->WindowSize,\r
+                    pContext->Threshold,\r
+                    pContext->AckCount,\r
+                    Value / 1000,\r
+                    Value % 1000 ));\r
+        }\r
+        DEBUG_CODE_END ( );\r
+      }\r
+    }\r
+\r
+    DBG_EXIT ( );\r
+  }\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Stop the TFTP server port creation timer\r
-\r
-  @param [in] pTftpServer The TFTP server control structure address.\r
+  A timeout has occurred, close the window\r
 \r
 \r
-  @retval EFI_SUCCESS   The TFTP port timer is stopped\r
-  @retval Other         Failed to stop the TFTP port timer\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpServerTimerStop (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+VOID\r
+WindowTimeout (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
   )\r
 {\r
   )\r
 {\r
-  EFI_STATUS Status;\r
+  if ( PcdGetBool ( Tftp_HighSpeed )) {\r
+    TFTP_PACKET * pPacket;\r
 \r
 \r
-  DBG_ENTER ( );\r
+    DBG_ENTER ( );\r
 \r
 \r
-  //\r
-  //  Assume the timer is stopped\r
-  //\r
-  Status = EFI_SUCCESS;\r
-  if ( pTftpServer->bTimerRunning ) {\r
     //\r
     //\r
-    //  Stop the port creation polling\r
+    //  Set the threshold at half the previous window size\r
     //\r
     //\r
-    Status = gBS->SetTimer ( pTftpServer->TimerEvent,\r
-                             TimerCancel,\r
-                             0 );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" ));\r
+    pContext->Threshold = ( pContext->WindowSize + 1 ) >> 1;\r
 \r
 \r
-      //\r
-      //  Mark the timer stopped\r
-      //\r
-      pTftpServer->bTimerRunning = FALSE;\r
+    //\r
+    //  Close the transmit window\r
+    //\r
+    pContext->WindowSize = 1;\r
+    pContext->PacketsInWindow = 0;\r
+\r
+    //\r
+    //  Double the round trip time\r
+    //\r
+    pContext->Rtt2x = LShiftU64 ( pContext->Rtt2x, 1 );\r
+    if ( pContext->Rtt2x > pContext->MaxTimeout ) {\r
+      pContext->Rtt2x = pContext->MaxTimeout;\r
+    }\r
+\r
+    //\r
+    //  Set the ACK count\r
+    //\r
+    if ( pContext->WindowSize < pContext->Threshold ) {\r
+      pContext->AckCount = pContext->WindowSize * PcdGet32 ( Tftp_AckMultiplier );\r
     }\r
     else {\r
     }\r
     else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,\r
-                "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n",\r
-                Status ));\r
+      pContext->AckCount = PcdGet32 ( Tftp_AckLogBase ) << pContext->WindowSize;\r
     }\r
     }\r
-  }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Send the next TFTP packet\r
-\r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
-  @param [in] pContext      The context structure address.\r
-\r
-  @retval EFI_SUCCESS   Message processed successfully\r
-\r
-**/\r
-EFI_STATUS\r
-TftpTxPacket (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
-  IN TSDT_CONNECTION_CONTEXT * pContext\r
-  )\r
-{\r
-  ssize_t LengthInBytes;\r
-  EFI_STATUS Status;\r
-\r
-  DBG_ENTER ( );\r
 \r
 \r
-  //\r
-  //  Assume success\r
-  //\r
-  Status = EFI_SUCCESS;\r
+    //\r
+    //  Display the round trip time\r
+    //\r
+    DEBUG_CODE_BEGIN ( );\r
+    UINT64 DeltaTime;\r
+    UINT32 Value;\r
+    \r
+    DeltaTime = RShiftU64 ( pContext->Rtt2x, 1 );\r
+    if ( 1000 > DeltaTime ) {\r
+      DEBUG (( DEBUG_WINDOW,\r
+                "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %Ld nSec\r\n",\r
+                pContext->WindowSize,\r
+                pContext->Threshold,\r
+                pContext->AckCount,\r
+                DeltaTime ));\r
+    }\r
+    else if (( 1000 * 1000 ) > DeltaTime ) {\r
+      Value = (UINT32)DeltaTime;\r
+      DEBUG (( DEBUG_WINDOW,\r
+                "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %d.%03d uSec\r\n",\r
+                pContext->WindowSize,\r
+                pContext->Threshold,\r
+                pContext->AckCount,\r
+                Value / 1000,\r
+                Value % 1000 ));\r
+    }\r
+    else if (( 1000 * 1000 * 1000 ) > DeltaTime ) {\r
+      Value = (UINT32)DivU64x32 ( DeltaTime, 1000 );\r
+      DEBUG (( DEBUG_WINDOW,\r
+                "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %d.%03d mSec\r\n",\r
+                pContext->WindowSize,\r
+                pContext->Threshold,\r
+                pContext->AckCount,\r
+                Value / 1000,\r
+                Value % 1000 ));\r
+    }\r
+    else {\r
+      Value = (UINT32)DivU64x32 ( DeltaTime, 1000 * 1000 );\r
+      DEBUG (( DEBUG_WINDOW,\r
+                "WindowSize: %d, Threshold: %d, AckCount: %4d, RTT: %d.%03d Sec\r\n",\r
+                pContext->WindowSize,\r
+                pContext->Threshold,\r
+                pContext->AckCount,\r
+                Value / 1000,\r
+                Value % 1000 ));\r
+    }\r
+    DEBUG_CODE_END ( );\r
 \r
 \r
-  //\r
-  //  Send the TFTP packet\r
-  //\r
-  DEBUG (( DEBUG_TX,\r
-            "0x%08x: pContext sending 0x%08x bytes\r\n",\r
-            pContext,\r
-            pContext->TxBytes ));\r
-  LengthInBytes = sendto ( pTftpServer->TftpPort.fd,\r
-                           &pContext->TxBuffer[0],\r
-                           pContext->TxBytes,\r
-                           0,\r
-                           (struct sockaddr *)&pContext->RemoteAddress,\r
-                           pContext->RemoteAddress.sin_len );\r
-  if ( -1 == LengthInBytes ) {\r
-    DEBUG (( DEBUG_ERROR | DEBUG_TX,\r
-              "ERROR - Transmit failure, errno: 0x%08x\r\n",\r
-              errno ));\r
-    Status = EFI_DEVICE_ERROR;\r
+    //\r
+    //  Retransmit the first packet in the window\r
+    //\r
+    pPacket = pContext->pTxHead;\r
+    if ( NULL != pPacket ) {\r
+      PacketTx ( pContext, pPacket );\r
+    }\r
+    \r
+    DBG_EXIT ( );\r
   }\r
   }\r
-\r
-  //\r
-  //  Return the operation status\r
-  //\r
-  DBG_EXIT_STATUS ( Status );\r
-  return Status;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -1466,25 +2209,46 @@ main (
   IN char **Argv\r
   )\r
 {\r
   IN char **Argv\r
   )\r
 {\r
+  UINTN Index;\r
   TSDT_TFTP_SERVER * pTftpServer;\r
   EFI_STATUS Status;\r
   TSDT_TFTP_SERVER * pTftpServer;\r
   EFI_STATUS Status;\r
+  UINT64 TriggerTime;\r
 \r
   //\r
 \r
   //\r
-  //  Create a timer event to start TFTP port\r
+  //  Get the performance counter characteristics\r
   //\r
   pTftpServer = &mTftpServer;\r
   //\r
   pTftpServer = &mTftpServer;\r
+  if ( PcdGetBool ( Tftp_HighSpeed )\r
+    || PcdGetBool ( Tftp_Bandwidth )) {\r
+    pTftpServer->ClockFrequency = GetPerformanceCounterProperties ( &pTftpServer->Time1,\r
+                                                                  &pTftpServer->Time2 );\r
+  }\r
+\r
+  //\r
+  //  Create a timer event to start TFTP port\r
+  //\r
   Status = gBS->CreateEvent ( EVT_TIMER,\r
                               TPL_TFTP_SERVER,\r
                               NULL,\r
                               NULL,\r
                               &pTftpServer->TimerEvent );\r
   if ( !EFI_ERROR ( Status )) {\r
   Status = gBS->CreateEvent ( EVT_TIMER,\r
                               TPL_TFTP_SERVER,\r
                               NULL,\r
                               NULL,\r
                               &pTftpServer->TimerEvent );\r
   if ( !EFI_ERROR ( Status )) {\r
-    Status = TftpServerTimerStart ( pTftpServer );\r
+    //\r
+    //  Compute the poll interval\r
+    //\r
+    TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );\r
+    Status = gBS->SetTimer ( pTftpServer->TimerEvent,\r
+                             TimerPeriodic,\r
+                             TriggerTime );\r
     if ( !EFI_ERROR ( Status )) {\r
     if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));\r
+\r
       //\r
       //  Run the TFTP server forever\r
       //\r
       //\r
       //  Run the TFTP server forever\r
       //\r
-      for ( ; ; ) {\r
+      pTftpServer->Udpv4Index = -1;\r
+      pTftpServer->Udpv6Index = -1;\r
+      do {\r
         //\r
         //  Poll the network layer to create the TFTP port\r
         //  for the tftp server.  More than one attempt may\r
         //\r
         //  Poll the network layer to create the TFTP port\r
         //  for the tftp server.  More than one attempt may\r
@@ -1492,28 +2256,107 @@ main (
         //  the IP address and initialize the upper layers\r
         //  of the network stack.\r
         //\r
         //  the IP address and initialize the upper layers\r
         //  of the network stack.\r
         //\r
-        TftpServerTimer ( pTftpServer );\r
+        if ( DIM ( pTftpServer->TftpPort ) != pTftpServer->Entries ) {\r
+          do {\r
+            //\r
+            //  Wait a while before polling for a connection\r
+            //\r
+            if ( EFI_SUCCESS != gBS->CheckEvent ( pTftpServer->TimerEvent )) {\r
+              if ( 0 == pTftpServer->Entries ) {\r
+                break;\r
+              }\r
+              gBS->WaitForEvent ( 1, &pTftpServer->TimerEvent, &Index );\r
+            }\r
+\r
+            //\r
+            //  Poll for a network connection\r
+            //\r
+            TftpServerSocket ( pTftpServer,\r
+                               AF_INET,\r
+                               &pTftpServer->Udpv4Index );\r
+            TftpServerSocket ( pTftpServer,\r
+                               AF_INET6,\r
+                               &pTftpServer->Udpv6Index );\r
+          } while ( 0 == pTftpServer->Entries );\r
+        }\r
 \r
         //\r
         //  Poll the socket for activity\r
         //\r
         do {\r
           SocketPoll ( pTftpServer );\r
 \r
         //\r
         //  Poll the socket for activity\r
         //\r
         do {\r
           SocketPoll ( pTftpServer );\r
-        } while ( -1 != pTftpServer->TftpPort.fd );\r
 \r
 \r
-//\r
-// TODO: Remove the following test code\r
-//  Exit when the network connection is broken\r
-//\r
-break;\r
-      }\r
+          //\r
+          //  Normal TFTP lets the client request the retransmit by\r
+          //  sending another ACK for the previous packet\r
+          //\r
+          if ( PcdGetBool ( Tftp_HighSpeed )) {\r
+            UINT64 CurrentTime;\r
+            UINT64 ElapsedTime;\r
+            TSDT_CONNECTION_CONTEXT * pContext;\r
+            TFTP_PACKET * pPacket;\r
+\r
+            //\r
+            //  High speed TFTP uses an agressive retransmit to\r
+            //  get the TFTP client moving again when the ACK or\r
+            //  previous data packet was lost.\r
+            //\r
+            //  Get the current time\r
+            //\r
+            CurrentTime = GetPerformanceCounter ( );\r
+\r
+            //\r
+            //  Walk the list of contexts\r
+            //\r
+            pContext = pTftpServer->pContextList;\r
+            while ( NULL != pContext )\r
+            {\r
+              //\r
+              //  Check for a transmit timeout\r
+              //\r
+              pPacket = pContext->pTxHead;\r
+              if ( NULL != pPacket ) {\r
+                //\r
+                //  Compute the elapsed time\r
+                //\r
+                if ( pTftpServer->Time2 > pTftpServer->Time1 ) {\r
+                  ElapsedTime = CurrentTime - pPacket->TxTime;\r
+                }\r
+                else {\r
+                  ElapsedTime = pPacket->TxTime - CurrentTime;\r
+                }\r
+                ElapsedTime = GetTimeInNanoSecond ( ElapsedTime );\r
+\r
+                //\r
+                //  Determine if a retransmission is necessary\r
+                //\r
+                if ( ElapsedTime >= pContext->Rtt2x ) {\r
+                  DEBUG (( DEBUG_WINDOW,\r
+                            "0x%08x: Context TX timeout for packet 0x%08x, Window: %d\r\n",\r
+                            pContext,\r
+                            pPacket,\r
+                            pContext->WindowSize ));\r
+                  WindowTimeout ( pContext );\r
+                }\r
+              }\r
+\r
+              //\r
+              //  Set the next context\r
+              //\r
+              pContext = pContext->pNext;\r
+            }\r
+          }\r
+        } while ( DIM ( pTftpServer->TftpPort ) == pTftpServer->Entries );\r
+      } while ( !mbTftpServerExit );\r
 \r
       //\r
       //  Done with the timer event\r
       //\r
 \r
       //\r
       //  Done with the timer event\r
       //\r
-      TftpServerTimerStop ( pTftpServer );\r
-      Status = gBS->CloseEvent ( pTftpServer->TimerEvent );\r
+      gBS->SetTimer ( pTftpServer->TimerEvent,\r
+                      TimerCancel,\r
+                      0 );\r
     }\r
     }\r
+    gBS->CloseEvent ( pTftpServer->TimerEvent );\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
index b1e9f83ce59995d1f99080d9f5d2242d16e65dfb..79b64c2820cda05d5583209a5d1fdc7cd7ccfe21 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Definitions for the TFTP server.\r
 \r
 /** @file\r
   Definitions for the TFTP server.\r
 \r
-  Copyright (c) 2011, Intel Corporation\r
+  Copyright (c) 2011, 2012, Intel Corporation\r
   All rights reserved. This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
   All rights reserved. This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -16,6 +16,7 @@
 #define _TFTP_SERVER_H_\r
 \r
 #include <errno.h>\r
 #define _TFTP_SERVER_H_\r
 \r
 #include <errno.h>\r
+#include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
 #include <Uefi.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
 #include <Uefi.h>\r
 \r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 \r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
 #include <Library/PcdLib.h>\r
+#include <Library/TimerLib.h>\r
 #include <Library/UefiApplicationEntryPoint.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Protocol/BlockIo.h>\r
 \r
 #include <netinet/in.h>\r
 #include <Library/UefiApplicationEntryPoint.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Protocol/BlockIo.h>\r
 \r
 #include <netinet/in.h>\r
+#include <netinet6/in6.h>\r
 \r
 #include <sys/EfiSysCall.h>\r
 #include <sys/poll.h>\r
 #include <sys/socket.h>\r
 \r
 #include <sys/EfiSysCall.h>\r
 #include <sys/poll.h>\r
 #include <sys/socket.h>\r
+#include <sys/Stat.h>\r
 \r
 //------------------------------------------------------------------------------\r
 //  Macros\r
 //------------------------------------------------------------------------------\r
 \r
 #if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */\r
 \r
 //------------------------------------------------------------------------------\r
 //  Macros\r
 //------------------------------------------------------------------------------\r
 \r
 #if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */\r
-#define DBG_ENTER()             DEBUG (( DEBUG_INFO, "Entering " __FUNCTION__ "\n" )) ///<  Display routine entry\r
-#define DBG_EXIT()              DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ "\n" ))  ///<  Display routine exit\r
-#define DBG_EXIT_DEC(Status)    DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display routine exit with decimal value\r
-#define DBG_EXIT_HEX(Status)    DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display routine exit with hex value\r
-#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display routine exit with status value\r
-#define DBG_EXIT_TF(Status)     DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" ))  ///<  Display routine with TRUE/FALSE value\r
+#define DBG_ENTER()             DEBUG (( DEBUG_ENTER_EXIT, "Entering " __FUNCTION__ "\n" )) ///<  Display routine entry\r
+#define DBG_EXIT()              DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ "\n" ))  ///<  Display routine exit\r
+#define DBG_EXIT_DEC(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display routine exit with decimal value\r
+#define DBG_EXIT_HEX(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display routine exit with hex value\r
+#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display routine exit with status value\r
+#define DBG_EXIT_TF(Status)     DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" ))  ///<  Display routine with TRUE/FALSE value\r
 #else   //  _MSC_VER\r
 #define DBG_ENTER()\r
 #define DBG_EXIT()\r
 #else   //  _MSC_VER\r
 #define DBG_ENTER()\r
 #define DBG_EXIT()\r
 //  Constants\r
 //------------------------------------------------------------------------------\r
 \r
 //  Constants\r
 //------------------------------------------------------------------------------\r
 \r
-#define DEBUG_PORT_WORK         0x40000000  ///<  Display the port work messages\r
-#define DEBUG_SERVER_TIMER      0x20000000  ///<  Display the socket poll messages\r
-#define DEBUG_TFTP_PORT         0x10000000  ///<  Display the TFTP port messages\r
-#define DEBUG_TFTP_REQUEST      0x08000000  ///<  Display the TFTP request messages\r
-#define DEBUG_TX                0x04000000  ///<  Display transmit messages\r
-#define DEBUG_SOCKET_POLL       0x02000000  ///<  Display the socket poll messages\r
-#define DEBUG_RX                0x01000000  ///<  Display receive messages\r
-#define DEBUG_TFTP_ACK          0x00800000  ///<  Display the TFTP ACK messages\r
+#define ACK_SHIFT               4           ///<  Number of samples in ACK average\r
+\r
+#define DEBUG_WINDOW            0x00000001  ///<  Display the window messages\r
+#define DEBUG_TX_PACKET         0x00000002  ///<  Display the transmit packet messages\r
+#define DEBUG_FILE_BUFFER       0x00000004  ///<  Display the file buffer messages\r
+#define DEBUG_SERVER_TIMER      0x00000008  ///<  Display the socket poll messages\r
+#define DEBUG_TFTP_REQUEST      0x00000010  ///<  Display the TFTP request messages\r
+#define DEBUG_PORT_WORK         0x00000020  ///<  Display the port work messages\r
+#define DEBUG_SOCKET_POLL       0x00000040  ///<  Display the socket poll messages\r
+#define DEBUG_TFTP_PORT         0x00000080  ///<  Display the TFTP port messages\r
+#define DEBUG_TX                0x00000100  ///<  Display transmit messages\r
+#define DEBUG_RX                0x00000200  ///<  Display receive messages\r
+#define DEBUG_TFTP_ACK          0x00000400  ///<  Display the TFTP ACK messages\r
+#define DEBUG_ENTER_EXIT        0x00000800  ///<  Display entry and exit messages\r
+\r
+#define MAX_PACKETS             8           ///<  Maximum number of packets in the window\r
 \r
 #define TFTP_PORT_POLL_DELAY  ( 2 * 1000 )  ///<  Delay in milliseconds for attempts to open the TFTP port\r
 #define CLIENT_POLL_DELAY     50            ///<  Delay in milliseconds between client polls\r
 \r
 #define TFTP_PORT_POLL_DELAY  ( 2 * 1000 )  ///<  Delay in milliseconds for attempts to open the TFTP port\r
 #define CLIENT_POLL_DELAY     50            ///<  Delay in milliseconds between client polls\r
 \r
 #define TFTP_MAX_BLOCK_SIZE       4096  ///<  Maximum block size\r
 \r
 \r
 #define TFTP_MAX_BLOCK_SIZE       4096  ///<  Maximum block size\r
 \r
+#define TFTP_ERROR_SEE_MSG          0   ///<  See the error message\r
+#define TFTP_ERROR_NOT_FOUND        1   ///<  File not found\r
+#define TFTP_ERROR_ACCESS_VIOLATION 2   ///<  Access violation\r
+#define TFTP_ERROR_DISK_FULL        3   ///<  Disk full\r
+#define TFTP_ERROR_ILLEGAL_OP       4   ///<  Illegal operation\r
+#define TFTP_ERROR_UNKNOWN_XFER_ID  5   ///<  Unknown transfer ID\r
+#define TFTP_ERROR_FILE_EXISTS      6   ///<  File already exists\r
+#define TFTP_ERROR_NO_SUCH_USER     7   ///<  No such user\r
+\r
 //------------------------------------------------------------------------------\r
 //  Data Types\r
 //------------------------------------------------------------------------------\r
 \r
 //------------------------------------------------------------------------------\r
 //  Data Types\r
 //------------------------------------------------------------------------------\r
 \r
+/**\r
+  Packet structure\r
+**/\r
+typedef struct _TFTP_PACKET TFTP_PACKET;\r
+typedef struct _TFTP_PACKET {\r
+  TFTP_PACKET * pNext;          ///<  Next packet in list\r
+  UINT64    TxTime;             ///<  Time the transmit was performed\r
+  ssize_t   TxBytes;            ///<  Bytes in the TX buffer\r
+  UINT32    RetryCount;         ///<  Number of transmissions\r
+  UINT16    BlockNumber;        ///<  Block number of this packet\r
+  UINT8     TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Transmit buffer\r
+} GCC_TFTP_PACKET;\r
+\r
 /**\r
   Port control structure\r
 **/\r
 /**\r
   Port control structure\r
 **/\r
@@ -135,33 +170,49 @@ typedef struct _TSDT_CONNECTION_CONTEXT {
   //\r
   //  Remote connection management\r
   //\r
   //\r
   //  Remote connection management\r
   //\r
-  TSDT_CONNECTION_CONTEXT * pNext;  ///<  Next context in the connection list\r
-  struct sockaddr_in RemoteAddress; ///<  Remote address\r
-\r
-  //\r
-  //  TFTP management parameters\r
-  //\r
-  UINT16 AckNext;               ///<  Next block to be received\r
-  BOOLEAN bExpectAck;           ///<  TRUE for read, FALSE for write\r
-  UINT32 BlockSize;             ///<  Negotiated block size\r
-  UINT32 Timeout;               ///<  Number of seconds to wait before retransmission\r
+  TSDT_CONNECTION_CONTEXT * pNext;    ///<  Next context in the connection list\r
+  struct sockaddr_in6 RemoteAddress;  ///<  Remote address\r
+  int SocketFd;                       ///<  Socket file descriptor\r
 \r
   //\r
   //  File management parameters\r
   //\r
 \r
   //\r
   //  File management parameters\r
   //\r
-  EFI_HANDLE File;              ///<  NULL while file is closed\r
+  FILE * File;                  ///<  NULL while file is closed\r
   UINT64 LengthInBytes;         ///<  Size of the file\r
   UINT64 LengthInBytes;         ///<  Size of the file\r
-  UINT64 MaxTransferSize;       ///<  Maximum transfer size\r
+  UINT64 BytesRemaining;        ///<  Number of bytes remaining to be sent\r
+  UINT64 BytesToSend;           ///<  Number of bytes to send\r
+  UINT64 ValidBytes;            ///<  Number of valid bytes in the buffer\r
   BOOLEAN bEofSent;             ///<  End of file sent\r
   BOOLEAN bEofSent;             ///<  End of file sent\r
+  UINT8 * pFill;                ///<  Next portion of the buffer to fill\r
   UINT8 * pBuffer;              ///<  Pointer into the file data\r
   UINT8 * pEnd;                 ///<  End of the file data\r
   UINT8 * pBuffer;              ///<  Pointer into the file data\r
   UINT8 * pEnd;                 ///<  End of the file data\r
-  UINT8 FileData[ 64 * TFTP_MAX_BLOCK_SIZE ]; ///<  File data to send\r
+  UINT8 FileData[ 2 * MAX_PACKETS * TFTP_MAX_BLOCK_SIZE ];  ///<  File data to send\r
+  UINT64 TimeStart;             ///<  Start of file transfer\r
+\r
+  //\r
+  //  TFTP management parameters\r
+  //\r
+  UINT16 BlockNumber;           ///<  Next block to be transmitted\r
+  UINT32 BlockSize;             ///<  Negotiated block size\r
+\r
+  //\r
+  //  Window management\r
+  //\r
+  UINT32 AckCount;              ///<  Number of ACKs to receive before increasing the window\r
+  UINT32 PacketsInWindow;       ///<  Number of packets in the window\r
+  UINT32 Threshold;             ///<  Size of window when ACK count becomes logrithmic\r
+  UINT32 WindowSize;            ///<  Size of the transmit window\r
+  UINT64 MaxTimeout;            ///<  Maximum number of seconds to wait before retransmission\r
+  UINT64 Rtt2x;                 ///<  Twice the average round trip time in nanoseconds\r
 \r
   //\r
   //  Buffer management\r
   //\r
 \r
   //\r
   //  Buffer management\r
   //\r
-  ssize_t   TxBytes;            ///<  Bytes in the TX buffer\r
-  UINT8     TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Transmit buffer\r
+  TFTP_PACKET * pFreeList;      ///<  List of free packets\r
+  TFTP_PACKET * pTxHead;        ///<  First packet in the list of packets for transmission\r
+  TFTP_PACKET * pTxTail;        ///<  Last packet in the list of packets for transmission\r
+  TFTP_PACKET ErrorPacket;      ///<  Error packet\r
+  TFTP_PACKET Tx[ MAX_PACKETS ];///<  Transmit packets\r
 }GCC_TSDT_CONNECTION_CONTEXT;\r
 \r
 /**\r
 }GCC_TSDT_CONNECTION_CONTEXT;\r
 \r
 /**\r
@@ -175,20 +226,32 @@ typedef struct {
   //\r
   EFI_HANDLE ImageHandle;       ///<  Image handle\r
 \r
   //\r
   EFI_HANDLE ImageHandle;       ///<  Image handle\r
 \r
+  //\r
+  //  Performance management\r
+  //\r
+  UINT64 ClockFrequency;        ///<  Frequency of the clock\r
+  UINT64 Time1;                 ///<  Clock value after rollover\r
+  UINT64 Time2;                 ///<  Clock value before rollover\r
+  UINT64 RxTime;                ///<  Time when the packet was recevied\r
+\r
   //\r
   //  TFTP port management\r
   //\r
   //\r
   //  TFTP port management\r
   //\r
-  BOOLEAN   bTimerRunning;      ///<  Port creation timer status\r
   EFI_EVENT TimerEvent;         ///<  Timer to open TFTP port\r
   EFI_EVENT TimerEvent;         ///<  Timer to open TFTP port\r
-  struct pollfd TftpPort;       ///<  Poll descriptor for the TFTP port\r
-  struct sockaddr_in TftpServerAddress; ///<  Address of the local TFTP server\r
+  int Udpv4Index;               ///<  Entry for UDPv4\r
+  int Udpv6Index;               ///<  Entry for UDPv6\r
+  int Entries;                  ///<  Number of TFTP ports\r
+  struct pollfd TftpPort [ 2 ]; ///<  Poll descriptor for the TFTP ports (UDP4, UDP6)\r
 \r
   //\r
   //  Request management\r
   //\r
 \r
   //\r
   //  Request management\r
   //\r
-  struct sockaddr_in RemoteAddress; ///<  Remote address\r
-  ssize_t   RxBytes;                ///<  Receive data length in bytes\r
-  UINT8     RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Receive buffer\r
+  union {\r
+    struct sockaddr_in v4;      ///<  UDP4 address\r
+    struct sockaddr_in6 v6;     ///<  UDP6 address\r
+  } RemoteAddress;              ///<  Remote address\r
+  ssize_t RxBytes;              ///<  Receive data length in bytes\r
+  UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Receive buffer\r
 \r
   //\r
   //  Client port management\r
 \r
   //\r
   //  Client port management\r
@@ -205,37 +268,77 @@ extern TSDT_TFTP_SERVER mTftpServer;
 //------------------------------------------------------------------------------\r
 \r
 /**\r
 //------------------------------------------------------------------------------\r
 \r
 /**\r
-  Process the TFTP request\r
+  Queue data packets for transmission\r
 \r
 \r
-  @param [in] pOption   Address of the first zero terminated option string\r
-  @param [in] pValue    Address to receive the value\r
+  @param [in] pContext    Connection context structure address\r
 \r
 \r
-  @retval EFI_SUCCESS   Option translated into a value\r
+  @retval TRUE if a read error occurred\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpOptionValue (\r
-  IN UINT8 * pOption,\r
-  IN INT32 * pValue\r
+BOOLEAN\r
+PacketFill (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
-  Process the TFTP request\r
+  Free the packet\r
 \r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    Connection context structure address\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
-TftpProcessRequest (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
+PacketFree(\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
+  );\r
+\r
+/**\r
+  Get a packet for transmission\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+\r
+  @retval Address of a ::TFTP_PACKET structure\r
+\r
+**/\r
+TFTP_PACKET *\r
+PacketGet (\r
   IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
   IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
+/**\r
+  Queue the packet for transmission\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
+\r
+  @retval TRUE if a transmission error has occurred\r
+\r
+**/\r
+BOOLEAN\r
+PacketQueue (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
+  );\r
+\r
+/**\r
+  Transmit the packet\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
+\r
+  @retval EFI_SUCCESS   Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+PacketTx (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
+  );\r
+\r
 /**\r
   Build and send an error packet\r
 \r
 /**\r
   Build and send an error packet\r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
   @param [in] pContext    The context structure address.\r
   @param [in] Error       Error number for the packet\r
   @param [in] pError      Zero terminated error string address\r
   @param [in] pContext    The context structure address.\r
   @param [in] Error       Error number for the packet\r
   @param [in] pError      Zero terminated error string address\r
@@ -244,85 +347,82 @@ TftpProcessRequest (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-TftpSendError (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
+SendError (\r
   IN TSDT_CONNECTION_CONTEXT * pContext,\r
   IN UINT16 Error,\r
   IN UINT8 * pError\r
   );\r
 \r
 /**\r
   IN TSDT_CONNECTION_CONTEXT * pContext,\r
   IN UINT16 Error,\r
   IN UINT8 * pError\r
   );\r
 \r
 /**\r
-  Send the next block of file system data\r
+  Process the TFTP request\r
 \r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    The context structure address.\r
+  @param [in] pOption   Address of the first zero terminated option string\r
+  @param [in] pValue    Address to receive the value\r
 \r
 \r
-  @retval EFI_SUCCESS   Message processed successfully\r
+  @retval EFI_SUCCESS   Option translated into a value\r
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-TftpSendNextBlock (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
-  IN TSDT_CONNECTION_CONTEXT * pContext\r
+TftpOptionValue (\r
+  IN UINT8 * pOption,\r
+  IN INT32 * pValue\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
-  TFTP port creation timer routine\r
-\r
-  This routine polls the socket layer waiting for the initial network connection\r
-  which will enable the creation of the TFTP port.  The socket layer will manage\r
-  the coming and going of the network connections after that until the last network\r
-  connection is broken.\r
+  Process the TFTP request\r
 \r
 \r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  @param [in] pTftpServer The TFTP server control structure address.\r
+  @param [in] pContext    Connection context structure address\r
+  @param [in] SocketFd    Socket file descriptor\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
-TftpServerTimer (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+TftpProcessRequest (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN int SocketFd\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
-  Start the TFTP server port creation timer\r
+  Process the read request\r
 \r
 \r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Connection context structure address\r
+  @param [in] SocketFd    Socket file descriptor\r
 \r
 \r
-  @retval EFI_SUCCESS         The timer was successfully started.\r
-  @retval EFI_ALREADY_STARTED The timer is already running.\r
-  @retval Other               The timer failed to start.\r
+  @retval TRUE if the context should be closed\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpServerTimerStart (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+BOOLEAN\r
+TftpRead (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN int SocketFd\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
-  Stop the TFTP server port creation timer\r
-\r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  Update the window due to the ACK\r
 \r
 \r
-  @retval EFI_SUCCESS   The TFTP port timer is stopped\r
-  @retval Other         Failed to stop the TFTP port timer\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpServerTimerStop (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+VOID\r
+WindowAck (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
-  Send the next TFTP packet\r
-\r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
-  @param [in] pContext      The context structure address.\r
+  A timeout has occurred, close the window\r
 \r
 \r
-  @retval EFI_SUCCESS   Message processed successfully\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
 \r
 **/\r
 \r
 **/\r
-EFI_STATUS\r
-TftpTxPacket (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
+VOID\r
+WindowTimeout (\r
   IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
   IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
index f48724289f8233fa34930aa2ca4245418eb43923..d7cbfaa303a077534f6e5848309156292499579f 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
   TftpServer.c\r
 \r
 \r
   TftpServer.c\r
 \r
 \r
+[Pcd]\r
+  gAppPkgTokenSpaceGuid.Tftp_AckLogBase\r
+  gAppPkgTokenSpaceGuid.Tftp_AckMultiplier\r
+  gAppPkgTokenSpaceGuid.Tftp_Bandwidth\r
+  gAppPkgTokenSpaceGuid.Tftp_HighSpeed\r
+  gAppPkgTokenSpaceGuid.Tftp_MaxRetry\r
+  gAppPkgTokenSpaceGuid.Tftp_MaxTimeoutInSec\r
+\r
+\r
 [Packages]\r
 [Packages]\r
+  AppPkg/AppPkg.dec\r
   MdePkg/MdePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   StdLib/StdLib.dec\r
   MdePkg/MdePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   StdLib/StdLib.dec\r
@@ -54,6 +64,7 @@
   LibC\r
   ShellLib\r
   ShellCEntryLib\r
   LibC\r
   ShellLib\r
   ShellCEntryLib\r
+  TimerLib\r
   UefiBootServicesTableLib\r
   UefiLib\r
   UefiRuntimeServicesTableLib\r
   UefiBootServicesTableLib\r
   UefiLib\r
   UefiRuntimeServicesTableLib\r
diff --git a/AppPkg/Applications/Sockets/WebServer/Exit.c b/AppPkg/Applications/Sockets/WebServer/Exit.c
new file mode 100644 (file)
index 0000000..cad4b00
--- /dev/null
@@ -0,0 +1,92 @@
+/*++
+  This file contains an 'Intel UEFI Application' and is        
+  licensed for Intel CPUs and chipsets under the terms of your  
+  license agreement with Intel or your vendor.  This file may   
+  be modified by the user, subject to additional terms of the   
+  license agreement                                             
+--*/
+/*++
+
+Copyright (c)  2011 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+--*/
+
+/** @file
+  Exit response page
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Respond with the Exit page
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [out] pbDone       Address to receive the request completion status
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+ExitPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+  
+  DBG_ENTER ( );
+  
+  //
+  //  Send the Hello World page
+  //
+  for ( ; ; ) {
+    //
+    //  Tell the web-server to exit
+    //
+    mWebServer.bRunning = FALSE;
+
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"Exit" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Send the page body
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>Exit</h1>\r\n"
+                                  "<p>\r\n"
+                                  "  Exiting the web-server application.\r\n"
+                                  "</p>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Send the page trailer
+    //
+    Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
index 8487de751a1287074b90c452f8273d7cb1109215..9a8bd70a9d62f71b5b464732c7357e19d8e97320 100644 (file)
@@ -401,8 +401,8 @@ HttpPageTrailer (
   int RetVal;\r
   EFI_STATUS Status;\r
   socklen_t LengthInBytes;\r
   int RetVal;\r
   EFI_STATUS Status;\r
   socklen_t LengthInBytes;\r
-  struct sockaddr_in LocalAddress;\r
-  struct sockaddr_in RemoteAddress;\r
+  struct sockaddr_in6 LocalAddress;\r
+  struct sockaddr_in6 RemoteAddress;\r
 \r
   DBG_ENTER ( );\r
 \r
 \r
   DBG_ENTER ( );\r
 \r
@@ -413,12 +413,13 @@ HttpPageTrailer (
     LengthInBytes = sizeof ( LocalAddress );\r
     RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );\r
     if ( 0 == RetVal ) {\r
     LengthInBytes = sizeof ( LocalAddress );\r
     RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );\r
     if ( 0 == RetVal ) {\r
+      LengthInBytes = sizeof ( LocalAddress );\r
       RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );\r
       if ( 0 == RetVal ) {\r
         //\r
         //  Seperate the body from the trailer\r
         //\r
       RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );\r
       if ( 0 == RetVal ) {\r
         //\r
         //  Seperate the body from the trailer\r
         //\r
-        Status = HttpSendAnsiString ( SocketFD, pPort, "  <hr>\r\n" );\r
+        Status = HttpSendAnsiString ( SocketFD, pPort, "  <hr>\r\n<code>" );\r
         if ( EFI_ERROR ( Status )) {\r
           break;\r
         }\r
         if ( EFI_ERROR ( Status )) {\r
           break;\r
         }\r
@@ -438,7 +439,7 @@ HttpPageTrailer (
         if ( EFI_ERROR ( Status )) {\r
           break;\r
         }\r
         if ( EFI_ERROR ( Status )) {\r
           break;\r
         }\r
-        Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" );\r
+        Status = HttpSendAnsiString ( SocketFD, pPort, "</code>\r\n" );\r
         if ( EFI_ERROR ( Status )) {\r
           break;\r
         }\r
         if ( EFI_ERROR ( Status )) {\r
           break;\r
         }\r
@@ -1213,7 +1214,7 @@ HttpSendHexBits (
     //\r
     Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
     if ( 10 <= Digit ) {\r
     //\r
     Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
     if ( 10 <= Digit ) {\r
-      Digit += 'A' - '0' - 10;\r
+      Digit += 'a' - '0' - 10;\r
     }\r
 \r
     //\r
     }\r
 \r
     //\r
@@ -1274,7 +1275,7 @@ HttpSendHexValue (
     //\r
     Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
     if ( 10 <= Digit ) {\r
     //\r
     Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
     if ( 10 <= Digit ) {\r
-      Digit += 'A' - '0' - 10;\r
+      Digit += 'a' - '0' - 10;\r
     }\r
 \r
     //\r
     }\r
 \r
     //\r
@@ -1305,6 +1306,112 @@ HttpSendHexValue (
 }\r
 \r
 \r
 }\r
 \r
 \r
+/**\r
+  Output an IP6 address value to the HTML page\r
+\r
+  @param [in] SocketFD          Socket file descriptor\r
+  @param [in] pPort             The WSDT_PORT structure address\r
+  @param [in] Value             Value to display\r
+  @param [in] bFirstValue       TRUE if first value\r
+  @param [in] bLastValue        TRUE if last value\r
+  @param [in] bZeroSuppression  TRUE while zeros are being suppressed\r
+  @param [in] pbZeroSuppression Address to receive TRUE when zero suppression\r
+                                has started, use NULL if next colon value not\r
+                                needed.\r
+\r
+  @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendIp6Value (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN UINT16 Value,\r
+  IN BOOLEAN bFirstValue,\r
+  IN BOOLEAN bLastValue,\r
+  IN BOOLEAN bZeroSuppression,\r
+  IN BOOLEAN * pbZeroSuppression\r
+  )\r
+{\r
+  BOOLEAN bZeroSuppressionStarting;\r
+  UINT32 Digit;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Use break instead of goto\r
+  //\r
+  bZeroSuppressionStarting = FALSE;\r
+  Status = EFI_SUCCESS;\r
+  for ( ; ; ) {\r
+    //\r
+    //  Display the leading colon if necessary\r
+    //\r
+    if ( bZeroSuppression && ( bLastValue || ( 0 != Value ))) {\r
+      Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Skip over a series of zero values\r
+    //\r
+    bZeroSuppressionStarting = (BOOLEAN)( 0 == Value );\r
+    if ( !bZeroSuppressionStarting ) {\r
+      //\r
+      //  Display the value\r
+      //\r
+      Digit = ( Value >> 4 ) & 0xf;\r
+      Status = HttpSendHexValue ( SocketFD,\r
+                                  pPort,\r
+                                  Digit );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Digit = Value & 0xf;\r
+      Status = HttpSendHexValue ( SocketFD,\r
+                                  pPort,\r
+                                  Digit );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Digit = ( Value >> 12 ) & 0xf;\r
+      Status = HttpSendHexValue ( SocketFD,\r
+                                  pPort,\r
+                                  Digit );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Digit = ( Value >> 8 ) & 0xf;\r
+      Status = HttpSendHexValue ( SocketFD,\r
+                                  pPort,\r
+                                  Digit );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Display the trailing colon if necessary\r
+    //\r
+    if (( !bLastValue ) && ( bFirstValue || ( 0 != Value ))) {\r
+      Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+    }\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the next colon display\r
+  if ( NULL != pbZeroSuppression ) {\r
+    *pbZeroSuppression = bZeroSuppressionStarting;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Output an IP address to the HTML page\r
 \r
 /**\r
   Output an IP address to the HTML page\r
 \r
@@ -1318,41 +1425,109 @@ EFI_STATUS
 HttpSendIpAddress (\r
   IN int SocketFD,\r
   IN WSDT_PORT * pPort,\r
 HttpSendIpAddress (\r
   IN int SocketFD,\r
   IN WSDT_PORT * pPort,\r
-  IN struct sockaddr_in * pAddress\r
+  IN struct sockaddr_in6 * pAddress\r
   )\r
 {\r
   )\r
 {\r
+  BOOLEAN bZeroSuppression;\r
+  UINT32 Index;\r
+  struct sockaddr_in * pIpv4;\r
+  struct sockaddr_in6 * pIpv6;\r
+  UINT16 PortNumber;\r
   EFI_STATUS Status;\r
 \r
   //\r
   EFI_STATUS Status;\r
 \r
   //\r
-  //  Output the IPv4 address\r
+  //  Use break instead of goto\r
   //\r
   //\r
-  Status = HttpSendValue ( SocketFD, pPort, (UINT8)pAddress->sin_addr.s_addr );\r
-  if ( !EFI_ERROR ( Status )) {\r
-    Status = HttpSendByte ( SocketFD, pPort, '.' );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 8 ));\r
-      if ( !EFI_ERROR ( Status )) {\r
-        Status = HttpSendByte ( SocketFD, pPort, '.' );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 16 ));\r
-          if ( !EFI_ERROR ( Status )) {\r
-            Status = HttpSendByte ( SocketFD, pPort, '.' );\r
-            if ( !EFI_ERROR ( Status )) {\r
-              Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 24 ));\r
-              if ( !EFI_ERROR ( Status )) {\r
-                //\r
-                //  Output the port number\r
-                //\r
-                Status = HttpSendByte ( SocketFD, pPort, ':' );\r
-                if ( !EFI_ERROR ( Status )) {\r
-                  Status = HttpSendValue ( SocketFD, pPort, htons ( pAddress->sin_port ));\r
-                }\r
-              }\r
-            }\r
-          }\r
+  for ( ; ; ) {\r
+    //\r
+    //  Determine the type of address\r
+    //\r
+    if ( AF_INET6 == pAddress->sin6_family ) {\r
+      pIpv6 = pAddress;\r
+\r
+      //\r
+      //  Display the address in RFC2732 format\r
+      //\r
+      bZeroSuppression = FALSE;\r
+      Status = HttpSendByte ( SocketFD, pPort, '[' );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      for ( Index = 0; 8 > Index; Index++ ) {\r
+        Status = HttpSendIp6Value ( SocketFD,\r
+                                    pPort,\r
+                                    pIpv6->sin6_addr.__u6_addr.__u6_addr16[ Index ],\r
+                                    (BOOLEAN)( 0 == Index ),\r
+                                    (BOOLEAN)( 7 == Index ),\r
+                                    bZeroSuppression,\r
+                                    &bZeroSuppression );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
         }\r
       }\r
         }\r
       }\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Separate the port number\r
+      //\r
+      Status = HttpSendByte ( SocketFD, pPort, ']' );\r
+\r
+      //\r
+      //  Get the port number\r
+      //\r
+      PortNumber = pIpv6->sin6_port;\r
     }\r
     }\r
+    else {\r
+      //\r
+      //  Output the IPv4 address\r
+      //\r
+      pIpv4 = (struct sockaddr_in *)pAddress;\r
+      Status = HttpSendValue ( SocketFD, pPort, (UINT8)pIpv4->sin_addr.s_addr );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 8 ));\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 16 ));\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 24 ));\r
+\r
+      //\r
+      //  Get the port number\r
+      //\r
+      PortNumber = pIpv4->sin_port;\r
+    }\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Display the port number\r
+    //\r
+    Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    Status = HttpSendValue ( SocketFD, pPort, htons ( PortNumber ));\r
+    break;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
index f26ab0fdbbb12852f3048db1d883fa712d468be7..98927e8e1dd91bd47de8a7dd2a75ad268dcbbd98 100644 (file)
@@ -44,10 +44,12 @@ CONST DT_PAGE mPageList[] = {
   { L"/DhcpOptions", DhcpOptionsPage, L"DHCP Options" },                                ///<  Display the DHCP options
   { PAGE_ACPI_DSDT, AcpiDsdtPage, L"DSDT - Differentiated System Description Table" },  ///<  Format DSDT
   { PAGE_DXE_SERVICES_TABLE, DxeServicesTablePage, L"DXE Services Table" },             ///<  Format DXE services table
   { L"/DhcpOptions", DhcpOptionsPage, L"DHCP Options" },                                ///<  Display the DHCP options
   { PAGE_ACPI_DSDT, AcpiDsdtPage, L"DSDT - Differentiated System Description Table" },  ///<  Format DSDT
   { PAGE_DXE_SERVICES_TABLE, DxeServicesTablePage, L"DXE Services Table" },             ///<  Format DXE services table
+  { L"/Exit", ExitPage, L"Exit the web server" },       ///<  Exit the web server application
   { PAGE_ACPI_FADT, AcpiFadtPage, L"FADT - Fixed ACPI Description Table" },             ///<  Format FADT
   { L"/Firmware", FirmwarePage, L"Firmware" },          ///<  Firmware status
   { L"/Handles", HandlePage, L"Display handles and associated protocol GUIDs" },        ///<  Handle database page
   { L"/Hello", HelloPage, L"Hello World" },             ///<  Hello world page
   { PAGE_ACPI_FADT, AcpiFadtPage, L"FADT - Fixed ACPI Description Table" },             ///<  Format FADT
   { L"/Firmware", FirmwarePage, L"Firmware" },          ///<  Firmware status
   { L"/Handles", HandlePage, L"Display handles and associated protocol GUIDs" },        ///<  Handle database page
   { L"/Hello", HelloPage, L"Hello World" },             ///<  Hello world page
+  { L"/Ports", PortsPage, L"Display web-server ports" },///<  Web-server ports page
   { L"/Reboot", RebootPage, L"Reboot the sytem" },      ///<  Reboot page
   { PAGE_ACPI_RSDP_10B, AcpiRsdp10Page, L"RSDP 1.0b - ACPI Root System Description Pointer" },  ///<  Format RSDP 1.0b table
   { PAGE_ACPI_RSDP_30, AcpiRsdp30Page, L"RSDP 3.0 - ACPI Root System Description Pointer" },    ///<  Format RSDP 3.0 table
   { L"/Reboot", RebootPage, L"Reboot the sytem" },      ///<  Reboot page
   { PAGE_ACPI_RSDP_10B, AcpiRsdp10Page, L"RSDP 1.0b - ACPI Root System Description Pointer" },  ///<  Format RSDP 1.0b table
   { PAGE_ACPI_RSDP_30, AcpiRsdp30Page, L"RSDP 3.0 - ACPI Root System Description Pointer" },    ///<  Format RSDP 3.0 table
diff --git a/AppPkg/Applications/Sockets/WebServer/Ports.c b/AppPkg/Applications/Sockets/WebServer/Ports.c
new file mode 100644 (file)
index 0000000..e9190bf
--- /dev/null
@@ -0,0 +1,146 @@
+/*++
+  This file contains an 'Intel UEFI Application' and is        
+  licensed for Intel CPUs and chipsets under the terms of your  
+  license agreement with Intel or your vendor.  This file may   
+  be modified by the user, subject to additional terms of the   
+  license agreement                                             
+--*/
+/*++
+
+Copyright (c)  2011 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+--*/
+
+/** @file
+  Ports response page
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Respond with the Ports page
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [out] pbDone       Address to receive the request completion status
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+PortsPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  socklen_t AddressLength;
+  struct sockaddr_in6 LocalAddress;
+  DT_WEB_SERVER * pWebServer;
+  EFI_STATUS Status;
+  
+  DBG_ENTER ( );
+  
+  //
+  //  Send the Hello World page
+  //
+  pWebServer = &mWebServer;
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"Ports" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Send the page body
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>Web-Server Ports</h1>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Check for TCP v4
+    //
+    if ( -1 != pWebServer->HttpListenPort ) {
+      AddressLength = sizeof ( LocalAddress );
+      if ( 0 == getsockname ( pWebServer->HttpListenPort,
+                              (struct sockaddr *)&LocalAddress,
+                              &AddressLength )) {
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "<a href=\"http://" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendIpAddress ( SocketFD,
+                                     pPort,
+                                     &LocalAddress );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "\">Tcp4</a><br>\r\n" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+    }
+
+    //
+    //  Check for TCP v6
+    //
+    if ( -1 != pWebServer->HttpListenPort6 ) {
+      AddressLength = sizeof ( LocalAddress );
+      if ( 0 == getsockname ( pWebServer->HttpListenPort6,
+                              (struct sockaddr *)&LocalAddress,
+                              &AddressLength )) {
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "<a href=\"http://" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendIpAddress ( SocketFD,
+                                     pPort,
+                                     &LocalAddress );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "\">Tcp6</a><br>\r\n" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+    }
+
+    //
+    //  Send the page trailer
+    //
+    Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
index 5c73bfe8f7d40df280ffaaace29375672dbbea56..00f8633efb2fba8169cbf3e94eadad950c692c9c 100644 (file)
@@ -337,7 +337,7 @@ PortWork (
   size_t LengthInBytes;
   int NewSocket;
   EFI_STATUS OpStatus;
   size_t LengthInBytes;
   int NewSocket;
   EFI_STATUS OpStatus;
-  struct sockaddr RemoteAddress;
+  struct sockaddr_in6 RemoteAddress;
   socklen_t RemoteAddressLength;
   EFI_STATUS Status;
 
   socklen_t RemoteAddressLength;
   EFI_STATUS Status;
 
@@ -355,14 +355,15 @@ PortWork (
     //
     //  Determine if this is a connection attempt
     //
     //
     //  Determine if this is a connection attempt
     //
-    if ( SocketFD == pWebServer->HttpListenPort ) {
+    if (( SocketFD == pWebServer->HttpListenPort )
+      || ( SocketFD == pWebServer->HttpListenPort6 )) {
       //
       //  Handle connection attempts
       //  Accepts arrive as read events
       //
       RemoteAddressLength = sizeof ( RemoteAddress );
       NewSocket = accept ( SocketFD,
       //
       //  Handle connection attempts
       //  Accepts arrive as read events
       //
       RemoteAddressLength = sizeof ( RemoteAddress );
       NewSocket = accept ( SocketFD,
-                           &RemoteAddress,
+                           (struct sockaddr *)&RemoteAddress,
                            &RemoteAddressLength );
       if ( -1 != NewSocket ) {
         if ( 0 != NewSocket ) {
                            &RemoteAddressLength );
       if ( -1 != NewSocket ) {
         if ( 0 != NewSocket ) {
@@ -561,9 +562,9 @@ SocketPoll (
 
 
 /**
 
 
 /**
-  Create the HTTP port for the web server
+  Create an HTTP port for the web server
 
 
-  This routine polls the network layer to create the HTTP port for the
+  This routine polls the network layer to create an HTTP port for the
   web server.  More than one attempt may be necessary since it may take
   some time to get the IP address and initialize the upper layers of
   the network stack.
   web server.  More than one attempt may be necessary since it may take
   some time to get the IP address and initialize the upper layers of
   the network stack.
@@ -572,195 +573,93 @@ SocketPoll (
   coming and going of the network connections until the last network
   connection is broken.
 
   coming and going of the network connections until the last network
   connection is broken.
 
-  @param [in] pWebServer  The web server control structure address.
+  @param [in] pWebServer    The web server control structure address.
+  @param [in] AddressFamily Address family for the network connection
+  @param [in] Protocol      Protocol to use for the network connection
+  @param [in] HttpPort      Port number for the HTTP connection
+  @param [out] pPort        Address of the port
 
 **/
 VOID
 
 **/
 VOID
-WebServerTimer (
-  IN DT_WEB_SERVER * pWebServer
+WebServerListen (
+  IN DT_WEB_SERVER * pWebServer,
+  IN sa_family_t AddressFamily,
+  IN int Protocol,
+  IN UINT16 HttpPort,
+  OUT int * pPort
   )
 {
   )
 {
-  UINT16 HttpPort;
-  struct sockaddr_in WebServerAddress;
+  union {
+    struct sockaddr_in v4;
+    struct sockaddr_in6 v6;
+  } WebServerAddress;
   int SocketStatus;
   EFI_STATUS Status;
 
   int SocketStatus;
   EFI_STATUS Status;
 
-  DEBUG (( DEBUG_SERVER_TIMER, "Entering WebServerTimer\r\n" ));
+  DEBUG (( DEBUG_SERVER_LISTEN, "Entering WebServerListen\r\n" ));
 
   //
 
   //
-  //  Open the HTTP port on the server
+  //  Attempt to create the socket for the web server
   //
   //
-  do {
-    do {
-      //
-      //  Complete the client operations
-      //
-      SocketPoll ( pWebServer );
-
-      //
-      //  Wait for a while
-      //
-      Status = gBS->CheckEvent ( pWebServer->TimerEvent );
-    } while ( EFI_SUCCESS != Status );
-
+  * pPort = socket ( AddressFamily, SOCK_STREAM, Protocol );
+  if ( -1 != *pPort ) {
     //
     //
-    //  Attempt to create the socket for the web server
+    //  Build the socket address
     //
     //
-    pWebServer->HttpListenPort = socket ( AF_INET,
-                                          SOCK_STREAM,
-                                          IPPROTO_TCP );
-    if ( -1 != pWebServer->HttpListenPort ) {
-      //
-      //  Set the socket address
-      //
-      ZeroMem ( &WebServerAddress, sizeof ( WebServerAddress ));
-      HttpPort = PcdGet16 ( WebServer_HttpPort );
-      DEBUG (( DEBUG_HTTP_PORT,
-                "HTTP Port: %d\r\n",
-                HttpPort ));
-      WebServerAddress.sin_len = sizeof ( WebServerAddress );
-      WebServerAddress.sin_family = AF_INET;
-      WebServerAddress.sin_addr.s_addr = INADDR_ANY;
-      WebServerAddress.sin_port = htons ( HttpPort );
+    ZeroMem ( &WebServerAddress, sizeof ( WebServerAddress ));
+    if ( AF_INET == AddressFamily ) {
+      WebServerAddress.v4.sin_len = sizeof ( WebServerAddress.v4 );
+      WebServerAddress.v4.sin_family = AddressFamily;
+      WebServerAddress.v4.sin_port = htons ( HttpPort );
+    }
+    else {
+      WebServerAddress.v6.sin6_len = sizeof ( WebServerAddress.v6 );
+      WebServerAddress.v6.sin6_family = AddressFamily;
+      WebServerAddress.v6.sin6_port = htons ( HttpPort );
+      WebServerAddress.v6.sin6_scope_id = __IPV6_ADDR_SCOPE_GLOBAL;
+    }
 
 
+    //
+    //  Bind the socket to the HTTP port
+    //
+    SocketStatus = bind ( *pPort,
+                          (struct sockaddr *) &WebServerAddress,
+                          WebServerAddress.v4.sin_len );
+    if ( -1 != SocketStatus ) {
       //
       //
-      //  Bind the socket to the HTTP port
+      //  Enable connections to the HTTP port
       //
       //
-      SocketStatus = bind ( pWebServer->HttpListenPort,
-                            (struct sockaddr *) &WebServerAddress,
-                            WebServerAddress.sin_len );
+      SocketStatus = listen ( *pPort, SOMAXCONN );
       if ( -1 != SocketStatus ) {
         //
       if ( -1 != SocketStatus ) {
         //
-        //  Enable connections to the HTTP port
+        //  Add the HTTP port to the list of ports to poll
         //
         //
-        SocketStatus = listen ( pWebServer->HttpListenPort,
-                                SOMAXCONN );
-      }
-  
-      //
-      //  Release the socket if necessary
-      //
-      if ( -1 == SocketStatus ) {
-        close ( pWebServer->HttpListenPort );
-        pWebServer->HttpListenPort = -1;
+        Status = PortAdd ( pWebServer, *pPort );
+        if ( EFI_ERROR ( Status )) {
+          SocketStatus = -1;
+        }
+        else {
+          DEBUG (( DEBUG_PORT_WORK,
+                    "Listening on Tcp%d:%d\r\n",
+                    ( AF_INET == AddressFamily ) ? 4 : 6,
+                    HttpPort ));
+        }
       }
     }
 
     //
       }
     }
 
     //
-    //  Wait until the socket is open
-    //
-  }while ( -1 == pWebServer->HttpListenPort );
-
-  DEBUG (( DEBUG_SERVER_TIMER, "Exiting WebServerTimer\r\n" ));
-}
-
-
-/**
-  Start the web server port creation timer
-
-  @param [in] pWebServer  The web server control structure address.
-
-  @retval EFI_SUCCESS         The timer was successfully started.
-  @retval EFI_ALREADY_STARTED The timer is already running.
-  @retval Other               The timer failed to start.
-
-**/
-EFI_STATUS
-WebServerTimerStart (
-  IN DT_WEB_SERVER * pWebServer
-  )
-{
-  EFI_STATUS Status;
-  UINT64 TriggerTime;
-
-  DBG_ENTER ( );
-
-  //
-  //  Assume the timer is already running
-  //
-  Status = EFI_ALREADY_STARTED;
-  if ( !pWebServer->bTimerRunning ) {
-    //
-    //  Compute the poll interval
+    //  Release the socket if necessary
     //
     //
-    TriggerTime = HTTP_PORT_POLL_DELAY * ( 1000 * 10 );
-    Status = gBS->SetTimer ( pWebServer->TimerEvent,
-                             TimerPeriodic,
-                             TriggerTime );
-    if ( !EFI_ERROR ( Status )) {
-      DEBUG (( DEBUG_HTTP_PORT, "HTTP port timer started\r\n" ));
-
-      //
-      //  Mark the timer running
-      //
-      pWebServer->bTimerRunning = TRUE;
-    }
-    else {
-      DEBUG (( DEBUG_ERROR | DEBUG_HTTP_PORT,
-                "ERROR - Failed to start HTTP port timer, Status: %r\r\n",
-                Status ));
+    if ( -1 == SocketStatus ) {
+      close ( *pPort );
+      *pPort = -1;
     }
   }
 
     }
   }
 
-  //
-  //  Return the operation status
-  //
-  DBG_EXIT_STATUS ( Status );
-  return Status;
+  DEBUG (( DEBUG_SERVER_LISTEN, "Exiting WebServerListen\r\n" ));
 }
 
 
 }
 
 
-/**
-  Stop the web server port creation timer
-
-  @param [in] pWebServer  The web server control structure address.
-
-  @retval EFI_SUCCESS   The HTTP port timer is stopped
-  @retval Other         Failed to stop the HTTP port timer
-
-**/
-EFI_STATUS
-WebServerTimerStop (
-  IN DT_WEB_SERVER * pWebServer
-  )
-{
-  EFI_STATUS Status;
-
-  DBG_ENTER ( );
-
-  //
-  //  Assume the timer is stopped
-  //
-  Status = EFI_SUCCESS;
-  if ( pWebServer->bTimerRunning ) {
-    //
-    //  Stop the port creation polling
-    //
-    Status = gBS->SetTimer ( pWebServer->TimerEvent,
-                             TimerCancel,
-                             0 );
-    if ( !EFI_ERROR ( Status )) {
-      DEBUG (( DEBUG_HTTP_PORT, "HTTP port timer stopped\r\n" ));
-
-      //
-      //  Mark the timer stopped
-      //
-      pWebServer->bTimerRunning = FALSE;
-    }
-    else {
-      DEBUG (( DEBUG_ERROR | DEBUG_HTTP_PORT,
-                "ERROR - Failed to stop HTTP port timer, Status: %r\r\n",
-                Status ));
-    }
-  }
-
-  //
-  //  Return the operation status
-  //
-  DBG_EXIT_STATUS ( Status );
-  return Status;
-}
-
 /**
   Entry point for the web server application.
 
 /**
   Entry point for the web server application.
 
@@ -776,8 +675,19 @@ main (
   IN char **Argv
   )
 {
   IN char **Argv
   )
 {
+  UINT16 HttpPort;
+  UINTN Index;
   DT_WEB_SERVER * pWebServer;
   EFI_STATUS Status;
   DT_WEB_SERVER * pWebServer;
   EFI_STATUS Status;
+  UINT64 TriggerTime;
+
+  //
+  //  Get the HTTP port
+  //
+  HttpPort = PcdGet16 ( WebServer_HttpPort );
+  DEBUG (( DEBUG_HTTP_PORT,
+            "HTTP Port: %d\r\n",
+            HttpPort ));
 
   //
   //  Create a timer event to start HTTP port
 
   //
   //  Create a timer event to start HTTP port
@@ -789,12 +699,18 @@ main (
                               NULL,
                               &pWebServer->TimerEvent );
   if ( !EFI_ERROR ( Status )) {
                               NULL,
                               &pWebServer->TimerEvent );
   if ( !EFI_ERROR ( Status )) {
-    Status = WebServerTimerStart ( pWebServer );
+    TriggerTime = HTTP_PORT_POLL_DELAY * ( 1000 * 10 );
+    Status = gBS->SetTimer ( pWebServer->TimerEvent,
+                             TimerPeriodic,
+                             TriggerTime );
     if ( !EFI_ERROR ( Status )) {
       //
       //  Run the web server forever
       //
     if ( !EFI_ERROR ( Status )) {
       //
       //  Run the web server forever
       //
-      for ( ; ; ) {
+      pWebServer->HttpListenPort = -1;
+      pWebServer->HttpListenPort6 = -1;
+      pWebServer->bRunning = TRUE;
+      do {
         //
         //  Poll the network layer to create the HTTP port
         //  for the web server.  More than one attempt may
         //
         //  Poll the network layer to create the HTTP port
         //  for the web server.  More than one attempt may
@@ -802,45 +718,72 @@ main (
         //  the IP address and initialize the upper layers
         //  of the network stack.
         //
         //  the IP address and initialize the upper layers
         //  of the network stack.
         //
-        WebServerTimer ( pWebServer );
-
-        //
-        //  Add the HTTP port to the list of ports
-        //
-        Status = PortAdd ( pWebServer, pWebServer->HttpListenPort );
-        if ( !EFI_ERROR ( Status )) {
-          //
-          //  Poll the sockets for activity
-          //
+        if (( -1 == pWebServer->HttpListenPort )
+          || ( -1 == pWebServer->HttpListenPort6 )) {
           do {
           do {
-            SocketPoll ( pWebServer );
-          } while ( -1 != pWebServer->HttpListenPort );
+            //
+            //  Wait a while before polling for a connection
+            //
+            if ( EFI_SUCCESS != gBS->CheckEvent ( pWebServer->TimerEvent )) {
+              if ( 0 != pWebServer->Entries ) {
+                  break;
+              }
+              gBS->WaitForEvent ( 1, &pWebServer->TimerEvent, &Index );
+            }
 
 
-          //
-          //  The HTTP port failed the accept and was closed
-          //
+            //
+            //  Poll for a network connection
+            //
+            if ( -1 == pWebServer->HttpListenPort ) {
+              WebServerListen ( pWebServer,
+                                AF_INET,
+                                IPPROTO_TCP,
+                                HttpPort,
+                                &pWebServer->HttpListenPort );
+            }
+            if ( -1 == pWebServer->HttpListenPort6 ) {
+              WebServerListen ( pWebServer,
+                                AF_INET6,
+                                IPPROTO_TCP,
+                                HttpPort,
+                                &pWebServer->HttpListenPort6 );
+            }
+
+            //
+            //  Continue polling while both network connections are
+            //  not present
+            //
+          } while ( 0 == pWebServer->Entries );
         }
 
         //
         }
 
         //
-        //  Close the HTTP port if necessary
+        //  Poll the sockets for activity while both network
+        //  connections are connected
         //
         //
-        if ( -1 != pWebServer->HttpListenPort ) {
-          close ( pWebServer->HttpListenPort );
-          pWebServer->HttpListenPort = -1;
-        }
-//
-// TODO: Remove the following test code
-//  Exit when the network connection is broken
-//
-break;
-      }
+        do {
+          SocketPoll ( pWebServer );
+        } while ( pWebServer->bRunning
+                && ( -1 != pWebServer->HttpListenPort )
+                && ( -1 != pWebServer->HttpListenPort6 ));
+
+        //
+        //  Continue polling the network connections until both
+        //  TCP4 and TCP6 are connected
+        //
+      } while ( pWebServer->bRunning );
 
       //
 
       //
-      //  Done with the timer event
+      //  Stop the timer
       //
       //
-      WebServerTimerStop ( pWebServer );
-      Status = gBS->CloseEvent ( pWebServer->TimerEvent );
+      gBS->SetTimer ( pWebServer->TimerEvent,
+                      TimerCancel,
+                      0 );
     }
     }
+
+    //
+    //  Done with the timer event
+    //
+    gBS->CloseEvent ( pWebServer->TimerEvent );
   }
 
   //
   }
 
   //
index 0eee114832b0318a7d9c1021c6312a0c87c5f8ca..a5dcea49698ff9fd907ea74c622202f855571852 100644 (file)
@@ -86,7 +86,7 @@
 \r
 #define DEBUG_SOCKET_POLL       0x00080000  ///<  Display the socket poll messages\r
 #define DEBUG_PORT_WORK         0x00040000  ///<  Display the port work messages\r
 \r
 #define DEBUG_SOCKET_POLL       0x00080000  ///<  Display the socket poll messages\r
 #define DEBUG_PORT_WORK         0x00040000  ///<  Display the port work messages\r
-#define DEBUG_SERVER_TIMER      0x00020000  ///<  Display the socket poll messages\r
+#define DEBUG_SERVER_LISTEN     0x00020000  ///<  Display the socket poll messages\r
 #define DEBUG_HTTP_PORT         0x00010000  ///<  Display HTTP port related messages\r
 #define DEBUG_REQUEST           0x00008000  ///<  Display the HTTP request messages\r
 \r
 #define DEBUG_HTTP_PORT         0x00010000  ///<  Display HTTP port related messages\r
 #define DEBUG_REQUEST           0x00008000  ///<  Display the HTTP request messages\r
 \r
@@ -173,9 +173,10 @@ typedef struct {
   //\r
   //  HTTP port management\r
   //\r
   //\r
   //  HTTP port management\r
   //\r
-  BOOLEAN   bTimerRunning;      ///<  Port creation timer status\r
+  BOOLEAN   bRunning;           ///<  Web server running\r
   EFI_EVENT TimerEvent;         ///<  Timer to open HTTP port\r
   EFI_EVENT TimerEvent;         ///<  Timer to open HTTP port\r
-  int       HttpListenPort;     ///<  File descriptor for the HTTP listen port\r
+  int       HttpListenPort;     ///<  File descriptor for the HTTP listen port over TCP4\r
+  int       HttpListenPort6;    ///<  File descriptor for the HTTP listen port over TCP6\r
 \r
   //\r
   //  Client port management\r
 \r
   //\r
   //  Client port management\r
@@ -377,6 +378,23 @@ DxeServicesTablePage (
   OUT BOOLEAN * pbDone\r
   );\r
 \r
   OUT BOOLEAN * pbDone\r
   );\r
 \r
+/**\r
+  Respond with the Exit page\r
+\r
+  @param [in] SocketFD      The socket's file descriptor to add to the list.\r
+  @param [in] pPort         The WSDT_PORT structure address\r
+  @param [out] pbDone       Address to receive the request completion status\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+ExitPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
 /**\r
   Respond with the firmware status\r
 \r
 /**\r
   Respond with the firmware status\r
 \r
@@ -445,6 +463,23 @@ IndexPage (
   OUT BOOLEAN * pbDone\r
   );\r
 \r
   OUT BOOLEAN * pbDone\r
   );\r
 \r
+/**\r
+  Respond with the Ports page\r
+\r
+  @param [in] SocketFD      The socket's file descriptor to add to the list.\r
+  @param [in] pPort         The WSDT_PORT structure address\r
+  @param [out] pbDone       Address to receive the request completion status\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+PortsPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
 /**\r
   Page to reboot the system\r
 \r
 /**\r
   Page to reboot the system\r
 \r
@@ -723,7 +758,7 @@ EFI_STATUS
 HttpSendIpAddress (\r
   IN int SocketFD,\r
   IN WSDT_PORT * pPort,\r
 HttpSendIpAddress (\r
   IN int SocketFD,\r
   IN WSDT_PORT * pPort,\r
-  IN struct sockaddr_in * pAddress\r
+  IN struct sockaddr_in6 * pAddress\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
index 308e4bfff2d57969a20afa4919a1912bb551755f..c250007295afcd25e329e40c3127fe57a889b58e 100644 (file)
@@ -8,7 +8,7 @@
 # license agreement                                           \r
 #\r
 #\r
 # license agreement                                           \r
 #\r
 #\r
-# Copyright (c)  20011 Intel Corporation. All rights reserved\r
+# Copyright (c)  2011 Intel Corporation. All rights reserved\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
 # This software and associated documentation (if any) is furnished\r
 # under a license and may only be used or copied in accordance\r
 # with the terms of the license. Except as permitted by such\r
   ConfigurationTable.c\r
   DhcpOptions.c\r
   DxeServicesTable.c\r
   ConfigurationTable.c\r
   DhcpOptions.c\r
   DxeServicesTable.c\r
+  Exit.c\r
   Firmware.c\r
   Handles.c\r
   Hello.c\r
   HTTP.c\r
   Index.c\r
   PageList.c\r
   Firmware.c\r
   Handles.c\r
   Hello.c\r
   HTTP.c\r
   Index.c\r
   PageList.c\r
+  Ports.c\r
   Reboot.c\r
   RuntimeServicesTable.c\r
   SystemTable.c\r
   Reboot.c\r
   RuntimeServicesTable.c\r
   SystemTable.c\r
 \r
 \r
 [Pcd]\r
 \r
 \r
 [Pcd]\r
-  gStdLibTokenSpaceGuid.WebServer_HttpPort\r
-\r
+  gAppPkgTokenSpaceGuid.WebServer_HttpPort\r
 \r
 [Packages]\r
 \r
 [Packages]\r
+  AppPkg/AppPkg.dec\r
   MdePkg/MdePkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   MdePkg/MdePkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   ShellPkg/ShellPkg.dec\r
   BsdSocketLib\r
   DebugLib\r
   DevShell\r
   BsdSocketLib\r
   DebugLib\r
   DevShell\r
-#  EfiSocketLib\r
+  EfiSocketLib\r
   LibC\r
   ShellLib\r
   ShellCEntryLib\r
   UefiBootServicesTableLib\r
   UefiLib\r
   UefiRuntimeServicesTableLib\r
   LibC\r
   ShellLib\r
   ShellCEntryLib\r
   UefiBootServicesTableLib\r
   UefiLib\r
   UefiRuntimeServicesTableLib\r
-  UseSocketDxe\r
+#  UseSocketDxe\r
 \r
 [Guids]\r
   gEfiAcpi10TableGuid\r
 \r
 [Guids]\r
   gEfiAcpi10TableGuid\r