]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add Socket Library applications.
authordarylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 30 Jul 2011 00:32:15 +0000 (00:32 +0000)
committerdarylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 30 Jul 2011 00:32:15 +0000 (00:32 +0000)
Modify AppPkg.dsc file to include StdLib.inc which contains the Boilerplate text for Standard Library based Applications.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12062 6f19259b-4bc3-4df7-8a09-765794883524

45 files changed:
AppPkg/AppPkg.dsc
AppPkg/Applications/Sockets/DataSink/DataSink.c [new file with mode: 0644]
AppPkg/Applications/Sockets/DataSink/DataSink.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/DataSource/DataSource.c [new file with mode: 0644]
AppPkg/Applications/Sockets/DataSource/DataSource.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByName/GetHostByName.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetNetByName/GetNetByName.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetServByName/GetServByName.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetServByName/GetServByName.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/GetServByPort/GetServByPort.c [new file with mode: 0644]
AppPkg/Applications/Sockets/GetServByPort/GetServByPort.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/RecvDgram/RecvDgram.c [new file with mode: 0644]
AppPkg/Applications/Sockets/RecvDgram/RecvDgram.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/SetHostName/SetHostName.c [new file with mode: 0644]
AppPkg/Applications/Sockets/SetHostName/SetHostName.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c [new file with mode: 0644]
AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/TftpServer/TftpServer.c [new file with mode: 0644]
AppPkg/Applications/Sockets/TftpServer/TftpServer.h [new file with mode: 0644]
AppPkg/Applications/Sockets/TftpServer/TftpServer.inf [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/ACPI.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/BootServicesTable.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/ConfigurationTable.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/DhcpOptions.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/DxeServicesTable.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/Firmware.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/HTTP.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/Handles.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/Hello.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/Index.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/PageList.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/Reboot.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/RuntimeServicesTable.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/SystemTable.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/WebServer.c [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/WebServer.h [new file with mode: 0644]
AppPkg/Applications/Sockets/WebServer/WebServer.inf [new file with mode: 0644]

index 7bc8f85d92268b88e54f2b70506e4924062a210f..59341ec9630d572175e1c5bd6f023af894fae8f3 100644 (file)
@@ -41,6 +41,7 @@
   #\r
   UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
   ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf\r
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf\r
   #\r
   # Common Libraries\r
   #\r
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf\r
   PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf\r
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
+\r
   ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf\r
   FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf\r
   SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf\r
-\r
-  #\r
-  # C Standard Libraries\r
-  #\r
-  LibC|StdLib/LibC/LibC.inf\r
-  LibStdLib|StdLib/LibC/StdLib/StdLib.inf\r
-  LibString|StdLib/LibC/String/String.inf\r
-  LibWchar|StdLib/LibC/Wchar/Wchar.inf\r
-  LibCType|StdLib/LibC/Ctype/Ctype.inf\r
-  LibTime|StdLib/LibC/Time/Time.inf\r
-  LibStdio|StdLib/LibC/Stdio/Stdio.inf\r
-  LibGdtoa|StdLib/LibC/gdtoa/gdtoa.inf\r
-  LibLocale|StdLib/LibC/Locale/Locale.inf\r
-  LibUefi|StdLib/LibC/Uefi/Uefi.inf\r
-  LibMath|StdLib/LibC/Math/Math.inf\r
-  LibSignal|StdLib/LibC/Signal/Signal.inf\r
-  LibNetUtil|StdLib/LibC/NetUtil/NetUtil.inf\r
-\r
-  # Libraries for device abstractions within the Standard C Library\r
-  # Applications should not directly access any functions defined in these libraries.\r
-  DevUtility|StdLib/LibC/Uefi/Devices/daUtility.inf\r
-  DevConsole|StdLib/LibC/Uefi/Devices/daConsole.inf\r
-  DevShell|StdLib/LibC/Uefi/Devices/daShell.inf\r
-\r
-[LibraryClasses.IA32]\r
-  TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf\r
-  # To run in an emulation environment, such as Nt32Pkg, comment out the TimerLib\r
-  # description above and un-comment the line below.\r
-#  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
-\r
-[LibraryClasses.X64]\r
-  TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf\r
-\r
-[LibraryClasses.IPF]\r
-  PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf\r
-  TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf\r
+  PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf\r
 \r
 ###################################################################################################\r
 #\r
 ###################################################################################################\r
 \r
 [Components]\r
-# BaseLib and BaseMemoryLib need to be built with the /GL- switch when using the Microsoft\r
-# tool chain.  This is required so that the library functions can be resolved during\r
-# the second pass of the linker during Link-time-code-generation.\r
-###\r
-  MdePkg/Library/BaseLib/BaseLib.inf {\r
-    <BuildOptions>\r
-      MSFT:*_*_*_CC_FLAGS    = /X /Zc:wchar_t /GL-\r
-  }\r
-\r
-  MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf {\r
-    <BuildOptions>\r
-      MSFT:*_*_*_CC_FLAGS    = /X /Zc:wchar_t /GL-\r
-  }\r
 \r
 #### Sample Applications.\r
   AppPkg/Applications/Hello/Hello.inf        # No LibC includes or functions.\r
   AppPkg/Applications/Main/Main.inf          # Simple invocation. No other LibC functions.\r
   AppPkg/Applications/Enquire/Enquire.inf\r
 \r
-# After extracting the Python distribution, un-comment the following line to build Python.\r
+#### After extracting the Python distribution, un-comment the following line to build Python.\r
 #  AppPkg/Applications/Python/PythonCore.inf\r
 \r
-################################################################\r
+##########\r
+#    Socket Applications - LibC based\r
+##########\r
+  AppPkg/Applications/Sockets/DataSink/DataSink.inf\r
+  AppPkg/Applications/Sockets/DataSource/DataSource.inf\r
+#  SocketPkg/Application/FtpNew/FTP.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/GetNetByAddr/GetNetByAddr.inf\r
+  AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf\r
+  AppPkg/Applications/Sockets/GetServByName/GetServByName.inf\r
+  AppPkg/Applications/Sockets/GetServByPort/GetServByPort.inf\r
+  AppPkg/Applications/Sockets/RecvDgram/RecvDgram.inf\r
+#  SocketPkg/Application/route/route.inf\r
+  AppPkg/Applications/Sockets/SetHostName/SetHostName.inf\r
+  AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.inf\r
+  AppPkg/Applications/Sockets/TftpServer/TftpServer.inf\r
+  AppPkg/Applications/Sockets/WebServer/WebServer.inf {\r
+    <PcdsFixedAtBuild>\r
+      gStdLibTokenSpaceGuid.WebServer_HttpPort|80\r
+  }\r
+\r
+###################################################################################################\r
 #\r
-# See the additional comments below if you plan to run applications under the\r
-# Nt32 emulation environment.\r
+#       Include Boilerplate text required for building with the Standard Libraries.\r
 #\r
-\r
-[BuildOptions]\r
-  INTEL:*_*_*_CC_FLAGS      = /Qfreestanding\r
-   MSFT:*_*_*_CC_FLAGS      = /X /Zc:wchar_t\r
-    GCC:*_*_*_CC_FLAGS      = -ffreestanding -nostdinc -nostdlib\r
-\r
-# The Build Options, below, are only used when building the C library\r
-# to be run under an emulation environment, such as Nt32Pkg.  The clock()\r
-# system call is modified to return -1 indicating that it is unsupported.\r
-# Just uncomment the lines below and select the correct TimerLib instance, above.\r
-\r
-  # INTEL:*_*_IA32_CC_FLAGS     = /D NT32dvm\r
-  #  MSFT:*_*_IA32_CC_FLAGS     = /D NT32dvm\r
-  #   GCC:*_*_IA32_CC_FLAGS     = -DNT32dvm\r
+###################################################################################################\r
+!include StdLib/StdLib.inc\r
diff --git a/AppPkg/Applications/Sockets/DataSink/DataSink.c b/AppPkg/Applications/Sockets/DataSink/DataSink.c
new file mode 100644 (file)
index 0000000..911cf36
--- /dev/null
@@ -0,0 +1,1029 @@
+/** @file\r
+  Data source for network testing.\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 <Uefi.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <netinet/in.h>\r
+\r
+#include <sys/EfiSysCall.h>\r
+#include <sys/poll.h>\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 AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average\r
+\r
+#define TPL_DATASINK        TPL_CALLBACK  ///<  Synchronization TPL\r
+\r
+#define PACKET_SIZE                 1448  ///<  Size of data packets\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
+  struct sockaddr_in RemoteAddress;\r
+  UINT64 Samples;\r
+} DT_PORT;\r
+\r
+volatile BOOLEAN bTick;\r
+BOOLEAN bTimerRunning;\r
+struct sockaddr_in LocalAddress;\r
+EFI_EVENT pTimer;\r
+int ListenSocket;\r
+UINT8 Buffer [ DATA_BUFFER_SIZE ];\r
+struct pollfd PollFd [ MAX_CONNECTIONS ];\r
+DT_PORT Port [ MAX_CONNECTIONS ];\r
+nfds_t MaxPort;\r
+\r
+\r
+//\r
+//  Forward routine declarations\r
+//\r
+EFI_STATUS TimerStart ( UINTN Milliseconds );\r
+\r
+\r
+/**\r
+  Check for control C entered at console\r
+\r
+  @retval  EFI_SUCCESS  Control C not entered\r
+  @retval  EFI_ABORTED  Control C entered\r
+**/\r
+EFI_STATUS\r
+ControlCCheck (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume no user intervention\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Display user stop request\r
+  //\r
+  if ( EFI_ERROR ( Status )) {\r
+    DEBUG (( DEBUG_INFO,\r
+              "User stop request!\r\n" ));\r
+  }\r
+\r
+  //\r
+  //  Return the check status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Accept a socket connection\r
+\r
+  @retval  EFI_SUCCESS      The application is running normally\r
+  @retval  EFI_NOT_STARTED  Error with the listen socket\r
+  @retval  Other            The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketAccept (\r
+  )\r
+{\r
+  INT32 SocketStatus;\r
+  EFI_STATUS Status;\r
+  INTN Index;\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  Status = EFI_DEVICE_ERROR;\r
+\r
+  //\r
+  //  Bind to the local address\r
+  //\r
+  SocketStatus = bind ( ListenSocket,\r
+                        (struct sockaddr *) &LocalAddress,\r
+                        LocalAddress.sin_len );\r
+  if ( 0 == SocketStatus ) {\r
+    //\r
+    //  Start listening on the local socket\r
+    //\r
+    SocketStatus = listen ( ListenSocket, 5 );\r
+    if ( 0 == SocketStatus ) {\r
+      //\r
+      //  Local socket in the listen state\r
+      //\r
+      Status = EFI_SUCCESS;\r
+\r
+      //\r
+      //  Allocate a port\r
+      //\r
+      Index = MaxPort++;\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
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Close the socket\r
+\r
+  @retval  EFI_SUCCESS  The application is running normally\r
+  @retval  Other        The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketClose (\r
+  )\r
+{\r
+  INT32 CloseStatus;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Determine if the socket is open\r
+  //\r
+  Status = EFI_DEVICE_ERROR;\r
+  if ( -1 != ListenSocket ) {\r
+    //\r
+    //  Attempt to close the socket\r
+    //\r
+    CloseStatus = close ( ListenSocket );\r
+    if ( 0 == CloseStatus ) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Socket closed\r\n",\r
+                ListenSocket ));\r
+      ListenSocket = -1;\r
+      Status = EFI_SUCCESS;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR: Failed to close socket, errno: %d\r\n",\r
+                errno ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Create the socket\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
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\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
+  \r
+  //\r
+  //  Loop creating the socket\r
+  //\r
+  DEBUG (( DEBUG_INFO,\r
+            "Creating the socket\r\n" ));\r
+\r
+  //\r
+  //  Check for user stop request\r
+  //\r
+  Status = ControlCCheck ( );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  Attempt to create the socket\r
+    //\r
+    ListenSocket = socket ( AF_INET,\r
+                            SOCK_STREAM,\r
+                            IPPROTO_TCP );\r
+    if ( -1 != ListenSocket ) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Socket created\r\n",\r
+                ListenSocket ));\r
+    }\r
+    else\r
+    {\r
+      Status = EFI_NOT_STARTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Poll the socket for more work\r
+\r
+  @retval  EFI_SUCCESS      The application is running normally\r
+  @retval  EFI_NOT_STARTED  Listen socket error\r
+  @retval  Other            The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketPoll (\r
+  )\r
+{\r
+  BOOLEAN bRemoveSocket;\r
+  BOOLEAN bListenError;\r
+  size_t BytesReceived;\r
+  int CloseStatus;\r
+  nfds_t Entry;\r
+  INTN EntryPrevious;\r
+  int FdCount;\r
+  nfds_t Index;\r
+  socklen_t LengthInBytes;\r
+  struct sockaddr_in RemoteAddress;\r
+  int Socket;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  //\r
+  //  Check for control-C\r
+  //\r
+  bListenError = FALSE;\r
+  Status = ControlCCheck ( );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  Poll the sockets\r
+    //\r
+    FdCount = poll ( &PollFd[0],\r
+                     MaxPort,\r
+                     0 );\r
+    if ( -1 == FdCount ) {\r
+      //\r
+      //  Poll error\r
+      //\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Poll error, errno: %d\r\n",\r
+                errno ));\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+    else {\r
+      //\r
+      //  Process the poll output\r
+      //\r
+      Index = 0;\r
+      while ( FdCount ) {\r
+        bRemoveSocket = FALSE;\r
+\r
+        //\r
+        //  Account for this descriptor\r
+        //\r
+        if ( 0 != PollFd [ Index ].revents ) {\r
+          FdCount -= 1;\r
+        }\r
+\r
+        //\r
+        //  Check for a broken connection\r
+        //\r
+        if ( 0 != ( PollFd [ Index ].revents & POLLHUP )) {\r
+          bRemoveSocket = TRUE;\r
+          if ( ListenSocket == PollFd [ Index ].fd ) {\r
+            bListenError = TRUE;\r
+            DEBUG (( DEBUG_ERROR,\r
+                      "ERROR - Network closed on listen socket, errno: %d\r\n",\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
+\r
+            //\r
+            //  Close the socket\r
+            //\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
+            }\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
+            }\r
+          }\r
+        }\r
+        \r
+        //\r
+        //  Check for a connection or read data\r
+        //\r
+        if ( 0 != ( PollFd [ Index ].revents & POLLRDNORM )) {\r
+          //\r
+          //  Check for a connection\r
+          //\r
+          if ( ListenSocket == PollFd [ Index ].fd ) {\r
+            //\r
+            //  Another client connection was received\r
+            //\r
+            LengthInBytes = sizeof ( RemoteAddress );\r
+            Socket = accept ( ListenSocket,\r
+                              (struct sockaddr *) &RemoteAddress,\r
+                              &LengthInBytes );\r
+            if ( -1 == Socket ) {\r
+              //\r
+              //  Listen socket error\r
+              //\r
+              bListenError = TRUE;\r
+              bRemoveSocket = TRUE;\r
+              DEBUG (( DEBUG_ERROR,\r
+                        "ERROR - Listen socket failure, errno: %d\r\n",\r
+                        errno ));\r
+            }\r
+            else {\r
+              //\r
+              //  Determine if there is room for this connection\r
+              //\r
+              if (( MAX_CONNECTIONS <= MaxPort )\r
+                || ((( MAX_CONNECTIONS - 1 ) == MaxPort ) && ( -1 == ListenSocket ))) {\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
+\r
+                //\r
+                //  No room for this connection\r
+                //  Close the connection\r
+                //\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
+                }\r
+                else {\r
+                  DEBUG (( DEBUG_ERROR,\r
+                            "ERROR - Failed to close socket 0x%08x, errno: %d\r\n",\r
+                            PollFd [ Index ].fd,\r
+                            errno ));\r
+                }\r
+\r
+                //\r
+                //  Keep the application running\r
+                //  No issue with the listen socket\r
+                //\r
+                Status = EFI_SUCCESS;\r
+              }\r
+              else\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
+\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
+                PollFd [ Index ].fd = Socket;\r
+                PollFd [ Index ].events = POLLRDNORM | POLLHUP;\r
+                PollFd [ Index ].revents = 0;\r
+              }\r
+            }\r
+          }\r
+          else {\r
+            //\r
+            //  Data received\r
+            //\r
+            BytesReceived = read ( PollFd [ Index ].fd,\r
+                                   &Buffer,\r
+                                   sizeof ( Buffer ));\r
+            if ( 0 < BytesReceived ) {\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
+\r
+              //\r
+              //  Synchronize with the TimerCallback routine\r
+              //\r
+              TplPrevious = gBS->RaiseTPL ( TPL_DATASINK );\r
+\r
+              //\r
+              //  Account for the data received\r
+              //\r
+              Port [ Index ].BytesTotal += BytesReceived;\r
+\r
+              //\r
+              //  Release the synchronization with the TimerCallback routine\r
+              //\r
+              gBS->RestoreTPL ( TplPrevious );\r
+            }\r
+            else if ( -1 == BytesReceived ) {\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
+              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
+              }\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
+              }\r
+            }\r
+\r
+            //\r
+            //  Keep the application running\r
+            //  No issue with the listen socket\r
+            //\r
+            Status = EFI_SUCCESS;\r
+          }\r
+        }\r
+\r
+        //\r
+        //  Remove the socket if necessary\r
+        //\r
+        if ( bRemoveSocket ) {\r
+          DEBUG (( DEBUG_INFO,\r
+                    "0x%08x: Socket removed from polling\r\n",\r
+                    PollFd [ Index ].fd ));\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
+            PollFd [ EntryPrevious ].events = PollFd [ Entry ].events;\r
+            PollFd [ EntryPrevious ].fd = PollFd [ Entry ].fd;\r
+            PollFd [ EntryPrevious ].revents = PollFd [ Entry ].revents;\r
+          }\r
+          PollFd [ MaxPort ].fd = -1;\r
+          Index -= 1;\r
+        }\r
+\r
+        //\r
+        //  Account for this socket\r
+        //\r
+        Index += 1;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the listen failure if necessary\r
+  //\r
+  if (( !EFI_ERROR ( Status )) && bListenError ) {\r
+    Status = EFI_NOT_STARTED;\r
+  }\r
+\r
+  //\r
+  //  Return the poll status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Handle the timer callback\r
+\r
+  @param [in] Event     Event that caused this callback\r
+  @param [in] pContext  Context for this routine\r
+**/\r
+VOID\r
+TimerCallback (\r
+  IN EFI_EVENT Event,\r
+  IN VOID * pContext\r
+  )\r
+{\r
+  UINT64 Average;\r
+  UINT64 BytesReceived;\r
+  UINT32 Delta;\r
+  UINT64 DeltaBytes;\r
+  nfds_t Index;\r
+\r
+  //\r
+  //  Notify the other code of the timer tick\r
+  //\r
+  bTick = TRUE;\r
+\r
+  //\r
+  //  Walk the list of ports\r
+  //\r
+  for ( Index = 0; MaxPort > Index; Index++ ) {\r
+    //\r
+    //  Determine if any data was received\r
+    //\r
+    BytesReceived = Port [ Index ].BytesTotal;\r
+    if (( ListenSocket != PollFd [ Index ].fd )\r
+      && ( 0 != BytesReceived )) {\r
+      //\r
+      //  Update the average bytes per second\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
+      //\r
+      //  Separate the samples\r
+      //\r
+      if (( 2 << AVERAGE_SHIFT_COUNT ) == Port [ Index ].Samples ) {\r
+        Print ( L"---------- Stable average ----------\r\n" );\r
+      }\r
+      Port [ Index ].Samples += 1;\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
+      }\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
+        }\r
+        else {\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
+          }\r
+          else {\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
+            }\r
+            else {\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
+              }\r
+              else {\r
+                Average >>= 10;\r
+                Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",\r
+                        Delta,\r
+                        (UINT32) Average );\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Create the timer\r
+\r
+  @retval  EFI_SUCCESS  The timer was successfully created\r
+  @retval  Other        Timer initialization failed\r
+**/\r
+EFI_STATUS\r
+TimerCreate (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Create the timer\r
+  //\r
+  Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                              TPL_DATASINK,\r
+                              TimerCallback,\r
+                              NULL,\r
+                              &pTimer );\r
+  if ( EFI_ERROR ( Status )) {\r
+    DEBUG (( DEBUG_ERROR,\r
+              "ERROR - Failed to allocate the timer event, Status: %r\r\n",\r
+              Status ));\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: Timer created\r\n",\r
+              pTimer ));\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop the timer\r
+\r
+  @retval  EFI_SUCCESS  The timer was stopped successfully\r
+  @retval  Other        The timer failed to stop\r
+**/\r
+EFI_STATUS\r
+TimerStop (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Determine if the timer is running\r
+  //\r
+  if ( bTimerRunning ) {\r
+    //\r
+    //  Stop the timer\r
+    //\r
+    Status = gBS->SetTimer ( pTimer,\r
+                             TimerCancel,\r
+                             0 );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to stop the timer, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      //\r
+      //  Timer timer is now stopped\r
+      //\r
+      bTimerRunning = FALSE;\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Timer stopped\r\n",\r
+                pTimer ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start the timer\r
+\r
+  @param [in] Milliseconds  The number of milliseconds between timer callbacks\r
+\r
+  @retval  EFI_SUCCESS  The timer was successfully created\r
+  @retval  Other        Timer initialization failed\r
+**/\r
+EFI_STATUS\r
+TimerStart (\r
+  UINTN Milliseconds\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINT64 TimeDelay;\r
+\r
+  //\r
+  //  Stop the timer if necessary\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  if ( bTimerRunning ) {\r
+    Status = TimerStop ( );\r
+  }\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  Compute the new delay\r
+    //\r
+    TimeDelay = Milliseconds;\r
+    TimeDelay *= 1000 * 10;\r
+\r
+    //\r
+    //  Start the timer\r
+    //\r
+    Status = gBS->SetTimer ( pTimer,\r
+                             TimerPeriodic,\r
+                             TimeDelay );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to start the timer, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      //\r
+      //  The timer is now running\r
+      //\r
+      bTimerRunning = TRUE;\r
+      DEBUG (( DEBUG_INFO,\r
+        "0x%08x: Timer running\r\n",\r
+        pTimer ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Destroy the timer\r
+\r
+  @retval  EFI_SUCCESS  The timer was destroyed successfully\r
+  @retval  Other        Failed to destroy the timer\r
+**/\r
+EFI_STATUS\r
+TimerDestroy (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Determine if the timer is running\r
+  //\r
+  if ( bTimerRunning ) {\r
+    //\r
+    //  Stop the timer\r
+    //\r
+    Status = TimerStop ( );\r
+  }\r
+  if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {\r
+    //\r
+    //  Done with this timer\r
+    //\r
+    Status = gBS->CloseEvent ( pTimer );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to free the timer event, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Timer Destroyed\r\n",\r
+                pTimer ));\r
+      pTimer = NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Receive data from the DataSource program to test a network's bandwidth.\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
+  EFI_STATUS Status;\r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "DataSink starting\r\n" ));\r
+\r
+  //\r
+  //  Use for/break instead of goto\r
+  //\r
+  for ( ; ; )\r
+  {\r
+    //\r
+    //  Create the timer\r
+    //\r
+    bTick = TRUE;\r
+    Status = TimerCreate ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Start a timer to perform network polling and display updates\r
+    //\r
+    Status = TimerStart ( 1 * 1000 );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Loop forever waiting for abuse\r
+    //\r
+    do {\r
+      ListenSocket = -1;\r
+      do {\r
+        //\r
+        //  Complete any client operations\r
+        //\r
+        Status = SocketPoll ( );\r
+        if ( EFI_ERROR ( Status )) {\r
+          //\r
+          //  Control-C\r
+          //\r
+          break;\r
+        }\r
+      \r
+        //\r
+        //  Wait for a while\r
+        //\r
+      } while ( !bTick );\r
+      if ( EFI_ERROR ( Status )) {\r
+        //\r
+        //  Control-C\r
+        //\r
+        break;\r
+      }\r
+      \r
+      //\r
+      //  Wait for the network layer to initialize\r
+      //\r
+      Status = SocketNew ( );\r
+      if ( EFI_ERROR ( Status )) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      //  Wait for the remote network application to start\r
+      //\r
+      Status = SocketAccept ( );\r
+      if ( EFI_NOT_STARTED == Status ) {\r
+        Status = SocketClose ( );\r
+        continue;\r
+      }\r
+      else if ( EFI_SUCCESS != Status ) {\r
+        //\r
+        //  Control-C\r
+        //\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Send data until the connection breaks\r
+      //\r
+      do {\r
+        Status = SocketPoll ( );\r
+      } while ( !EFI_ERROR ( Status ));\r
+\r
+      //\r
+      //  Done with the socket\r
+      //\r
+      Status = SocketClose ( );\r
+    } while ( !EFI_ERROR ( Status ));\r
+\r
+    //\r
+    //  Close the socket if necessary\r
+    //\r
+    SocketClose ( );\r
+\r
+    //\r
+    //  All done\r
+    //\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Stop the timer if necessary\r
+  //\r
+  TimerStop ( );\r
+  TimerDestroy ( );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DEBUG (( DEBUG_INFO,\r
+            "DataSink exiting, Status: %r\r\n",\r
+            Status ));\r
+  return Status;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/DataSink/DataSink.inf b/AppPkg/Applications/Sockets/DataSink/DataSink.inf
new file mode 100644 (file)
index 0000000..7c79ab2
--- /dev/null
@@ -0,0 +1,67 @@
+#/** @file\r
+#  DataSink 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)  20011 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                      = DataSink\r
+  FILE_GUID                      = A85DCA1B-198F-4e14-A673-874264687E85\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
+  DataSink.c\r
+\r
+\r
+[Pcd]\r
+  gStdLibTokenSpaceGuid.DataSource_Port\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
+  DebugLib\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/DataSource/DataSource.c b/AppPkg/Applications/Sockets/DataSource/DataSource.c
new file mode 100644 (file)
index 0000000..d8f7f05
--- /dev/null
@@ -0,0 +1,1615 @@
+/** @file\r
+  Data source for network testing.\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 <Uefi.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <netinet/in.h>\r
+\r
+#include <Protocol/ServiceBinding.h>\r
+#include <Protocol/Tcp4.h>\r
+\r
+#include <sys/EfiSysCall.h>\r
+#include <sys/poll.h>\r
+#include <sys/socket.h>\r
+\r
+\r
+#define RANGE_SWITCH                2048  ///<  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
+\r
+#define TPL_DATASOURCE      TPL_CALLBACK  ///<  Synchronization TPL\r
+\r
+#define PACKET_SIZE                 1448  ///<  Size of data packets\r
+#define DATA_BUFFER_SIZE    (( 65536 / PACKET_SIZE ) * PACKET_SIZE )  ///<  Buffer size in bytes\r
+\r
+\r
+//\r
+//  Socket Data\r
+//\r
+int Socket = -1;\r
+\r
+//\r
+//  TCP V4 Data\r
+//\r
+BOOLEAN bTcp4;                      ///<  TRUE if TCP4 is being used\r
+BOOLEAN bTcp4Connected;             ///<  TRUE if connected to remote system\r
+BOOLEAN bTcp4Connecting;            ///<  TRUE while connection in progress\r
+UINTN Tcp4Index;                    ///<  Index into handle array\r
+EFI_HANDLE Tcp4Controller;          ///<  Network controller handle\r
+EFI_HANDLE Tcp4Handle;              ///<  TCP4 port handle\r
+EFI_TCP4_PROTOCOL * pTcp4Protocol;  ///<  TCP4 protocol pointer\r
+EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;  ///<  TCP4 Service binding\r
+EFI_TCP4_CONFIG_DATA Tcp4ConfigData;///<  TCP4 configuration data\r
+EFI_TCP4_OPTION Tcp4Option;         ///<  TCP4 port options\r
+EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;///<  Close control\r
+EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken; ///<  Connection control\r
+EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken;      ///<  Listen control\r
+EFI_TCP4_IO_TOKEN Tcp4TxToken;      ///<  Normal data token\r
+\r
+//\r
+//  Timer Data\r
+//\r
+volatile BOOLEAN bTick;\r
+BOOLEAN bTimerRunning;\r
+EFI_EVENT pTimer;\r
+\r
+//\r
+//  Remote IP Address Data\r
+//\r
+struct sockaddr_in RemoteHostAddress;\r
+CHAR8 * pRemoteHost;\r
+\r
+//\r
+//  Traffic Data\r
+//\r
+UINT64 TotalBytesSent;\r
+UINT64 PreviousBytes;\r
+UINT64 AverageBytes;\r
+UINT64 Samples;\r
+UINT8 Buffer [ DATA_BUFFER_SIZE ];\r
+\r
+\r
+//\r
+//  Forward routine declarations\r
+//\r
+EFI_STATUS TimerStart ( UINTN Milliseconds );\r
+\r
+\r
+/**\r
+  Check for control C entered at console\r
+\r
+  @retval  EFI_SUCCESS  Control C not entered\r
+  @retval  EFI_ABORTED  Control C entered\r
+**/\r
+EFI_STATUS\r
+ControlCCheck (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume no user intervention\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Display user stop request\r
+  //\r
+  if ( EFI_ERROR ( Status )) {\r
+    DEBUG (( DEBUG_INFO,\r
+              "User stop request!\r\n" ));\r
+  }\r
+\r
+  //\r
+  //  Return the check status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get a digit\r
+\r
+  @param [in] pDigit    The address of the next digit\r
+  @param [out] pValue   The address to receive the value\r
+\r
+  @returns  Returns the address of the separator\r
+\r
+**/\r
+CHAR8 *\r
+GetDigit (\r
+  CHAR8 * pDigit,\r
+  UINT32 * pValue\r
+  )\r
+{\r
+  UINT32 Value;\r
+\r
+  //\r
+  //  Walk the digits\r
+  //\r
+  Value = 0;\r
+  while (( '0' <= *pDigit ) && ( '9' >= *pDigit ))\r
+  {\r
+    //\r
+    //  Make room for the new least significant digit\r
+    //\r
+    Value *= 10;\r
+\r
+    //\r
+    //  Convert the digit from ASCII to binary\r
+    //\r
+    Value += *pDigit - '0';\r
+\r
+    //\r
+    //  Set the next digit\r
+    //\r
+    pDigit += 1;\r
+  }\r
+\r
+  //\r
+  //  Return the value\r
+  //\r
+  *pValue = Value;\r
+\r
+  //\r
+  //  Return the next separator\r
+  //\r
+  return pDigit;\r
+}\r
+\r
+\r
+/**\r
+  Get the IP address\r
+\r
+  @retval  EFI_SUCCESS  The IP address is valid\r
+  @retval  Other        Failure to convert the IP address\r
+**/\r
+EFI_STATUS\r
+IpAddress (\r
+  )\r
+{\r
+  CHAR8 * pSeparator;\r
+  INT32 RemoteAddress;\r
+  EFI_STATUS Status;\r
+  UINT32 Value1;\r
+  UINT32 Value2;\r
+  UINT32 Value3;\r
+  UINT32 Value4;\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  Status = EFI_INVALID_PARAMETER;\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
+  }\r
+  if ( EFI_ERROR ( Status )) {\r
+    Print ( L"Invalid digit detected: %d\r\n", *pSeparator );\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Close the socket\r
+\r
+  @retval  EFI_SUCCESS  The application is running normally\r
+  @retval  Other        The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketClose (\r
+  )\r
+{\r
+  int CloseStatus;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Determine if the socket is open\r
+  //\r
+  Status = EFI_DEVICE_ERROR;\r
+  if ( -1 != Socket ) {\r
+    //\r
+    //  Attempt to close the socket\r
+    //\r
+    CloseStatus = close ( Socket );\r
+    if ( 0 == CloseStatus ) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Socket closed\r\n",\r
+                Socket ));\r
+      Socket = -1;\r
+      Status = EFI_SUCCESS;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR: Failed to close socket, errno: %d\r\n",\r
+                errno ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Connect the socket\r
+\r
+  @retval  EFI_SUCCESS  The application is running normally\r
+  @retval  Other        The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketConnect (\r
+  )\r
+{\r
+  int ConnectStatus;\r
+  UINT32 RemoteAddress;\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
+\r
+  //\r
+  //  Connect to the remote system\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  do {\r
+    //\r
+    //  Check for user stop request\r
+    //\r
+    while ( ! bTick ) {\r
+      Status = ControlCCheck ( );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+    bTick = FALSE;\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Connect to the remote system\r
+    //\r
+    ConnectStatus = connect ( Socket,\r
+                              (struct sockaddr *) &RemoteHostAddress,\r
+                              RemoteHostAddress.sin_len );\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
+    }\r
+    else {\r
+      //\r
+      //  Close the socket and try again\r
+      //\r
+      if ( EAGAIN != errno ) {\r
+        Status = EFI_NOT_STARTED;\r
+        break;\r
+      }\r
+    }\r
+  } while ( -1 == ConnectStatus );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Create the socket\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
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Loop creating the socket\r
+  //\r
+  DEBUG (( DEBUG_INFO,\r
+            "Creating the socket\r\n" ));\r
+  do {\r
+    //\r
+    //  Check for user stop request\r
+    //\r
+    Status = ControlCCheck ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Attempt to create the socket\r
+    //\r
+    Socket = socket ( AF_INET,\r
+                      SOCK_STREAM,\r
+                      IPPROTO_TCP );\r
+    if ( -1 != Socket ) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Socket created\r\n",\r
+                Socket ));\r
+      break;\r
+    }\r
+  } while ( -1 == Socket );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Send data over the socket\r
+\r
+  @retval  EFI_SUCCESS  The application is running normally\r
+  @retval  Other        The user stopped the application\r
+**/\r
+EFI_STATUS\r
+SocketSend (\r
+  )\r
+{\r
+  size_t BytesSent;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  //\r
+  //  Restart the timer\r
+  //\r
+  TimerStart ( 1000 << DATA_RATE_UPDATE_SHIFT );\r
+\r
+  //\r
+  //  Loop until the connection breaks or the user stops\r
+  //\r
+  do {\r
+    //\r
+    //  Check for user stop request\r
+    //\r
+    Status = ControlCCheck ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Send some bytes\r
+    //\r
+    BytesSent = write ( Socket, &Buffer[0], sizeof ( Buffer ));\r
+    if ( -1 == BytesSent ) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "ERROR: send failed, errno: %d\r\n",\r
+                errno ));\r
+\r
+      //\r
+      //  Try again\r
+      //\r
+      Status = EFI_SUCCESS;\r
+\r
+//\r
+//  Exit now\r
+//\r
+Status = EFI_NOT_STARTED;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Synchronize with the TimerCallback routine\r
+    //\r
+    TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
+\r
+    //\r
+    //  Account for the data sent\r
+    //\r
+    TotalBytesSent += BytesSent;\r
+\r
+    //\r
+    //  Release the TimerCallback routine synchronization\r
+    //\r
+    gBS->RestoreTPL ( TplPrevious );\r
+  } while ( !EFI_ERROR ( Status ));\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Open the network connection and send the data.\r
+\r
+  @retval EFI_SUCCESS   Continue looping\r
+  @retval other         Stopped by user's Control-C input\r
+\r
+**/\r
+EFI_STATUS\r
+SocketOpen (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Use do/while and break instead of goto\r
+  //\r
+  do\r
+  {\r
+    //\r
+    //  Wait for the network layer to initialize\r
+    //\r
+    Status = SocketNew ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Wait for the remote network application to start\r
+    //\r
+    Status = SocketConnect ( );\r
+    if ( EFI_NOT_STARTED == Status ) {\r
+      Status = SocketClose ( );\r
+      continue;\r
+    }\r
+    else if ( EFI_SUCCESS != Status ) {\r
+      //\r
+      //  Control-C\r
+      //\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Send data until the connection breaks\r
+    //\r
+    Status = SocketSend ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+  } while ( FALSE );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Close the TCP connection\r
+\r
+  @retval  EFI_SUCCESS  The application is running normally\r
+  @retval  Other        The user stopped the application\r
+**/\r
+EFI_STATUS\r
+Tcp4Close (\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINT8 * pIpAddress;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Close the port\r
+  //\r
+  if ( bTcp4Connected ) {\r
+    Tcp4CloseToken.AbortOnClose = TRUE;\r
+    Status = pTcp4Protocol->Close ( pTcp4Protocol,\r
+                                    &Tcp4CloseToken );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to start the TCP port close, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      Status = gBS->WaitForEvent ( 1,\r
+                                   &Tcp4CloseToken.CompletionToken.Event,\r
+                                    &Index );\r
+      if ( EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_ERROR,\r
+                  "ERROR - Failed to wait for close event, Status: %r\r\n",\r
+                  Status ));\r
+      }\r
+      else {\r
+        Status = Tcp4CloseToken.CompletionToken.Status;\r
+        if ( EFI_ERROR ( Status )) {\r
+          DEBUG (( DEBUG_ERROR,\r
+                    "ERROR - Failed to close the TCP port, Status: %r\r\n",\r
+                    Status ));\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_INFO,\r
+                    "0x%08x: TCP port closed\r\n",\r
+                    pTcp4Protocol ));\r
+          bTcp4Connected = FALSE;\r
+\r
+          //\r
+          //  Display the port closed message\r
+          //\r
+          pIpAddress = (UINT8 *)&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
+                  htons ( RemoteHostAddress.sin_port ));\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Release the events\r
+  //\r
+  if ( NULL != Tcp4TxToken.CompletionToken.Event ) {\r
+    Status = gBS->CloseEvent ( Tcp4TxToken.CompletionToken.Event );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: TX event closed\r\n",\r
+                Tcp4TxToken.CompletionToken.Event ));\r
+      Tcp4TxToken.CompletionToken.Event = NULL;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+  }\r
+\r
+  if ( NULL != Tcp4ListenToken.CompletionToken.Event ) {\r
+    Status = gBS->CloseEvent ( Tcp4ListenToken.CompletionToken.Event );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Listen event closed\r\n",\r
+                Tcp4ListenToken.CompletionToken.Event ));\r
+      Tcp4ListenToken.CompletionToken.Event = NULL;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+  }\r
+\r
+  if ( NULL != Tcp4ConnectToken.CompletionToken.Event ) {\r
+    Status = gBS->CloseEvent ( Tcp4ConnectToken.CompletionToken.Event );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Connect event closed\r\n",\r
+                Tcp4ConnectToken.CompletionToken.Event ));\r
+      Tcp4ConnectToken.CompletionToken.Event = NULL;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+  }\r
+\r
+  if ( NULL != Tcp4CloseToken.CompletionToken.Event ) {\r
+    Status = gBS->CloseEvent ( Tcp4CloseToken.CompletionToken.Event );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Close event closed\r\n",\r
+                Tcp4CloseToken.CompletionToken.Event ));\r
+      Tcp4CloseToken.CompletionToken.Event = NULL;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Close the TCP protocol\r
+  //\r
+  if ( NULL != pTcp4Protocol ) {\r
+    Status = gBS->CloseProtocol ( Tcp4Handle,\r
+                                  &gEfiTcp4ProtocolGuid,\r
+                                  gImageHandle,\r
+                                  NULL );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to close the TCP protocol, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: TCP4 protocol closed\r\n",\r
+                pTcp4Protocol ));\r
+      pTcp4Protocol = NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Done with the TCP service\r
+  //\r
+  if ( NULL != Tcp4Handle ) {\r
+    Status = pTcp4Service->DestroyChild ( pTcp4Service,\r
+                                          Tcp4Handle );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to release TCP service handle, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_INFO,\r
+                "Ox%08x: TCP service closed\r\n",\r
+                Tcp4Handle ));\r
+      Tcp4Handle = NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Close the service protocol\r
+  //\r
+  if ( NULL != pTcp4Service ) {\r
+    Status = gBS->CloseProtocol ( Tcp4Controller,\r
+                                  &gEfiTcp4ServiceBindingProtocolGuid,\r
+                                  gImageHandle,\r
+                                  NULL );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
+                Tcp4Controller ));\r
+      pTcp4Service = NULL;\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+  }\r
+  Tcp4Controller = NULL;\r
+  bTcp4Connecting = TRUE;\r
+\r
+  //\r
+  //  Mark the connection as closed\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Locate TCP protocol\r
+\r
+  @retval EFI_SUCCESS   Protocol found\r
+  @retval other         Protocl not found\r
+**/\r
+EFI_STATUS\r
+Tcp4Locate (\r
+  )\r
+{\r
+  UINTN HandleCount;\r
+  EFI_HANDLE * pHandles;\r
+  UINT8 * pIpAddress;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Use do/while and break instead of goto\r
+  //\r
+  do {\r
+    //\r
+    //  Attempt to locate the next TCP adapter in the system\r
+    //\r
+    Status = gBS->LocateHandleBuffer ( ByProtocol,\r
+                                       &gEfiTcp4ServiceBindingProtocolGuid,\r
+                                       NULL,\r
+                                       &HandleCount,\r
+                                       &pHandles );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_WARN,\r
+                "WARNING - No network controllers or TCP4 available, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Wrap the index if necessary\r
+    //\r
+    if ( HandleCount <= Tcp4Index ) {\r
+      Tcp4Index = 0;\r
+    \r
+      //\r
+      //  Wait for the next timer tick\r
+      //\r
+      do {\r
+      } while ( !bTick );\r
+      bTick = FALSE;\r
+    }\r
+\r
+    //\r
+    //  Display the connecting message\r
+    //\r
+    if ( bTcp4Connecting ) {\r
+      pIpAddress = (UINT8 *)&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
+              htons ( RemoteHostAddress.sin_port ));\r
+      bTcp4Connecting = FALSE;\r
+    }\r
+    \r
+    //\r
+    //  Open the network controller's service protocol\r
+    //\r
+    Tcp4Controller = pHandles [ Tcp4Index++ ];\r
+    Status = gBS->OpenProtocol (\r
+                    Tcp4Controller,\r
+                    &gEfiTcp4ServiceBindingProtocolGuid,\r
+                    (VOID **) &pTcp4Service,\r
+                    gImageHandle,\r
+                    NULL,\r
+                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",\r
+                Tcp4Controller ));\r
+      Tcp4Controller = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",\r
+              Tcp4Controller ));\r
+\r
+    //\r
+    //  Connect to the TCP service\r
+    //\r
+    Status = pTcp4Service->CreateChild ( pTcp4Service,\r
+                                         &Tcp4Handle );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to open TCP service, Status: %r\r\n",\r
+                Status ));\r
+      Tcp4Handle = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "Ox%08x: TCP service opened\r\n",\r
+              Tcp4Handle ));\r
+\r
+    //\r
+    //  Locate the TCP protcol\r
+    //\r
+    Status = gBS->OpenProtocol ( Tcp4Handle,\r
+                                 &gEfiTcp4ProtocolGuid,\r
+                                 (VOID **)&pTcp4Protocol,\r
+                                 gImageHandle,\r
+                                 NULL,\r
+                                 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to open the TCP protocol, Status: %r\r\n",\r
+                Status ));\r
+      pTcp4Protocol = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: TCP4 protocol opened\r\n",\r
+              pTcp4Protocol ));\r
+  }while ( FALSE );\r
+\r
+  //\r
+  //  Release the handle buffer\r
+  //\r
+  gBS->FreePool ( pHandles );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Send data over the TCP4 connection\r
+\r
+  @retval  EFI_SUCCESS  The application is running normally\r
+  @retval  Other        The user stopped the application\r
+**/\r
+EFI_STATUS\r
+Tcp4Send (\r
+  )\r
+{\r
+  UINTN Index;\r
+  EFI_TCP4_TRANSMIT_DATA Packet;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  //\r
+  //  Restart the timer\r
+  //\r
+  TimerStart ( 1000 << DATA_RATE_UPDATE_SHIFT );\r
+\r
+  //\r
+  //  Initialize the packet\r
+  //\r
+  Packet.DataLength = sizeof ( Buffer );\r
+  Packet.FragmentCount = 1;\r
+  Packet.Push = FALSE;\r
+  Packet.Urgent = FALSE;\r
+  Packet.FragmentTable[0].FragmentBuffer = &Buffer[0];\r
+  Packet.FragmentTable[0].FragmentLength = sizeof ( Buffer );\r
+  Tcp4TxToken.Packet.TxData = &Packet;\r
+\r
+  //\r
+  //  Loop until the connection breaks or the user stops\r
+  //\r
+  do {\r
+    //\r
+    //  Check for user stop request\r
+    //\r
+    Status = ControlCCheck ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Send some bytes\r
+    //\r
+    Status = pTcp4Protocol->Transmit ( pTcp4Protocol,\r
+                                       &Tcp4TxToken );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to start the transmit, Status: %r\r\n",\r
+                Status ));\r
+\r
+      //\r
+      //  Try again\r
+      //\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Wait for the transmit to complete\r
+    //\r
+    Status = gBS->WaitForEvent ( 1,\r
+                                 &Tcp4TxToken.CompletionToken.Event,\r
+                                 &Index );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to wait for transmit completion, Status: %r\r\n",\r
+                Status ));\r
+\r
+      //\r
+      //  Try again\r
+      //\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Get the transmit status\r
+    //\r
+    Status = Tcp4TxToken.CompletionToken.Status;\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_WARN,\r
+                "WARNING - Failed the transmission, Status: %r\r\n",\r
+                Status ));\r
+\r
+      //\r
+      //  Try again\r
+      //\r
+      Status = EFI_SUCCESS;\r
+\r
+//\r
+//  Exit now\r
+//\r
+Status = EFI_NOT_STARTED;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Synchronize with the TimerCallback routine\r
+    //\r
+    TplPrevious = gBS->RaiseTPL ( TPL_DATASOURCE );\r
+\r
+    //\r
+    //  Account for the data sent\r
+    //\r
+    TotalBytesSent += Packet.DataLength;\r
+\r
+    //\r
+    //  Release the TimerCallback routine synchronization\r
+    //\r
+    gBS->RestoreTPL ( TplPrevious );\r
+  } while ( !EFI_ERROR ( Status ));\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Open the network connection and send the data.\r
+\r
+  @retval EFI_SUCCESS   Continue looping\r
+  @retval other         Stopped by user's Control-C input\r
+\r
+**/\r
+EFI_STATUS\r
+Tcp4Open (\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINT8 * pIpAddress;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Use do/while and break instead of goto\r
+  //\r
+  do {\r
+    //\r
+    //  Locate the TCP protocol\r
+    //\r
+    Status = Tcp4Locate ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Create the necessary events\r
+    //\r
+    Status = gBS->CreateEvent ( 0,\r
+                                TPL_CALLBACK,\r
+                                NULL,\r
+                                NULL,\r
+                                &Tcp4CloseToken.CompletionToken.Event );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to create the close event, Status: %r\r\n",\r
+                Status ));\r
+      Tcp4CloseToken.CompletionToken.Event = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: Close event open\r\n",\r
+              Tcp4CloseToken.CompletionToken.Event ));\r
+\r
+    Status = gBS->CreateEvent ( 0,\r
+                                TPL_CALLBACK,\r
+                                NULL,\r
+                                NULL,\r
+                                &Tcp4ConnectToken.CompletionToken.Event );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to create the connect event, Status: %r\r\n",\r
+                Status ));\r
+      Tcp4ConnectToken.CompletionToken.Event = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: Connect event open\r\n",\r
+              Tcp4ConnectToken.CompletionToken.Event ));\r
+\r
+    Status = gBS->CreateEvent ( 0,\r
+                                TPL_CALLBACK,\r
+                                NULL,\r
+                                NULL,\r
+                                &Tcp4ListenToken.CompletionToken.Event );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to create the listen event, Status: %r\r\n",\r
+                Status ));\r
+      Tcp4ListenToken.CompletionToken.Event = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: Listen event open\r\n",\r
+              Tcp4ListenToken.CompletionToken.Event ));\r
+\r
+    Status = gBS->CreateEvent ( 0,\r
+                                TPL_CALLBACK,\r
+                                NULL,\r
+                                NULL,\r
+                                &Tcp4TxToken.CompletionToken.Event );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to create the TX event, Status: %r\r\n",\r
+                Status ));\r
+      Tcp4TxToken.CompletionToken.Event = NULL;\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: TX event open\r\n",\r
+              Tcp4TxToken.CompletionToken.Event ));\r
+\r
+    //\r
+    //  Configure the local TCP port\r
+    //\r
+    Tcp4ConfigData.TimeToLive = 255;\r
+    Tcp4ConfigData.TypeOfService = 0;\r
+    Tcp4ConfigData.ControlOption = NULL;\r
+    Tcp4ConfigData.AccessPoint.ActiveFlag = TRUE;\r
+    Tcp4ConfigData.AccessPoint.StationAddress.Addr[0] = 0;\r
+    Tcp4ConfigData.AccessPoint.StationAddress.Addr[1] = 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.UseDefaultAddress = TRUE;\r
+    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[0] = 0;\r
+    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[1] = 0;\r
+    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[2] = 0;\r
+    Tcp4ConfigData.AccessPoint.SubnetMask.Addr[3] = 0;\r
+    Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
+                                        &Tcp4ConfigData );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR, \r
+                "ERROR - Failed to configure TCP port, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: TCP4 port configured\r\n",\r
+              pTcp4Protocol ));\r
+\r
+    //\r
+    //  Connect to the remote TCP port\r
+    //\r
+    Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
+                                      &Tcp4ConnectToken );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+    Status = gBS->WaitForEvent ( 1,\r
+                                 &Tcp4ConnectToken.CompletionToken.Event,\r
+                                 &Index );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to wait for the connection, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+    Status = Tcp4ConnectToken.CompletionToken.Status;\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_WARN,\r
+                "WARNING - Failed to connect to the remote system, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: TCP4 port connected\r\n",\r
+              pTcp4Protocol ));\r
+    bTcp4Connected = TRUE;\r
+\r
+    //\r
+    //  Display the connection\r
+    //\r
+    pIpAddress = (UINT8 *)&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
+            htons ( RemoteHostAddress.sin_port ));\r
+  } while ( 0 );\r
+\r
+  if ( EFI_ERROR ( Status )) {\r
+    //\r
+    //  Try again\r
+    //\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  else {\r
+    //\r
+    //  Semd data until the connection breaks\r
+    //\r
+    Status = Tcp4Send ( );\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Handle the timer callback\r
+\r
+  @param [in] Event     Event that caused this callback\r
+  @param [in] pContext  Context for this routine\r
+**/\r
+VOID\r
+TimerCallback (\r
+  IN EFI_EVENT Event,\r
+  IN VOID * pContext\r
+  )\r
+{\r
+  UINT64 BytesSent;\r
+  UINT64 DeltaBytes;\r
+  UINT32 Delta;\r
+  UINT64 Average;\r
+\r
+  //\r
+  //  Notify the other code of the timer tick\r
+  //\r
+  bTick = TRUE;\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
+\r
+    //\r
+    //  Separate the samples\r
+    //\r
+    if (( 2 << AVERAGE_SHIFT_COUNT ) == Samples ) {\r
+      Print ( L"---------- Stable average ----------\r\n" );\r
+    }\r
+    Samples += 1;\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
+    }\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
+      }\r
+      else {\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
+        }\r
+        else {\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
+          }\r
+          else {\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
+            }\r
+            else {\r
+              Average >>= 10;\r
+              Print ( L"%d Bytes/sec, Ave: %d PiBytes/Sec\r\n",\r
+                      Delta,\r
+                      (UINT32) Average );\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Create the timer\r
+\r
+  @retval  EFI_SUCCESS  The timer was successfully created\r
+  @retval  Other        Timer initialization failed\r
+**/\r
+EFI_STATUS\r
+TimerCreate (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Create the timer\r
+  //\r
+  Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                              TPL_DATASOURCE,\r
+                              TimerCallback,\r
+                              NULL,\r
+                              &pTimer );\r
+  if ( EFI_ERROR ( Status )) {\r
+    DEBUG (( DEBUG_ERROR,\r
+              "ERROR - Failed to allocate the timer event, Status: %r\r\n",\r
+              Status ));\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_INFO,\r
+              "0x%08x: Timer created\r\n",\r
+              pTimer ));\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop the timer\r
+\r
+  @retval  EFI_SUCCESS  The timer was stopped successfully\r
+  @retval  Other        The timer failed to stop\r
+**/\r
+EFI_STATUS\r
+TimerStop (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Determine if the timer is running\r
+  //\r
+  if ( bTimerRunning ) {\r
+    //\r
+    //  Stop the timer\r
+    //\r
+    Status = gBS->SetTimer ( pTimer,\r
+                             TimerCancel,\r
+                             0 );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to stop the timer, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      //\r
+      //  Timer timer is now stopped\r
+      //\r
+      bTimerRunning = FALSE;\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Timer stopped\r\n",\r
+                pTimer ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start the timer\r
+\r
+  @param [in] Milliseconds  The number of milliseconds between timer callbacks\r
+\r
+  @retval  EFI_SUCCESS  The timer was successfully created\r
+  @retval  Other        Timer initialization failed\r
+**/\r
+EFI_STATUS\r
+TimerStart (\r
+  UINTN Milliseconds\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINT64 TimeDelay;\r
+\r
+  //\r
+  //  Stop the timer if necessary\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  if ( bTimerRunning ) {\r
+    Status = TimerStop ( );\r
+  }\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  Compute the new delay\r
+    //\r
+    TimeDelay = Milliseconds;\r
+    TimeDelay *= 1000 * 10;\r
+\r
+    //\r
+    //  Start the timer\r
+    //\r
+    Status = gBS->SetTimer ( pTimer,\r
+                             TimerPeriodic,\r
+                             TimeDelay );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to start the timer, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      //\r
+      //  The timer is now running\r
+      //\r
+      bTimerRunning = TRUE;\r
+      DEBUG (( DEBUG_INFO,\r
+        "0x%08x: Timer running\r\n",\r
+        pTimer ));\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Destroy the timer\r
+\r
+  @retval  EFI_SUCCESS  The timer was destroyed successfully\r
+  @retval  Other        Failed to destroy the timer\r
+**/\r
+EFI_STATUS\r
+TimerDestroy (\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Determine if the timer is running\r
+  //\r
+  if ( bTimerRunning ) {\r
+    //\r
+    //  Stop the timer\r
+    //\r
+    Status = TimerStop ( );\r
+  }\r
+  if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {\r
+    //\r
+    //  Done with this timer\r
+    //\r
+    Status = gBS->CloseEvent ( pTimer );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to free the timer event, Status: %r\r\n",\r
+                Status ));\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_INFO,\r
+                "0x%08x: Timer Destroyed\r\n",\r
+                pTimer ));\r
+      pTimer = NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Send data to the DataSink program to test a network's bandwidth.\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
+  EFI_STATUS (* pClose) ();\r
+  EFI_STATUS (* pOpen) ();\r
+  EFI_STATUS Status;\r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "DataSource starting\r\n" ));\r
+\r
+  //\r
+  //  Validate the command line\r
+  //\r
+  if ( 2 != Argc ) {\r
+    Print ( L"%s  <remote IP address>\r\n", Argv[0] );\r
+    return -1;\r
+  }\r
+\r
+bTcp4 = TRUE;\r
+\r
+  //\r
+  //  Determine the support routines\r
+  //\r
+  if ( bTcp4 ) {\r
+    pOpen = Tcp4Open;\r
+    pClose = Tcp4Close;\r
+    bTcp4Connecting = TRUE;\r
+  }\r
+  else {\r
+    pOpen = SocketOpen;\r
+    pClose = SocketClose;\r
+  }\r
+\r
+  //\r
+  //  Use for/break instead of goto\r
+  //\r
+  for ( ; ; )\r
+  {\r
+    //\r
+    //  No bytes sent so far\r
+    //\r
+    TotalBytesSent = 0;\r
+    AverageBytes = 0;\r
+    PreviousBytes = 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
+\r
+Print ( L"Argc: %d\r\n", Argc);\r
+Print ( L"Argv[0]: %a\r\n", Argv[0]);\r
+Print ( L"Argv[1]: %a\r\n", Argv[1]);\r
+\r
+    //\r
+    //  Get the IP address\r
+    //\r
+    pRemoteHost = Argv [1];\r
+    Status = IpAddress ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Create the timer\r
+    //\r
+    bTick = TRUE;\r
+    Status = TimerCreate ( );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Loop forever abusing the specified system\r
+    //\r
+    do {\r
+      //\r
+      //  Start a timer to perform connection polling and display updates\r
+      //\r
+      Status = TimerStart ( 2 * 1000 );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Open the network connection and send the data\r
+      //\r
+      Status = pOpen ( );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Done with the network connection\r
+      //\r
+      Status = pClose ( );\r
+    } while ( !EFI_ERROR ( Status ));\r
+\r
+    //\r
+    //  Close the network connection if necessary\r
+    //\r
+    pClose ( );\r
+\r
+    //\r
+    //  All done\r
+    //\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Stop the timer if necessary\r
+  //\r
+  TimerStop ( );\r
+  TimerDestroy ( );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DEBUG (( DEBUG_INFO,\r
+            "DataSource exiting, Status: %r\r\n",\r
+            Status ));\r
+  return Status;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/DataSource/DataSource.inf b/AppPkg/Applications/Sockets/DataSource/DataSource.inf
new file mode 100644 (file)
index 0000000..ec9cf6c
--- /dev/null
@@ -0,0 +1,70 @@
+#/** @file\r
+#  DataSource 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)  20011 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                      = DataSource\r
+  FILE_GUID                      = 30EB0F26-FC0A-4fd2-B9C9-751EA2BB1980\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
+  DataSource.c\r
+\r
+\r
+[Pcd]\r
+  gStdLibTokenSpaceGuid.DataSource_Port\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
+  EfiSocketLib\r
+  DebugLib\r
+  LibC\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\r
+#  UseSocketDxe\r
+\r
+[Protocols]\r
+  gEfiTcp4ProtocolGuid\r
+  gEfiTcp4ServiceBindingProtocolGuid\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
diff --git a/AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.c b/AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.c
new file mode 100644 (file)
index 0000000..2e62639
--- /dev/null
@@ -0,0 +1,133 @@
+/** @file\r
+  Translate the port number into a service name\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 <stdio.h>\r
+#include <string.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <arpa\nameser.h>\r
+#include <arpa\nameser_compat.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+/**\r
+  Translate the IP address into a host name\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
+  UINTN Index;\r
+  UINT8 IpAddress[4];\r
+  struct hostent * pHost;\r
+  UINT8 * pIpAddress;\r
+  char ** ppName;\r
+  UINT32 RemoteAddress[4];\r
+\r
+  //\r
+  //  Determine if the IPv4 address is specified\r
+  //\r
+  if (( 2 != Argc )\r
+    || ( 4 != sscanf ( Argv[1],\r
+                       "%d.%d.%d.%d",\r
+                       &RemoteAddress[0],\r
+                       &RemoteAddress[1],\r
+                       &RemoteAddress[2],\r
+                       &RemoteAddress[3]))\r
+    || ( 255 < RemoteAddress [0])\r
+    || ( 255 < RemoteAddress [1])\r
+    || ( 255 < RemoteAddress [2])\r
+    || ( 255 < RemoteAddress [3])) {\r
+    Print ( L"%a  <IPv4 Address>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the address into a host name\r
+    //\r
+    IpAddress[0] = (UINT8)RemoteAddress[0];\r
+    IpAddress[1] = (UINT8)RemoteAddress[1];\r
+    IpAddress[2] = (UINT8)RemoteAddress[2];\r
+    IpAddress[3] = (UINT8)RemoteAddress[3];\r
+    pHost = gethostbyaddr ( &IpAddress[0], INADDRSZ, AF_INET );\r
+    if ( NULL == pHost ) {\r
+      Print ( L"ERROR - host not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      pIpAddress = (UINT8 *)pHost->h_addr_list [ 0 ];\r
+      Print ( L"%d.%d.%d.%d, %a\r\n",\r
+              pIpAddress[0],\r
+              pIpAddress[1],\r
+              pIpAddress[2],\r
+              pIpAddress[3],\r
+              pHost->h_name );\r
+\r
+      //\r
+      //  Display the other addresses\r
+      //\r
+      for ( Index = 1; NULL != pHost->h_addr_list[Index]; Index++ ) {\r
+        pIpAddress = (UINT8 *)pHost->h_addr_list[Index];\r
+        Print ( L"%d.%d.%d.%d\r\n",\r
+                pIpAddress[0],\r
+                pIpAddress[1],\r
+                pIpAddress[2],\r
+                pIpAddress[3]);\r
+      }\r
+\r
+      //\r
+      //  Display the list of aliases\r
+      //\r
+      ppName = pHost->h_aliases;\r
+      if (( NULL == ppName ) || ( NULL == *ppName )) {\r
+        Print ( L"No aliases\r\n" );\r
+      }\r
+      else {\r
+        Print ( L"Aliases: " );\r
+        while ( NULL != *ppName ) {\r
+          //\r
+          //  Display the alias\r
+          //\r
+          Print ( L"%a", *ppName );\r
+\r
+          //\r
+          //  Set the next alias\r
+          //\r
+          ppName += 1;\r
+          if ( NULL != *ppName ) {\r
+            Print ( L", " );\r
+          }\r
+        }\r
+        Print ( L"\r\n" );\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf b/AppPkg/Applications/Sockets/GetHostByAddr/GetHostByAddr.inf
new file mode 100644 (file)
index 0000000..f31b827
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetHostByAddr 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)  20011 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                      = GetHostByAddr\r
+  FILE_GUID                      = C31A6189-639A-458b-B040-D7D506CA8F4F\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
+  GetHostByAddr.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.c b/AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.c
new file mode 100644 (file)
index 0000000..47453ac
--- /dev/null
@@ -0,0 +1,85 @@
+/** @file\r
+  Translate the host name into an IP address\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 <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+struct hostent * _gethostbydnsname(const char *, int);\r
+\r
+char mBuffer [65536];\r
+\r
+\r
+/**\r
+  Translate the host name into an IP address\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
+  UINT8 * pIpAddress;\r
+  struct hostent * pHost;\r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a starting\r\n",\r
+            Argv[0]));\r
+\r
+  //\r
+  //  Determine if the host name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 == Argc ) {\r
+    Print ( L"%a  <host name>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the host name\r
+    //\r
+    pHost = _gethostbydnsname ( Argv[1], AF_INET );\r
+    if ( NULL == pHost ) {\r
+      Print ( L"ERROR - host not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      pIpAddress = (UINT8 *)pHost->h_addr;\r
+      Print ( L"%a: Type %d, %d.%d.%d.%d\r\n",\r
+              pHost->h_name,\r
+              pHost->h_addrtype,\r
+              pIpAddress[0],\r
+              pIpAddress[1],\r
+              pIpAddress[2],\r
+              pIpAddress[3]);\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf b/AppPkg/Applications/Sockets/GetHostByDns/GetHostByDns.inf
new file mode 100644 (file)
index 0000000..417eb5e
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetHostByDns 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)  20011 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                      = GetHostByDns\r
+  FILE_GUID                      = 3698D2B0-E727-4537-A636-A8770736ABFB\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
+  GetHostByDns.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/GetHostByName/GetHostByName.c b/AppPkg/Applications/Sockets/GetHostByName/GetHostByName.c
new file mode 100644 (file)
index 0000000..d539c99
--- /dev/null
@@ -0,0 +1,123 @@
+/** @file\r
+  Translate the host name into an IP address\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 <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer [65536];\r
+\r
+\r
+/**\r
+  Translate the host name into an IP address\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
+  UINTN Index;\r
+  struct hostent * pHost;\r
+  UINT8 * pIpAddress;\r
+  char ** ppName;\r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a starting\r\n",\r
+            Argv[0]));\r
+\r
+  //\r
+  //  Determine if the host name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 == Argc ) {\r
+    Print ( L"%a  <host name>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the host name\r
+    //\r
+    pHost = gethostbyname ( Argv[1]);\r
+    if ( NULL == pHost ) {\r
+      Print ( L"ERROR - host not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      pIpAddress = (UINT8 *)pHost->h_addr;\r
+      Print ( L"%d.%d.%d.%d, Type %d, %a\r\n",\r
+              pIpAddress[0],\r
+              pIpAddress[1],\r
+              pIpAddress[2],\r
+              pIpAddress[3],\r
+              pHost->h_addrtype,\r
+              pHost->h_name );\r
+\r
+      //\r
+      //  Display the other addresses\r
+      //\r
+      for ( Index = 1; NULL != pHost->h_addr_list[Index]; Index++ ) {\r
+        pIpAddress = (UINT8 *)pHost->h_addr_list[Index];\r
+        Print ( L"%d.%d.%d.%d\r\n",\r
+                pIpAddress[0],\r
+                pIpAddress[1],\r
+                pIpAddress[2],\r
+                pIpAddress[3]);\r
+      }\r
+\r
+      //\r
+      //  Display the list of aliases\r
+      //\r
+      ppName = pHost->h_aliases;\r
+      if (( NULL == ppName ) || ( NULL == *ppName )) {\r
+        Print ( L"No aliases\r\n" );\r
+      }\r
+      else {\r
+        Print ( L"Aliases: " );\r
+        while ( NULL != *ppName ) {\r
+          //\r
+          //  Display the alias\r
+          //\r
+          Print ( L"%a", *ppName );\r
+\r
+          //\r
+          //  Set the next alias\r
+          //\r
+          ppName += 1;\r
+          if ( NULL != *ppName ) {\r
+            Print ( L", " );\r
+          }\r
+        }\r
+        Print ( L"\r\n" );\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf b/AppPkg/Applications/Sockets/GetHostByName/GetHostByName.inf
new file mode 100644 (file)
index 0000000..48beb2a
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetHostByName 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)  20011 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                      = GetHostByName\r
+  FILE_GUID                      = 70FB9CE0-2CB1-4fd7-80EE-AB4B6CF4B43F\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
+  GetHostByName.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.c b/AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.c
new file mode 100644 (file)
index 0000000..51d8c6d
--- /dev/null
@@ -0,0 +1,89 @@
+/** @file\r
+  Translate the IPv4 address into a network name\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 <stdio.h>\r
+#include <string.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+/**\r
+  Translate the IPv4 address into a network name\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
+  UINT32 RemoteAddress[4];\r
+  UINT8 IpAddress[4];\r
+  struct netent * pNetwork;\r
+  \r
+  //\r
+  //  Determine if the IPv4 address is specified\r
+  //\r
+  if (( 2 != Argc )\r
+    || ( 4 != sscanf ( Argv[1],\r
+                       "%d.%d.%d.%d",\r
+                       &RemoteAddress[0],\r
+                       &RemoteAddress[1],\r
+                       &RemoteAddress[2],\r
+                       &RemoteAddress[3]))\r
+    || ( 255 < RemoteAddress [0])\r
+    || ( 255 < RemoteAddress [1])\r
+    || ( 255 < RemoteAddress [2])\r
+    || ( 255 < RemoteAddress [3])) {\r
+    Print ( L"%a  <IPv4 Address>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the address into a network name\r
+    //\r
+    IpAddress[0] = (UINT8)RemoteAddress[0];\r
+    IpAddress[1] = (UINT8)RemoteAddress[1];\r
+    IpAddress[2] = (UINT8)RemoteAddress[2];\r
+    IpAddress[3] = (UINT8)RemoteAddress[3];\r
+    pNetwork = getnetbyaddr ( *(uint32_t *)&IpAddress[0], AF_INET );\r
+    if ( NULL == pNetwork ) {\r
+      Print ( L"ERROR - network not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      Print ( L"%a: %d.%d.%d.%d, 0x%08x\r\n",\r
+              pNetwork->n_name,\r
+              IpAddress[0],\r
+              IpAddress[1],\r
+              IpAddress[2],\r
+              IpAddress[3],\r
+              pNetwork->n_net );\r
+    }\r
+  }\r
+  \r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf b/AppPkg/Applications/Sockets/GetNetByAddr/GetNetByAddr.inf
new file mode 100644 (file)
index 0000000..c280d18
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetNetByAddr 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)  20011 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                      = GetNetByAddr\r
+  FILE_GUID                      = 22198FD5-4835-4842-BF31-EB957C7DD70D\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
+  GetNetByAddr.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/GetNetByName/GetNetByName.c b/AppPkg/Applications/Sockets/GetNetByName/GetNetByName.c
new file mode 100644 (file)
index 0000000..b3609c9
--- /dev/null
@@ -0,0 +1,83 @@
+/** @file\r
+  Translate the network name into an IP address\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 <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer [65536];\r
+\r
+\r
+/**\r
+  Translate the network name into an IP address\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
+  UINT8 * pIpAddress;\r
+  struct netent * pNetwork;\r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a starting\r\n",\r
+            Argv[0]));\r
+\r
+  //\r
+  //  Determine if the network name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 == Argc ) {\r
+    Print ( L"%a  <network name>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the net name\r
+    //\r
+    pNetwork = getnetbyname ( Argv[1]);\r
+    if ( NULL == pNetwork ) {\r
+      Print ( L"ERROR - network not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      pIpAddress = (UINT8 *)pNetwork->n_net;\r
+      Print ( L"%a: Type %d, %d.%d.%d.%d\r\n",\r
+              pNetwork->n_name,\r
+              pNetwork->n_addrtype,\r
+              pIpAddress[0],\r
+              pIpAddress[1],\r
+              pIpAddress[2],\r
+              pIpAddress[3]);\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf b/AppPkg/Applications/Sockets/GetNetByName/GetNetByName.inf
new file mode 100644 (file)
index 0000000..1b9764e
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetNetByName 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)  20011 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                      = GetNetByName\r
+  FILE_GUID                      = DAF7B0E6-32DE-4619-B63A-2B9173A75B14\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
+  GetNetByName.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/GetServByName/GetServByName.c b/AppPkg/Applications/Sockets/GetServByName/GetServByName.c
new file mode 100644 (file)
index 0000000..d7237d3
--- /dev/null
@@ -0,0 +1,76 @@
+/** @file\r
+  Translate the service name into a port number\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 <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer [65536];\r
+\r
+\r
+/**\r
+  Translate the service name into a port number\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 PortNumber;\r
+  struct servent * pService;\r
+\r
+  //\r
+  //  Determine if the service name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 == Argc ) {\r
+    Print ( L"%a  <service name>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the service name\r
+    //\r
+    pService = getservbyname ( Argv[1], NULL );\r
+    if ( NULL == pService ) {\r
+      Print ( L"ERROR - service not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      PortNumber = htons ( pService->s_port );\r
+      Print ( L"%a: %d, %a\r\n",\r
+              pService->s_name,\r
+              PortNumber,\r
+              pService->s_proto );\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetServByName/GetServByName.inf b/AppPkg/Applications/Sockets/GetServByName/GetServByName.inf
new file mode 100644 (file)
index 0000000..290d15e
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetServByName 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)  20011 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                      = GetServByName\r
+  FILE_GUID                      = 5D1F3F9E-8CEE-4299-93C2-4C64EBB58977\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
+  GetServByName.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/GetServByPort/GetServByPort.c b/AppPkg/Applications/Sockets/GetServByPort/GetServByPort.c
new file mode 100644 (file)
index 0000000..6a5fc46
--- /dev/null
@@ -0,0 +1,77 @@
+/** @file\r
+  Translate the port number into a service name\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 <stdio.h>\r
+#include <string.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer [65536];\r
+\r
+\r
+/**\r
+  Translate the port number into a service name\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 PortNumber;\r
+  struct servent * pService;\r
+\r
+  //\r
+  //  Determine if the service name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if (( 2 != Argc )\r
+    || ( 1 != sscanf ( Argv[1], "%d", &PortNumber ))) {\r
+    Print ( L"%a  <port number>\r\n", Argv[0]);\r
+  }\r
+  else {\r
+    //\r
+    //  Translate the port number\r
+    //\r
+    pService = getservbyport ( htons ( PortNumber ), NULL );\r
+    if ( NULL == pService ) {\r
+      Print ( L"ERROR - service not found, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      Print ( L"%a: %d, %a\r\n",\r
+              pService->s_name,\r
+              PortNumber,\r
+              pService->s_proto );\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/GetServByPort/GetServByPort.inf b/AppPkg/Applications/Sockets/GetServByPort/GetServByPort.inf
new file mode 100644 (file)
index 0000000..1a232c0
--- /dev/null
@@ -0,0 +1,65 @@
+#/** @file\r
+#  GetServByPort 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)  20011 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                      = GetServByPort\r
+  FILE_GUID                      = 83381B06-2EEA-4cf3-9B5F-D75B9B5C93DE\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
+  GetServByPort.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  LibNetUtil\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/RecvDgram/RecvDgram.c b/AppPkg/Applications/Sockets/RecvDgram/RecvDgram.c
new file mode 100644 (file)
index 0000000..7809e80
--- /dev/null
@@ -0,0 +1,116 @@
+/** @file\r
+  Receive a datagram\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 <string.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <netinet/in.h>\r
+\r
+#include <sys/socket.h>\r
+#include <sys/time.h>\r
+\r
+UINT8 mBuffer [ 65536 ];\r
+\r
+/**\r
+  Receive a datagram\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
+  struct sockaddr_in Address;\r
+  socklen_t AddressLength;\r
+  ssize_t LengthInBytes;\r
+  int s;\r
+  int Status;\r
+  struct timeval Timeout;\r
+  \r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a starting\r\n",\r
+            Argv[0]));\r
+\r
+  //\r
+  //  Get the socket\r
+  //\r
+  s = socket ( AF_INET, SOCK_DGRAM, 0 );\r
+  if ( -1 == s ) {\r
+    Print ( L"ERROR - Unable to open the socket, errno: %d\r\n", errno );\r
+  }\r
+  else {\r
+    Timeout.tv_sec = 5;\r
+    Timeout.tv_usec = 0;\r
+    Status = setsockopt ( s,\r
+                          SOL_SOCKET,\r
+                          SO_RCVTIMEO,\r
+                          &Timeout,\r
+                          sizeof ( Timeout ));\r
+    if ( -1 == Status ) {\r
+      Print ( L"ERROR - Unable to set the receive timeout, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      AddressLength = sizeof ( Address );\r
+      LengthInBytes = recvfrom ( s,\r
+                                 &mBuffer[0],\r
+                                 sizeof ( mBuffer[0]),\r
+                                 0,\r
+                                 (struct sockaddr *)&Address,\r
+                                 &AddressLength );\r
+      if ( -1 == LengthInBytes ) {\r
+        if ( ETIMEDOUT == errno ) {\r
+          Print ( L"No datagram received\r\n" );\r
+        }\r
+        else {\r
+          Print ( L"ERROR - No datagram received, errno: %d\r\n", errno );\r
+        }\r
+      }\r
+      else {\r
+        Print ( L"Received %d bytes from %d.%d.%d.%d:%d\r\n",\r
+                LengthInBytes,\r
+                (UINT8)Address.sin_addr.s_addr,\r
+                (UINT8)( Address.sin_addr.s_addr >> 8 ),\r
+                (UINT8)( Address.sin_addr.s_addr >> 16 ),\r
+                (UINT8)( Address.sin_addr.s_addr >> 24 ),\r
+                htons ( Address.sin_port ));\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Done with the socket\r
+    //\r
+    close ( s );\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a exiting, errno: %d\r\n",\r
+            Argv[0],\r
+            errno ));\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/RecvDgram/RecvDgram.inf b/AppPkg/Applications/Sockets/RecvDgram/RecvDgram.inf
new file mode 100644 (file)
index 0000000..bef842a
--- /dev/null
@@ -0,0 +1,64 @@
+#/** @file\r
+#  Receive Datagram 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)  20011 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                      = RecvDgram\r
+  FILE_GUID                      = 929189C9-0670-4c0b-AF7D-135D1550C8C0\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
+  RecvDgram.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/SetHostName/SetHostName.c b/AppPkg/Applications/Sockets/SetHostName/SetHostName.c
new file mode 100644 (file)
index 0000000..85dc1c4
--- /dev/null
@@ -0,0 +1,100 @@
+/** @file\r
+  Set the host name\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 <string.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+\r
+char mBuffer [65536];\r
+\r
+\r
+/**\r
+  Set the host name\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
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a starting\r\n",\r
+            Argv[0]));\r
+\r
+  //\r
+  //  Determine if the host name is specified\r
+  //\r
+  AppStatus = 0;\r
+  if ( 1 < Argc ) {\r
+    //\r
+    //  Set the host name\r
+    //\r
+    AppStatus = sethostname ( Argv[1], strlen ( Argv[1]));\r
+    if ( -1 == AppStatus ) {\r
+      switch ( errno ) {\r
+      default:\r
+        Print ( L"ERROR - errno: %d\r\n", errno );\r
+        break;\r
+\r
+      case ENODEV:\r
+        Print ( L"WARNING - Plarform does not support permanent storage!\r\n" );\r
+        break;\r
+\r
+      case ENOMEM:\r
+        Print ( L"ERROR - Insufficient storage to save host name!\r\n" );\r
+        break;\r
+\r
+      case ENOTSUP:\r
+        Print ( L"ERROR - Platform does not support environment variable storage!\r\n" );\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  else {\r
+    //\r
+    //  Display the current host name\r
+    //\r
+    AppStatus = gethostname ( &mBuffer[0], sizeof ( mBuffer ));\r
+    if ( -1 == AppStatus ) {\r
+      Print ( L"ERROR - Unable to get host name, errno: %d\r\n", errno );\r
+    }\r
+    else {\r
+      if ( 0 == mBuffer[0]) {\r
+        Print ( L"Host name is not set!\r\n" );\r
+      }\r
+      else {\r
+        Print ( L"Host name: %a", &mBuffer[0]);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/SetHostName/SetHostName.inf b/AppPkg/Applications/Sockets/SetHostName/SetHostName.inf
new file mode 100644 (file)
index 0000000..2b0bdc7
--- /dev/null
@@ -0,0 +1,64 @@
+#/** @file\r
+#  SetHostName 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)  20011 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                      = SetHostName\r
+  FILE_GUID                      = 4BC80B15-255D-4858-8072-51D6D98CF90E\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
+  SetHostName.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c b/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.c
new file mode 100644 (file)
index 0000000..fdc4552
--- /dev/null
@@ -0,0 +1,379 @@
+/** @file\r
+  Set the socket options\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 <stdio.h>\r
+#include <string.h>\r
+#include <Uefi.h>\r
+#include <unistd.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <sys/socket.h>\r
+#include <sys/time.h>\r
+\r
+typedef enum _DATA_TYPE {\r
+  DATA_TYPE_UNKNOWN = 0,\r
+  DATA_TYPE_INT32_DECIMAL,\r
+  DATA_TYPE_SOCKET_TYPE,\r
+  DATA_TYPE_TIMEVAL\r
+} DATA_TYPE;\r
+\r
+typedef struct {\r
+  char * pOptionName;\r
+  int OptionValue;\r
+  int OptionLevel;\r
+  BOOLEAN bSetAllowed;\r
+  DATA_TYPE DataType;\r
+} OPTIONS;\r
+\r
+CONST OPTIONS mOptions [] = {\r
+  { "SO_ACCEPTCONN", SO_ACCEPTCONN, SOL_SOCKET, FALSE, DATA_TYPE_UNKNOWN },\r
+  { "SO_BROADCAST", SO_BROADCAST, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_DEBUG", SO_DEBUG, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_DONTROUTE", SO_DONTROUTE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_ERROR", SO_ERROR, SOL_SOCKET, FALSE, DATA_TYPE_UNKNOWN },\r
+  { "SO_KEEPALIVE", SO_KEEPALIVE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_OOBINLINE", SO_OOBINLINE, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_OVERFLOWED", SO_OVERFLOWED, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_RCVBUF", SO_RCVBUF, SOL_SOCKET, TRUE, DATA_TYPE_INT32_DECIMAL },\r
+  { "SO_RCVLOWAT", SO_RCVLOWAT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_RCVTIMEO", SO_RCVTIMEO, SOL_SOCKET, TRUE, DATA_TYPE_TIMEVAL },\r
+  { "SO_REUSEADDR", SO_REUSEADDR, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_REUSEPORT", SO_REUSEPORT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_SNDBUF", SO_SNDBUF, SOL_SOCKET, TRUE, DATA_TYPE_INT32_DECIMAL },\r
+  { "SO_SNDLOWAT", SO_SNDLOWAT, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_SNDTIMEO", SO_SNDTIMEO, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_TIMESTAMP", SO_TIMESTAMP, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN },\r
+  { "SO_TYPE", SO_TYPE, SOL_SOCKET, FALSE, DATA_TYPE_SOCKET_TYPE },\r
+  { "SO_USELOOPBACK", SO_USELOOPBACK, SOL_SOCKET, TRUE, DATA_TYPE_UNKNOWN }\r
+};\r
+\r
+\r
+UINT8 mBuffer [ 65536 ];\r
+UINT8 mValue [ 65536 ];\r
+char * mSocketType [] = {\r
+  "SOCK_STREAM",\r
+  "SOCK_DGRAM",\r
+  "SOCK_RAW",\r
+  "SOCK_RDM",\r
+  "SOCK_SEQPACKET"\r
+};\r
+\r
+void\r
+DisplayOption (\r
+  CONST OPTIONS * pOption,\r
+  socklen_t LengthInBytes,\r
+  BOOLEAN bDisplayUpdate,\r
+  BOOLEAN bDisplayCrLf\r
+  )\r
+{\r
+  UINT8 * pEnd;\r
+  char * pString;\r
+  union {\r
+    UINT8 * u8;\r
+    INT32 * i32;\r
+    struct timeval * TimeVal;\r
+  } Value;\r
+\r
+  //\r
+  //  Display the value length\r
+  //\r
+  if ( !bDisplayUpdate ) {\r
+    Print ( L"LengthInBytes: %d\r\n", LengthInBytes );\r
+    Print ( L"%a: ", pOption->pOptionName );\r
+  }\r
+  else {\r
+    Print ( L" --> " );\r
+  }\r
+\r
+  //\r
+  //  Display the value\r
+  //\r
+  Value.u8 = &mBuffer[0];\r
+  switch ( pOption->DataType )\r
+  {\r
+  case DATA_TYPE_UNKNOWN:\r
+    Print ( L"%a:", pOption->pOptionName );\r
+    pEnd = &Value.u8 [ LengthInBytes ];\r
+    while ( pEnd > Value.u8 ) {\r
+      Print ( L" %02x", *Value.u8 );\r
+      Value.u8 += 1;\r
+    }\r
+    break;\r
+    \r
+  case DATA_TYPE_INT32_DECIMAL:\r
+    if ( 4 == LengthInBytes ) {\r
+      Print ( L"%d", *Value.i32 );\r
+    }\r
+    else {\r
+      errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
+      Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
+    }\r
+    break;\r
+\r
+  case DATA_TYPE_SOCKET_TYPE:\r
+    if ( 4 == LengthInBytes ) {\r
+      if (( SOCK_STREAM <= *Value.i32 ) && ( SOCK_SEQPACKET >= *Value.i32 )) {\r
+        pString = mSocketType [ *Value.i32 - SOCK_STREAM ];\r
+        Print ( L"%a", pString );\r
+      }\r
+      else {\r
+        Print ( L"%08x (unknown type)", *Value.i32 );\r
+      }\r
+    }\r
+    else {\r
+      errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
+      Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
+    }\r
+    break;\r
+\r
+  case DATA_TYPE_TIMEVAL:\r
+    if ( sizeof ( *Value.TimeVal ) == LengthInBytes ) {\r
+      if (( 0 == Value.TimeVal->tv_sec )\r
+        && ( 0 == Value.TimeVal->tv_usec )) {\r
+        Print ( L"Infinite" );\r
+      }\r
+      else {\r
+        Print ( L"%d.%06d sec",\r
+                Value.TimeVal->tv_sec,\r
+                Value.TimeVal->tv_usec );\r
+      }\r
+    }\r
+    else {\r
+      errno = ( 4 > LengthInBytes ) ? EBUFSIZE : ERANGE;\r
+      Print ( L"\r\nERROR - Invalid length, errno: %d\r\n", errno );\r
+    }\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Terminate the line\r
+  //\r
+  if ( bDisplayCrLf ) {\r
+    Print ( L"\r\n" );\r
+  }\r
+}\r
+\r
+socklen_t\r
+GetOptionValue (\r
+  CONST OPTIONS * pOption,\r
+  char * pValue\r
+  )\r
+{\r
+  socklen_t BytesToWrite;\r
+  union {\r
+    UINT8 * u8;\r
+    INT32 * i32;\r
+    struct timeval * TimeVal;\r
+  } Value;\r
+  int Values;\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  errno = EINVAL;\r
+  BytesToWrite = 0;\r
+\r
+  //\r
+  //  Determine the type of parameter\r
+  //\r
+  if ( pOption->bSetAllowed ) {\r
+    Value.u8 = &mValue[0];\r
+    switch ( pOption->DataType ) {\r
+    case DATA_TYPE_INT32_DECIMAL:\r
+      Values = sscanf ( pValue, "%d", Value.i32 );\r
+      if ( 1 == Values ) {\r
+        BytesToWrite = sizeof ( *Value.i32);\r
+        errno = 0;\r
+      }\r
+      break;\r
+\r
+    case DATA_TYPE_TIMEVAL:\r
+      Values = sscanf ( pValue, "%d.%0d",\r
+                        &Value.TimeVal->tv_sec,\r
+                        &Value.TimeVal->tv_usec );\r
+      if (( 2 == Values )\r
+        && ( 0 <= Value.TimeVal->tv_sec )\r
+        && ( 0 <= Value.TimeVal->tv_usec )\r
+        && ( 1000000 > Value.TimeVal->tv_usec )){\r
+        BytesToWrite = sizeof ( *Value.TimeVal );\r
+        errno = 0;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Display the error\r
+  //\r
+  if ( 0 == BytesToWrite ) {\r
+    Print ( L"ERROR - Invalid value!\r\n" );\r
+  }\r
+\r
+  //\r
+  //  Return the number of bytes to be written\r
+  //\r
+  return BytesToWrite;\r
+}\r
+\r
+\r
+/**\r
+  Set the socket options\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
+  socklen_t BytesToWrite;\r
+  socklen_t LengthInBytes;\r
+  CONST OPTIONS * pEnd;\r
+  CONST OPTIONS * pOption;\r
+  int s;\r
+  int Status;\r
+\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a starting\r\n",\r
+            Argv[0]));\r
+\r
+  //\r
+  //  Parse the socket option\r
+  //\r
+  pOption = &mOptions[0];\r
+  pEnd = &pOption[sizeof ( mOptions ) / sizeof ( mOptions[0])];\r
+  if ( 2 <= Argc ) {\r
+    while ( pEnd > pOption ) {\r
+      if ( 0 == strcmp ( Argv[1], pOption->pOptionName )) {\r
+        break;\r
+      }\r
+      pOption += 1;\r
+    }\r
+    if ( pEnd <= pOption ) {\r
+      Print ( L"ERROR: Invalid option: %a\r\n", Argv[1]);\r
+      Argc = 1;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Display the help if necessary\r
+  //\r
+  if (( 2 > Argc ) || ( 3 < Argc )) {\r
+    Print ( L"%a <option>\r\n", Argv[0]);\r
+    Print ( L"\r\n" );\r
+    Print ( L"Option one of:\r\n" );\r
+    pOption = &mOptions[0];\r
+    while ( pEnd > pOption ) {\r
+      Print ( L"   %a: %a\r\n",\r
+              pOption->pOptionName,\r
+              pOption->bSetAllowed ? "get/set" : "get" );\r
+      pOption += 1;\r
+    }\r
+    errno = EINVAL;\r
+  }\r
+  else {\r
+    //\r
+    //  Determine if the value is to be set\r
+    //\r
+    BytesToWrite = 0;\r
+    if (( 3 > Argc )\r
+      || ( 0 < ( BytesToWrite = GetOptionValue ( pOption, Argv [2])))) {\r
+      //\r
+      //  Get the socket\r
+      //\r
+      s = socket ( AF_INET, 0, 0 );\r
+      if ( -1 == s ) {\r
+        Print ( L"ERROR - Unable to open the socket, errno: %d\r\n", errno );\r
+      }\r
+      else {\r
+        //\r
+        //  Display the option value\r
+        //\r
+        LengthInBytes = sizeof ( mBuffer );\r
+        Status = getsockopt ( s,\r
+                              pOption->OptionLevel,\r
+                              pOption->OptionValue,\r
+                              &mBuffer,\r
+                              &LengthInBytes );\r
+        if ( -1 == Status ) {\r
+          Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
+        }\r
+        else {\r
+          DisplayOption ( pOption,\r
+                          LengthInBytes,\r
+                          FALSE,\r
+                          (BOOLEAN)( 0 == BytesToWrite ));\r
+\r
+          //\r
+          //  Determine if the value is to be set\r
+          //\r
+          if (( 0 < BytesToWrite )\r
+              && ( BytesToWrite == LengthInBytes )) {\r
+            //\r
+            //  Set the option value\r
+            //\r
+            Status = setsockopt ( s,\r
+                                  pOption->OptionLevel,\r
+                                  pOption->OptionValue,\r
+                                  &mValue,\r
+                                  BytesToWrite );\r
+            if ( -1 == Status ) {\r
+              Print ( L"ERROR - setsockopt failed, errno: %d\r\n", errno );\r
+            }\r
+            else {\r
+              //\r
+              //  Display the updated option value\r
+              //\r
+              Status = getsockopt ( s,\r
+                                    pOption->OptionLevel,\r
+                                    pOption->OptionValue,\r
+                                    &mBuffer,\r
+                                    &LengthInBytes );\r
+              if ( -1 == Status ) {\r
+                Print ( L"ERROR - getsockopt failed, errno: %d\r\n", errno );\r
+              }\r
+              else {\r
+                DisplayOption ( pOption,\r
+                                LengthInBytes,\r
+                                TRUE,\r
+                                TRUE );\r
+              }\r
+            }\r
+          }\r
+        }\r
+\r
+        //\r
+        //  Done with the socket\r
+        //\r
+        close ( s );\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  All done\r
+  //\r
+  DEBUG (( DEBUG_INFO,\r
+            "%a exiting, errno: %d\r\n",\r
+            Argv[0],\r
+            errno ));\r
+  return errno;\r
+}\r
diff --git a/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.inf b/AppPkg/Applications/Sockets/SetSockOpt/SetSockOpt.inf
new file mode 100644 (file)
index 0000000..835e1eb
--- /dev/null
@@ -0,0 +1,64 @@
+#/** @file\r
+#  SetHostName 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)  20011 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                      = SetSockOpt\r
+  FILE_GUID                      = 6E851687-A7A9-4aa2-8DD0-673E03E51433\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
+  SetSockOpt.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  LibMath\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\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
diff --git a/AppPkg/Applications/Sockets/TftpServer/TftpServer.c b/AppPkg/Applications/Sockets/TftpServer/TftpServer.c
new file mode 100644 (file)
index 0000000..a1e19c2
--- /dev/null
@@ -0,0 +1,1527 @@
+/*++
+  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
+  This is a simple TFTP server application
+
+**/
+
+#include <TftpServer.h>
+
+TSDT_TFTP_SERVER mTftpServer; ///<  TFTP server's control structure
+
+
+/**
+  Add a connection context to the list of connection contexts.
+
+  @param [in] pTftpServer   The TFTP server control structure address.
+
+  @retval Context structure address, NULL if allocation fails
+
+**/
+TSDT_CONNECTION_CONTEXT *
+ContextAdd (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  size_t LengthInBytes;
+  TSDT_CONNECTION_CONTEXT * pContext;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Allocate a new context
+    //
+    LengthInBytes = sizeof ( *pContext );
+    Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+                                 LengthInBytes,
+                                 (VOID **)&pContext );
+    if ( EFI_ERROR ( Status )) {
+      DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+                "ERROR - Failed to allocate the context, Status: %r\r\n",
+                Status ));
+      pContext = NULL;
+      break;
+    }
+
+    //
+    //  Initialize the context
+    //
+    ZeroMem ( pContext, LengthInBytes );
+    CopyMem ( &pContext->RemoteAddress,
+              &pTftpServer->RemoteAddress,
+              sizeof ( pContext->RemoteAddress ));
+    pContext->BlockSize = TFTP_MAX_BLOCK_SIZE;
+    pContext->pBuffer = &pContext->FileData[0];
+    pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )];
+    pContext->MaxTransferSize = 0;
+    pContext->MaxTransferSize -= 1;
+
+    //
+    //  Display the new context
+    //
+    DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,
+              "0x%08x: Context for %d.%d.%d.%d:%d\r\n",
+              pContext,
+              (UINT8)pContext->RemoteAddress.sin_addr.s_addr,
+              (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ),
+              (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ),
+              (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ),
+              htons ( pContext->RemoteAddress.sin_port )));
+
+    //
+    //  Add the context to the context list
+    //
+    pContext->pNext = pTftpServer->pContextList;
+    pTftpServer->pContextList = pContext;
+
+    //
+    //  All done
+    //
+    break;
+  }
+
+  //
+  //  Return the connection context
+  //
+  DBG_EXIT_STATUS ( pContext );
+  return pContext;
+}
+
+
+/**
+  Locate a remote connection context.
+
+  @param [in] pTftpServer   The TFTP server control structure address.
+
+  @param [in] pIpAddress    The start of the remote IP address in network order
+
+  @param [in] Port          The remote port number
+
+  @retval Context structure address, NULL if not found
+
+**/
+TSDT_CONNECTION_CONTEXT *
+ContextFind (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  TSDT_CONNECTION_CONTEXT * pContext;
+
+  DBG_ENTER ( );
+
+  //
+  //  Walk the list of connection contexts
+  //
+  pContext = pTftpServer->pContextList;
+  while ( NULL != pContext ) {
+    //
+    //  Attempt to locate the remote network connection
+    //
+    if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr )
+      && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) {
+      //
+      //  The connection was found
+      //
+      DEBUG (( DEBUG_TFTP_REQUEST,
+                "0x%08x: pContext found\r\n",
+                pContext ));
+      break;
+    }
+
+    //
+    //  Set the next context
+    //
+    pContext = pContext->pNext;
+  }
+
+  //
+  //  Return the connection context structure address
+  //
+  DBG_EXIT_HEX ( pContext );
+  return pContext;
+}
+
+
+/**
+  Remove a context from the list.
+
+  @param [in] pTftpServer    The TFTP server control structure address.
+
+  @param [in] pContext       The context structure address.
+
+**/
+VOID
+ContextRemove (
+  IN TSDT_TFTP_SERVER * pTftpServer,
+  IN TSDT_CONNECTION_CONTEXT * pContext
+  )
+{
+  TSDT_CONNECTION_CONTEXT * pNextContext;
+  TSDT_CONNECTION_CONTEXT * pPreviousContext;
+
+  DBG_ENTER ( );
+
+  //
+  //  Attempt to locate the context in the list
+  //
+  pPreviousContext = NULL;
+  pNextContext = pTftpServer->pContextList;
+  while ( NULL != pNextContext ) {
+    //
+    //  Determine if the context was found
+    //
+    if ( pNextContext == pContext ) {
+      //
+      //  Remove the context from the list
+      //
+      if ( NULL == pPreviousContext ) {
+        pTftpServer->pContextList = pContext->pNext;
+      }
+      else {
+        pPreviousContext->pNext = pContext->pNext;
+      }
+      break;
+    }
+
+    //
+    //  Set the next context
+    //
+    pPreviousContext = pNextContext;
+    pNextContext = pNextContext->pNext;
+  }
+
+  //
+  //  Determine if the context was found
+  //
+  if ( NULL != pContext ) {
+    //
+    //  Return the resources
+    //
+    gBS->FreePool ( pContext );
+  }
+
+  DBG_EXIT ( );
+}
+
+
+/**
+  Process the work for the sockets.
+
+  @param [in] pTftpServer   The TFTP server control structure address.
+
+**/
+VOID
+PortWork (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  TSDT_CONNECTION_CONTEXT * pContext;
+  socklen_t RemoteAddressLength;
+
+  DBG_ENTER ( );
+
+  //
+  //  Handle input events
+  //
+  if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) {
+    //
+    //  Receive the message from the remote system
+    //
+    RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );
+    pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd,
+                                      &pTftpServer->RxBuffer[0],
+                                      sizeof ( pTftpServer->RxBuffer ),
+                                      0,
+                                      (struct sockaddr *) &pTftpServer->RemoteAddress,
+                                      &RemoteAddressLength );
+    if ( -1 != pTftpServer->RxBytes ) {
+      pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength;
+      DEBUG (( DEBUG_TFTP_PORT,
+                 "Received %d bytes from %d.%d.%d.%d:%d\r\n",
+                 pTftpServer->RxBytes,
+                 pTftpServer->RemoteAddress.sin_addr.s_addr & 0xff,
+                 ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
+                 ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
+                 ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
+                 htons ( pTftpServer->RemoteAddress.sin_port )));
+
+      //
+      //  Lookup connection context using the remote system address and port
+      //  to determine if an existing connection to this remote
+      //  system exists
+      //
+      pContext = ContextFind ( pTftpServer );
+
+      //
+      //  Process the received message
+      //
+      TftpProcessRequest ( pTftpServer, pContext );
+    }
+    else {
+      //
+      //  Receive error on the TFTP server port
+      //  Close the server socket
+      //
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",
+                errno ));
+      pTftpServer->TftpPort.revents |= POLLHUP;
+    }
+  }
+
+  //
+  //  Handle the close event
+  //
+  if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) {
+    //
+    //  Close the port
+    //
+    close ( pTftpServer->TftpPort.fd );
+    pTftpServer->TftpPort.fd = -1;
+  }
+
+  DBG_EXIT ( );
+}
+
+
+/**
+  Scan the list of sockets and process any pending work
+
+  @param [in] pTftpServer   The TFTP server control structure address.
+
+**/
+VOID
+SocketPoll (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  int FDCount;
+
+  DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));
+
+  //
+  //  Determine if any ports are active
+  //
+  FDCount = poll ( &pTftpServer->TftpPort,
+                   1,
+                   CLIENT_POLL_DELAY );
+  if ( -1 == FDCount ) {
+    DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL,
+              "ERROR - errno: %d\r\n",
+              errno ));
+  }
+
+  if ( 0 < FDCount ) {
+    //
+    //  Process this port
+    //
+    PortWork ( pTftpServer );
+    pTftpServer->TftpPort.revents = 0;
+  }
+
+  DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));
+}
+
+
+/**
+  Convert a character to lower case
+
+  @param [in] Character The character to convert
+
+  @returns  The lower case equivalent of the character
+
+**/
+int
+tolower (
+  int Character
+  )
+{
+  //
+  //  Determine if the character is upper case
+  //
+  if (( 'A' <= Character ) && ( 'Z' >= Character )) {
+    //
+    //  Convert the character to lower caes
+    //
+    Character += 'a' - 'A';
+  }
+
+  //
+  //  Return the converted character
+  //
+  return Character;
+}
+
+
+/**
+  Case independent string comparison
+
+  @param [in] pString1  Zero terminated string address
+  @param [in] pString2  Zero terminated string address
+
+  @returns    Returns the first character difference between string 1
+              and string 2.
+
+**/
+int
+stricmp (
+  char * pString1,
+  char * pString2
+  )
+{
+  int Char1;
+  int Char2;
+  int Difference;
+
+  //
+  //  Walk the length of the strings
+  //
+  do {
+    //
+    //  Get the next characters
+    //
+    Char1 = (UINT8)*pString1++;
+    Char2 = (UINT8)*pString2++;
+
+    //
+    //  Convert them to lower case
+    //
+    Char1 = tolower ( Char1 );
+    Char2 = tolower ( Char2 );
+
+    //
+    //  Done when the characters differ
+    //
+    Difference = Char1 - Char2;
+    if ( 0 != Difference ) {
+      break;
+    }
+
+    //
+    //  Done at the end of the string
+    //
+  } while ( 0 != Char1 );
+
+  //
+  //  Return the difference
+  //
+  return Difference;
+}
+
+
+/**
+  Get the next TFTP option
+
+  @param [in] pOption       Address of a zero terminated option string
+  @param [in] pEnd          End of buffer address
+  @param [in] ppNextOption  Address to receive the address of the next
+                            zero terminated option string
+
+  @retval EFI_SUCCESS   Message processed successfully
+
+**/
+EFI_STATUS
+TftpOptionGet (
+  IN UINT8 * pOption,
+  IN UINT8 * pEnd,
+  IN UINT8 ** ppNextOption
+  )
+{
+  UINT8 * pNextOption;
+  EFI_STATUS Status;
+
+  //
+  //  Locate the end of the option
+  //
+  pNextOption = pOption;
+  while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {
+    pNextOption += 1;
+  }
+  if ( pEnd <= pNextOption ) {
+    //
+    //  Error - end of buffer reached
+    //
+    DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
+              "ERROR - Option without zero termination received!\r\n" ));
+    Status = EFI_INVALID_PARAMETER;
+  }
+  else {
+    //
+    //  Zero terminated option found
+    //
+    pNextOption += 1;
+
+    //
+    //  Display the zero terminated ASCII option string
+    //
+    DEBUG (( DEBUG_TFTP_REQUEST,
+              "Option: %a\r\n",
+              pOption ));
+    Status = EFI_SUCCESS;
+  }
+
+  //
+  //  Return the next option address
+  //
+  *ppNextOption = pNextOption;
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Place an option value into the option acknowledgement
+
+  @param [in] pOack     Option acknowledgement address
+  @param [in] Value     Value to translate into ASCII decimal
+
+  @returns              Option acknowledgement address
+
+**/
+UINT8 *
+TftpOptionSet (
+  IN UINT8 * pOack,
+  IN UINT64 Value
+  )
+{
+  UINT64 NextValue;
+
+  //
+  //  Determine the next value
+  //
+  NextValue = Value / 10;
+
+  //
+  //  Supress leading zeros
+  //
+  if ( 0 != NextValue ) {
+    pOack = TftpOptionSet ( pOack, NextValue );
+  }
+
+  //
+  //  Output this digit
+  //
+  *pOack++ = (UINT8)( Value - ( NextValue * 10 ) + '0' );
+
+  //
+  //  Return the next option acknowledgement location
+  //
+  return pOack;
+}
+
+
+/**
+  Process the TFTP request
+
+  @param [in] pContext  The context structure address.
+  @param [in] pOption   Address of the first zero terminated option string
+  @param [in] pEnd      End of buffer address
+
+**/
+VOID
+TftpOptions (
+  IN TSDT_CONNECTION_CONTEXT * pContext,
+  IN UINT8 * pOption,
+  IN UINT8 * pEnd
+  )
+{
+  UINT8 * pNextOption;
+  UINT8 * pOack;
+  UINT8 * pTemp;
+  UINT8 * pValue;
+  EFI_STATUS Status;
+  INT32 Value;
+
+  //
+  //  Start the OACK packet
+  //  Let the OACK handle the parsing errors
+  //  See http://tools.ietf.org/html/rfc2347
+  //
+  pOack = &pContext->TxBuffer[0];
+  *pOack++ = 0;
+  *pOack++ = TFTP_OP_OACK;
+  pContext->TxBytes = 2;
+
+  //
+  //  Walk the list of options
+  //
+  do {
+    //
+    //  Get the next option, skip junk at end of message
+    //
+    Status = TftpOptionGet ( pOption, pEnd, &pNextOption );
+    if ( !EFI_ERROR ( Status )) {
+      //
+      //  Process the option
+      //
+
+      //
+      //  blksize - See http://tools.ietf.org/html/rfc2348
+      //
+      pValue = pNextOption;
+      if ( 0 == stricmp ((char *)pOption, "blksize" )) {
+        //
+        //  Get the value
+        //
+        Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
+        if ( !EFI_ERROR ( Status )) {
+          //
+          //  Validate the block size, skip non-numeric block sizes
+          //
+          Status = TftpOptionValue ( pValue, &Value );
+          if ( !EFI_ERROR ( Status )) {
+            //
+            //  Propose a smaller block size if necessary
+            //
+            if ( Value > TFTP_MAX_BLOCK_SIZE ) {
+              Value = TFTP_MAX_BLOCK_SIZE;
+            }
+
+            //
+            //  Set the new block size
+            //
+            pContext->BlockSize = Value;
+            DEBUG (( DEBUG_TFTP_REQUEST,
+                      "Using block size of %d bytes\r\n",
+                      pContext->BlockSize ));
+
+            //
+            //  Update the OACK
+            //
+            pTemp = pOack;
+            *pOack++ = 'b';
+            *pOack++ = 'l';
+            *pOack++ = 'k';
+            *pOack++ = 's';
+            *pOack++ = 'i';
+            *pOack++ = 'z';
+            *pOack++ = 'e';
+            *pOack++ = 0;
+            pOack = TftpOptionSet ( pOack, pContext->BlockSize );
+            *pOack++ = 0;
+            pContext->TxBytes += pOack - pTemp;
+          }
+        }
+      }
+
+      //
+      //  timeout - See http://tools.ietf.org/html/rfc2349
+      //
+      else if ( 0 == stricmp ((char *)pOption, "timeout" )) {
+        //
+        //  Get the value
+        //
+        Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
+        if ( !EFI_ERROR ( Status )) {
+          Status = TftpOptionValue ( pValue, &Value );
+          if ( !EFI_ERROR ( Status )) {
+            //
+            //  Set the timeout value
+            //
+            pContext->Timeout = Value;
+            DEBUG (( DEBUG_TFTP_REQUEST,
+                      "Using timeout of %d seconds\r\n",
+                      pContext->Timeout ));
+
+            //
+            //  Update the OACK
+            //
+            pTemp = pOack;
+            *pOack++ = 't';
+            *pOack++ = 'i';
+            *pOack++ = 'm';
+            *pOack++ = 'e';
+            *pOack++ = 'o';
+            *pOack++ = 'u';
+            *pOack++ = 't';
+            *pOack++ = 0;
+            pOack = TftpOptionSet ( pOack, pContext->Timeout );
+            *pOack++ = 0;
+            pContext->TxBytes += pOack - pTemp;
+          }
+        }
+      }
+
+      //
+      //  tsize - See http://tools.ietf.org/html/rfc2349
+      //
+      else if ( 0 == stricmp ((char *)pOption, "tsize" )) {
+        //
+        //  Get the value
+        //
+        Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
+        if ( !EFI_ERROR ( Status )) {
+          Status = TftpOptionValue ( pValue, &Value );
+          if ( !EFI_ERROR ( Status )) {
+            //
+            //  Return the file size
+            //
+            DEBUG (( DEBUG_TFTP_REQUEST,
+                      "Returning file size of %Ld bytes\r\n",
+                      pContext->LengthInBytes ));
+
+            //
+            //  Update the OACK
+            //
+            pTemp = pOack;
+            *pOack++ = 't';
+            *pOack++ = 's';
+            *pOack++ = 'i';
+            *pOack++ = 'z';
+            *pOack++ = 'e';
+            *pOack++ = 0;
+            pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );
+            *pOack++ = 0;
+            pContext->TxBytes += pOack - pTemp;
+          }
+        }
+      }
+      else {
+        //
+        //  Unknown option - Ignore it
+        //
+        DEBUG (( DEBUG_WARN | DEBUG_TFTP_REQUEST,
+                  "WARNING - Skipping unknown option: %a\r\n",
+                  pOption ));
+      }
+    }
+
+    //
+    //  Set the next option
+    //
+    pOption = pNextOption;
+  } while ( pEnd > pOption );
+}
+
+
+/**
+  Process the TFTP request
+
+  @param [in] pOption   Address of the first zero terminated option string
+  @param [in] pValue    Address to receive the value
+
+  @retval EFI_SUCCESS   Option translated into a value
+
+**/
+EFI_STATUS
+TftpOptionValue (
+  IN UINT8 * pOption,
+  IN INT32 * pValue
+  )
+{
+  UINT8 Digit;
+  EFI_STATUS Status;
+  INT32 Value;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Walk the characters in the option
+  //
+  Value = 0;
+  while ( 0 != *pOption ) {
+    //
+    //  Convert the next digit to binary
+    //
+    Digit = *pOption++;
+    if (( '0' <= Digit ) && ( '9' >= Digit )) {
+      Value *= 10;
+      Value += Digit - '0';
+    }
+    else {
+      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
+                "ERROR - Invalid character '0x%02x' in the value\r\n",
+                Digit ));
+      Status = EFI_INVALID_PARAMETER;
+      break;
+    }
+  }
+
+  //
+  //  Return the value
+  //
+  *pValue = Value;
+
+  //
+  //  Return the conversion status
+  //
+  return Status;
+}
+
+
+/**
+  Process the TFTP request
+
+  @param [in] pTftpServer The TFTP server control structure address.
+  @param [in] pContext    Connection context structure address
+
+**/
+VOID
+TftpProcessRequest (
+  IN TSDT_TFTP_SERVER * pTftpServer,
+  IN TSDT_CONNECTION_CONTEXT * pContext
+  )
+{
+  BOOLEAN bCloseContext;
+  BOOLEAN bIgnorePacket;
+  UINT16 BlockNumber;
+  UINT16 Opcode;
+  UINT8 * pBuffer;
+  UINT8 * pEnd;
+  UINT8 * pFileName;
+  UINT8 * pMode;
+  UINT8 * pOption;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Get the opcode
+  //
+  pBuffer = &pTftpServer->RxBuffer[0];
+  Opcode = HTONS ( *(UINT16 *)&pBuffer[0]);
+Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode );
+
+  //
+  //  Validate the parameters
+  //
+  bCloseContext = FALSE;
+  bIgnorePacket = FALSE;
+  switch ( Opcode ) {
+  default:
+    DEBUG (( DEBUG_TFTP_REQUEST,
+              "ERROR - Unknown TFTP opcode: %d\r\n",
+              Opcode ));
+    bIgnorePacket = TRUE;
+    break;
+
+  case TFTP_OP_READ_REQUEST:
+    break;
+
+  case TFTP_OP_DATA:
+    if ( NULL == pContext ) {
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
+                (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
+                htons ( pTftpServer->RemoteAddress.sin_port )));
+      bIgnorePacket = TRUE;
+      break;
+    }
+    if ( pContext->bExpectAck ) {
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",
+                pContext ));
+      bIgnorePacket = TRUE;
+      break;
+    }
+    if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 ))
+    {
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - Receive data length of %d > %d bytes (maximum block size) for pContext 0x%08x\r\n",
+                pTftpServer->RxBytes - 2 - 2,
+                pContext->BlockSize,
+                pContext ));
+      bIgnorePacket = TRUE;
+      break;
+    }
+    break;
+
+  case TFTP_OP_ACK:
+    if ( NULL == pContext ) {
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
+                (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
+                htons ( pTftpServer->RemoteAddress.sin_port )));
+      bIgnorePacket = TRUE;
+    }
+    if ( !pContext->bExpectAck ) {
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",
+                pContext ));
+      bIgnorePacket = TRUE;
+      break;
+    }
+    break;
+
+  case TFTP_OP_ERROR:
+    if ( NULL == pContext ) {
+      DEBUG (( DEBUG_ERROR,
+                "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
+                (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
+                (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
+                htons ( pTftpServer->RemoteAddress.sin_port )));
+      bIgnorePacket = TRUE;
+    }
+    break;
+  }
+  if ( !bIgnorePacket ) {
+    //
+    //  Process the request
+    //
+    switch ( Opcode ) {
+    default:
+      DEBUG (( DEBUG_TFTP_REQUEST,
+                "ERROR - Unable to process TFTP opcode: %d\r\n",
+                Opcode ));
+      break;
+
+    case TFTP_OP_READ_REQUEST:
+
+      //
+      //  Close the context if necessary
+      //
+      if ( NULL != pContext ) {
+        ContextRemove ( pTftpServer, pContext );
+      }
+
+      //
+      //  Create the connection context
+      //
+      pContext = ContextAdd ( pTftpServer );
+      if ( NULL == pContext ) {
+        break;
+      }
+
+      //
+      //  Locate the mode
+      //
+      pFileName = &pBuffer[2];
+      pEnd = &pBuffer[pTftpServer->RxBytes];
+      pMode = pFileName;
+      while (( pEnd > pMode ) && ( 0 != *pMode )) {
+        pMode += 1;
+      }
+      if ( pEnd <= pMode ) {
+        //
+        //  Mode not found
+        //
+        DEBUG (( DEBUG_ERROR | DEBUG_RX,
+                  "ERROR - File mode not found\r\n" ));
+        //
+        //  Tell the client of the error
+        //
+        TftpSendError ( pTftpServer,
+                        pContext,
+                        0,
+                        (UINT8 *)"File open mode not found" );
+        break;
+      }
+      pMode += 1;
+      DEBUG (( DEBUG_TFTP_REQUEST,
+                "TFTP - FileName: %a\n",
+                pFileName ));
+
+      //
+      //  Locate the options
+      //
+      pOption = pMode;
+      while (( pEnd > pOption ) && ( 0 != *pOption )) {
+        pOption += 1;
+      }
+      if ( pEnd <= pOption ) {
+        //
+        //  End of mode not found
+        //
+        DEBUG (( DEBUG_ERROR | DEBUG_RX,
+                  "ERROR - File mode not valid\r\n" ));
+        //
+        //  Tell the client of the error
+        //
+        TftpSendError ( pTftpServer,
+                        pContext,
+                        0,
+                        (UINT8 *)"File open mode not valid" );
+        break;
+      }
+      pOption += 1;
+      DEBUG (( DEBUG_TFTP_REQUEST,
+                "TFTP - Mode: %a\r\n",
+                pMode ));
+
+      //
+      //  Verify the mode is supported
+      //
+      if ( 0 != stricmp ((char *)pMode, "octet" )) {
+        //
+        //  File access mode not supported
+        //
+        DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
+                  "ERROR - File mode %a not supported\r\n",
+                  pMode ));
+
+        //
+        //  Tell the client of the error
+        //
+        TftpSendError ( pTftpServer,
+                        pContext,
+                        0,
+                        (UINT8 *)"File open mode not supported" );
+        break;
+      }
+
+      //
+      //  Open the file, close the context on error
+      //
+// TODO: Remove the following line
+pContext->File = (EFI_HANDLE)1;
+
+      //
+      //  Determine the file length
+      //
+//fstat
+
+      //
+      //  Process the options
+      //
+      TftpOptions ( pContext, pOption, pEnd );
+
+      //
+      //  Read in the first portion of the file
+      //
+
+      //
+      //  Send the first block
+      //
+      pContext->bExpectAck = TRUE;
+      if ( 2 < pContext->TxBytes ) {
+        //
+        //  Send the OACK
+        //
+        Status = TftpTxPacket ( pTftpServer, pContext );
+      }
+      else {
+        //
+        //  Send the first block of data
+        //
+        Status = TftpSendNextBlock ( pTftpServer, pContext );
+      }
+      break;
+
+    case TFTP_OP_ACK:
+      //
+      //  Get the block number that is being ACKed
+      //
+      BlockNumber = pTftpServer->RxBuffer[2];
+      BlockNumber <<= 8;
+      BlockNumber |= pTftpServer->RxBuffer[3];
+
+      //
+      //  Determine if this is the correct ACK
+      //
+      DEBUG (( DEBUG_TFTP_ACK,
+                "ACK for block 0x%04x received\r\n",
+                BlockNumber ));
+      if (( !pContext->bExpectAck )
+        || ( BlockNumber != pContext->AckNext ))
+      {
+        DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK,
+                  "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",
+                  pContext->AckNext,
+                  BlockNumber ));
+      }
+      else {
+        //
+        //  Process the expected ACK
+        //
+        if ( pContext->bEofSent ) {
+          bCloseContext = TRUE;
+        }
+        else {
+          //
+          //  Set the next expected ACK
+          //
+          pContext->AckNext += 1;
+
+          //
+          //  Send the next packet of data
+          //
+          Status = TftpSendNextBlock ( pTftpServer, pContext );
+        }
+      }
+      break;
+    }
+  }
+
+  //
+  //  Determine if the context should be closed
+  //
+  if ( bCloseContext ) {
+    ContextRemove ( pTftpServer, pContext );
+  }
+
+  DBG_EXIT ( );
+}
+
+
+/**
+  Build and send an error packet
+
+  @param [in] pTftpServer The TFTP server control structure address.
+  @param [in] pContext    The context structure address.
+  @param [in] Error       Error number for the packet
+  @param [in] pError      Zero terminated error string address
+
+  @retval EFI_SUCCESS     Message processed successfully
+
+**/
+EFI_STATUS
+TftpSendError (
+  IN TSDT_TFTP_SERVER * pTftpServer,
+  IN TSDT_CONNECTION_CONTEXT * pContext,
+  IN UINT16 Error,
+  IN UINT8 * pError
+  )
+{
+  UINT8 Character;
+  UINT8 * pBuffer;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Build the error packet
+  //
+  pBuffer = &pContext->TxBuffer[0];
+  pBuffer[0] = 0;
+  pBuffer[1] = TFTP_OP_ERROR;
+  pBuffer[2] = (UINT8)( Error >> 8 );
+  pBuffer[3] = (UINT8)Error;
+
+  //
+  //  Copy the zero terminated string into the buffer
+  //
+  pBuffer += 4;
+  do {
+    Character = *pError++;
+    *pBuffer++ = Character;
+  } while ( 0 != Character );
+
+  //
+  //  Send the error message
+  //
+  pContext->TxBytes = pBuffer - &pContext->TxBuffer[0];
+  Status = TftpTxPacket ( pTftpServer, pContext );
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Send the next block of file system data
+
+  @param [in] pTftpServer The TFTP server control structure address.
+  @param [in] pContext    The context structure address.
+
+  @retval EFI_SUCCESS   Message processed successfully
+
+**/
+EFI_STATUS
+TftpSendNextBlock (
+  IN TSDT_TFTP_SERVER * pTftpServer,
+  IN TSDT_CONNECTION_CONTEXT * pContext
+  )
+{
+  ssize_t LengthInBytes;
+  UINT8 * pBuffer;
+  EFI_STATUS Status;
+
+  //
+  //  Determine how much data needs to be sent
+  //
+  LengthInBytes = pContext->BlockSize;
+  if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE )
+    || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) {
+    LengthInBytes = (ssize_t)pContext->LengthInBytes;
+    pContext->bEofSent = TRUE;
+  }
+
+  //
+  //  Set the TFTP opcode and block number
+  //
+  pBuffer = &pContext->TxBuffer[0];
+  *pBuffer++ = 0;
+  *pBuffer++ = TFTP_OP_DATA;
+  *pBuffer++ = (UINT8)( pContext->AckNext >> 8 );
+  *pBuffer++ = (UINT8)pContext->AckNext;
+
+  //
+  //  Copy the file data into the transmit buffer
+  //
+  pContext->TxBytes = 2 + 2 + LengthInBytes;
+  if ( 0 < LengthInBytes ) {
+    CopyMem ( &pBuffer,
+              pContext->pBuffer,
+              LengthInBytes );
+  }
+
+  //
+  //  Send the next block
+  //
+  Status = TftpTxPacket ( pTftpServer, pContext );
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Create the port for the TFTP server
+
+  This routine polls the network layer to create the TFTP port for the
+  TFTP 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.
+
+  @param [in] pTftpServer  The TFTP server control structure address.
+
+**/
+VOID
+TftpServerTimer (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  UINT16 TftpPort;
+  int SocketStatus;
+  EFI_STATUS Status;
+
+  DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" ));
+
+  //
+  //  Open the TFTP port on the server
+  //
+  do {
+    do {
+      //
+      //  Wait for a while
+      //
+      Status = gBS->CheckEvent ( pTftpServer->TimerEvent );
+    } while ( EFI_SUCCESS != Status );
+
+    //
+    //  Attempt to create the socket for the TFTP server
+    //
+    pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP;
+    pTftpServer->TftpPort.revents = 0;
+    pTftpServer->TftpPort.fd = socket ( AF_INET,
+                                        SOCK_DGRAM,
+                                        IPPROTO_UDP );
+    if ( -1 != pTftpServer->TftpPort.fd )
+    {
+      //
+      //  Set the socket address
+      //
+      ZeroMem ( &pTftpServer->TftpServerAddress,
+                sizeof ( pTftpServer->TftpServerAddress ));
+      TftpPort = 69;
+      DEBUG (( DEBUG_TFTP_PORT,
+                "TFTP Port: %d\r\n",
+                TftpPort ));
+      pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress );
+      pTftpServer->TftpServerAddress.sin_family = AF_INET;
+      pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY;
+      pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort );
+
+      //
+      //  Bind the socket to the TFTP port
+      //
+      SocketStatus = bind ( pTftpServer->TftpPort.fd,
+                            (struct sockaddr *) &pTftpServer->TftpServerAddress,
+                            pTftpServer->TftpServerAddress.sin_len );
+      if ( -1 != SocketStatus ) {
+        DEBUG (( DEBUG_TFTP_PORT,
+                  "0x%08x: Socket bound to port %d\r\n",
+                  pTftpServer->TftpPort.fd,
+                  TftpPort ));
+      }
+
+      //
+      //  Release the socket if necessary
+      //
+      if ( -1 == SocketStatus ) {
+        close ( pTftpServer->TftpPort.fd );
+        pTftpServer->TftpPort.fd = -1;
+      }
+    }
+
+    //
+    //  Wait until the socket is open
+    //
+  }while ( -1 == pTftpServer->TftpPort.fd );
+
+  DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" ));
+}
+
+
+/**
+  Start the TFTP server port creation timer
+
+  @param [in] pTftpServer The TFTP 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
+TftpServerTimerStart (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  EFI_STATUS Status;
+  UINT64 TriggerTime;
+
+  DBG_ENTER ( );
+
+  //
+  //  Assume the timer is already running
+  //
+  Status = EFI_ALREADY_STARTED;
+  if ( !pTftpServer->bTimerRunning ) {
+    //
+    //  Compute the poll interval
+    //
+    TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );
+    Status = gBS->SetTimer ( pTftpServer->TimerEvent,
+                             TimerPeriodic,
+                             TriggerTime );
+    if ( !EFI_ERROR ( Status )) {
+      DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));
+
+      //
+      //  Mark the timer running
+      //
+      pTftpServer->bTimerRunning = TRUE;
+    }
+    else {
+      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,
+                "ERROR - Failed to start TFTP port timer, Status: %r\r\n",
+                Status ));
+    }
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Stop the TFTP server port creation timer
+
+  @param [in] pTftpServer The TFTP server control structure address.
+
+  @retval EFI_SUCCESS   The TFTP port timer is stopped
+  @retval Other         Failed to stop the TFTP port timer
+
+**/
+EFI_STATUS
+TftpServerTimerStop (
+  IN TSDT_TFTP_SERVER * pTftpServer
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Assume the timer is stopped
+  //
+  Status = EFI_SUCCESS;
+  if ( pTftpServer->bTimerRunning ) {
+    //
+    //  Stop the port creation polling
+    //
+    Status = gBS->SetTimer ( pTftpServer->TimerEvent,
+                             TimerCancel,
+                             0 );
+    if ( !EFI_ERROR ( Status )) {
+      DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" ));
+
+      //
+      //  Mark the timer stopped
+      //
+      pTftpServer->bTimerRunning = FALSE;
+    }
+    else {
+      DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,
+                "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n",
+                Status ));
+    }
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+/**
+  Send the next TFTP packet
+
+  @param [in] pTftpServer   The TFTP server control structure address.
+  @param [in] pContext      The context structure address.
+
+  @retval EFI_SUCCESS   Message processed successfully
+
+**/
+EFI_STATUS
+TftpTxPacket (
+  IN TSDT_TFTP_SERVER * pTftpServer,
+  IN TSDT_CONNECTION_CONTEXT * pContext
+  )
+{
+  ssize_t LengthInBytes;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Send the TFTP packet
+  //
+  DEBUG (( DEBUG_TX,
+            "0x%08x: pContext sending 0x%08x bytes\r\n",
+            pContext,
+            pContext->TxBytes ));
+  LengthInBytes = sendto ( pTftpServer->TftpPort.fd,
+                           &pContext->TxBuffer[0],
+                           pContext->TxBytes,
+                           0,
+                           (struct sockaddr *)&pContext->RemoteAddress,
+                           pContext->RemoteAddress.sin_len );
+  if ( -1 == LengthInBytes ) {
+    DEBUG (( DEBUG_ERROR | DEBUG_TX,
+              "ERROR - Transmit failure, errno: 0x%08x\r\n",
+              errno ));
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Entry point for the TFTP server application.
+
+  @param [in] Argc  The number of arguments
+  @param [in] Argv  The argument value array
+
+  @retval  0        The application exited normally.
+  @retval  Other    An error occurred.
+**/
+int
+main (
+  IN int Argc,
+  IN char **Argv
+  )
+{
+  TSDT_TFTP_SERVER * pTftpServer;
+  EFI_STATUS Status;
+
+  //
+  //  Create a timer event to start TFTP port
+  //
+  pTftpServer = &mTftpServer;
+  Status = gBS->CreateEvent ( EVT_TIMER,
+                              TPL_TFTP_SERVER,
+                              NULL,
+                              NULL,
+                              &pTftpServer->TimerEvent );
+  if ( !EFI_ERROR ( Status )) {
+    Status = TftpServerTimerStart ( pTftpServer );
+    if ( !EFI_ERROR ( Status )) {
+      //
+      //  Run the TFTP server forever
+      //
+      for ( ; ; ) {
+        //
+        //  Poll the network layer to create the TFTP port
+        //  for the tftp 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.
+        //
+        TftpServerTimer ( pTftpServer );
+
+        //
+        //  Poll the socket for activity
+        //
+        do {
+          SocketPoll ( pTftpServer );
+        } while ( -1 != pTftpServer->TftpPort.fd );
+
+//
+// TODO: Remove the following test code
+//  Exit when the network connection is broken
+//
+break;
+      }
+
+      //
+      //  Done with the timer event
+      //
+      TftpServerTimerStop ( pTftpServer );
+      Status = gBS->CloseEvent ( pTftpServer->TimerEvent );
+    }
+  }
+
+  //
+  //  Return the final status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/TftpServer/TftpServer.h b/AppPkg/Applications/Sockets/TftpServer/TftpServer.h
new file mode 100644 (file)
index 0000000..e56d21b
--- /dev/null
@@ -0,0 +1,331 @@
+/** @file\r
+  Definitions for the TFTP server.\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
+#ifndef _TFTP_SERVER_H_\r
+#define _TFTP_SERVER_H_\r
+\r
+#include <errno.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <Uefi.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.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
+\r
+#include <sys/EfiSysCall.h>\r
+#include <sys/poll.h>\r
+#include <sys/socket.h>\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
+#else   //  _MSC_VER\r
+#define DBG_ENTER()\r
+#define DBG_EXIT()\r
+#define DBG_EXIT_DEC(Status)\r
+#define DBG_EXIT_HEX(Status)\r
+#define DBG_EXIT_STATUS(Status)\r
+#define DBG_EXIT_TF(Status)\r
+#endif  //  _MSC_VER\r
+\r
+#define DIM(x)    ( sizeof ( x ) / sizeof ( x[0] ))   ///<  Compute the number of entries in an array\r
+\r
+//------------------------------------------------------------------------------\r
+//  Constants\r
+//------------------------------------------------------------------------------\r
+\r
+#define DEBUG_SOCKET_POLL       0x40000000  ///<  Display the socket poll messages\r
+#define DEBUG_PORT_WORK         0x20000000  ///<  Display the port work messages\r
+#define DEBUG_SERVER_TIMER      0x10000000  ///<  Display the socket poll messages\r
+#define DEBUG_TFTP_PORT         0x08000000  ///<  Display the TFTP port messages\r
+#define DEBUG_TFTP_REQUEST      0x04000000  ///<  Display the TFTP request messages\r
+#define DEBUG_TX                0x02000000  ///<  Display transmit messages\r
+#define DEBUG_RX                0x01000000  ///<  Display receive messages\r
+#define DEBUG_TFTP_ACK          0x00800000  ///<  Display the TFTP ACK messages\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 TPL_TFTP_SERVER        TPL_CALLBACK ///<  TPL for routine synchronization\r
+\r
+/**\r
+  Verify new TPL value\r
+\r
+  This macro which is enabled when debug is enabled verifies that\r
+  the new TPL value is >= the current TPL value.\r
+**/\r
+#ifdef VERIFY_TPL\r
+#undef VERIFY_TPL\r
+#endif  //  VERIFY_TPL\r
+\r
+#if !defined(MDEPKG_NDEBUG)\r
+\r
+#define VERIFY_TPL(tpl)                           \\r
+{                                                 \\r
+  EFI_TPL PreviousTpl;                            \\r
+                                                  \\r
+  PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \\r
+  gBS->RestoreTPL ( PreviousTpl );                \\r
+  if ( PreviousTpl > tpl ) {                      \\r
+    DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl ));  \\r
+    ASSERT ( PreviousTpl <= tpl );                \\r
+  }                                               \\r
+}\r
+\r
+#else   //  MDEPKG_NDEBUG\r
+\r
+#define VERIFY_TPL(tpl)\r
+\r
+#endif  //  MDEPKG_NDEBUG\r
+\r
+#define TFTP_SERVER_SIGNATURE       SIGNATURE_32('T','F','T','P') ///<  TSDT_TFTP_SERVER memory signature\r
+\r
+//\r
+//  See: http://www.rfc-editor.org/rfc/pdfrfc/rfc1350.txt.pdf\r
+//\r
+//  TFTP Operations\r
+//\r
+\r
+#define TFTP_OP_READ_REQUEST      1     ///<  Read request, zero terminated file name, zero terminated mode\r
+#define TFTP_OP_WRITE_REQUEST     2     ///<  Write request, zero terminated file name, zero terminated mode\r
+#define TFTP_OP_DATA              3     ///<  Data block, end-of-file indicated by short block\r
+#define TFTP_OP_ACK               4     ///<  ACK block number\r
+#define TFTP_OP_ERROR             5     ///<  Error number and explaination\r
+#define TFTP_OP_OACK              6     ///<  ACK the options\r
+\r
+#define TFTP_MAX_BLOCK_SIZE       4096  ///<  Maximum block size\r
+\r
+//------------------------------------------------------------------------------\r
+//  Data Types\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Port control structure\r
+**/\r
+typedef struct _TSDT_CONNECTION_CONTEXT TSDT_CONNECTION_CONTEXT;\r
+typedef struct _TSDT_CONNECTION_CONTEXT {\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
+\r
+  //\r
+  //  File management parameters\r
+  //\r
+  EFI_HANDLE File;              ///<  NULL while file is closed\r
+  UINT64 LengthInBytes;         ///<  Size of the file\r
+  UINT64 MaxTransferSize;       ///<  Maximum transfer size\r
+  BOOLEAN bEofSent;             ///<  End of file sent\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
+\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
+}GCC_TSDT_CONNECTION_CONTEXT;\r
+\r
+/**\r
+  TFTP server control structure\r
+**/\r
+typedef struct {\r
+  UINTN Signature;              ///<  Structure identification\r
+\r
+  //\r
+  //  Image attributes\r
+  //\r
+  EFI_HANDLE ImageHandle;       ///<  Image handle\r
+\r
+  //\r
+  //  TFTP port management\r
+  //\r
+  BOOLEAN   bTimerRunning;      ///<  Port creation timer status\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
+\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
+\r
+  //\r
+  //  Client port management\r
+  //\r
+  TSDT_CONNECTION_CONTEXT * pContextList; ///<  List of connection context structures\r
+} TSDT_TFTP_SERVER;\r
+\r
+//#define SERVER_FROM_SERVICE(a) CR(a, TSDT_TFTP_SERVER, ServiceBinding, TFTP_SERVER_SIGNATURE) ///< Locate DT_LAYER from service binding\r
+\r
+extern TSDT_TFTP_SERVER mTftpServer;\r
+\r
+//------------------------------------------------------------------------------\r
+// Support routines\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Process the TFTP request\r
+\r
+  @param [in] pOption   Address of the first zero terminated option string\r
+  @param [in] pValue    Address to receive the value\r
+\r
+  @retval EFI_SUCCESS   Option translated into a value\r
+\r
+**/\r
+EFI_STATUS\r
+TftpOptionValue (\r
+  IN UINT8 * pOption,\r
+  IN INT32 * pValue\r
+  );\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
+\r
+**/\r
+VOID\r
+TftpProcessRequest (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
+  );\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
+\r
+  @retval EFI_SUCCESS     Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+TftpSendError (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\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
+\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
+TftpSendNextBlock (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\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
+\r
+  @param [in] pTftpServer  The TFTP server control structure address.\r
+\r
+**/\r
+VOID\r
+TftpServerTimer (\r
+  IN TSDT_TFTP_SERVER * pTftpServer\r
+  );\r
+\r
+/**\r
+  Start the TFTP server port creation timer\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
+\r
+**/\r
+EFI_STATUS\r
+TftpServerTimerStart (\r
+  IN TSDT_TFTP_SERVER * pTftpServer\r
+  );\r
+\r
+/**\r
+  Stop the TFTP server port creation timer\r
+\r
+  @param [in] pTftpServer  The TFTP server control structure address.\r
+\r
+  @retval EFI_SUCCESS   The TFTP port timer is stopped\r
+  @retval Other         Failed to stop the TFTP port timer\r
+\r
+**/\r
+EFI_STATUS\r
+TftpServerTimerStop (\r
+  IN TSDT_TFTP_SERVER * pTftpServer\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
+//------------------------------------------------------------------------------\r
+\r
+#endif  //  _TFTP_SERVER_H_\r
diff --git a/AppPkg/Applications/Sockets/TftpServer/TftpServer.inf b/AppPkg/Applications/Sockets/TftpServer/TftpServer.inf
new file mode 100644 (file)
index 0000000..f487242
--- /dev/null
@@ -0,0 +1,66 @@
+#/** @file\r
+#  TFTP Server 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)  20011 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                      = TftpServer\r
+  FILE_GUID                      = 94621F9E-B5CA-4cfd-82BE-0C542EB0D9BE\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
+  TftpServer.h\r
+  TftpServer.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
+  DebugLib\r
+  DevShell\r
+  EfiSocketLib\r
+  LibC\r
+  ShellLib\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\r
+  UefiRuntimeServicesTableLib\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
diff --git a/AppPkg/Applications/Sockets/WebServer/ACPI.c b/AppPkg/Applications/Sockets/WebServer/ACPI.c
new file mode 100644 (file)
index 0000000..a7da233
--- /dev/null
@@ -0,0 +1,1918 @@
+/*++
+  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
+  Display the runtime services table
+
+**/
+
+#include <WebServer.h>
+#include <Guid/Acpi.h>
+#include <IndustryStandard/Acpi10.h>
+#include <IndustryStandard/Acpi30.h>
+
+#pragma warning ( disable : 4305 )
+
+//
+// Ensure proper structure formats
+//
+#pragma pack(1)
+
+typedef struct {
+  UINT8 AddressSpaceId;
+  UINT8 RegisterBitWidth;
+  UINT8 RegisterBitOffset;
+  UINT8 AccessSize;
+  UINT64 Address;
+} GENERIC_ADDRESS;
+
+
+typedef struct {
+  UINT32 Signature;           //    0
+  UINT32 Length;              //    4
+  UINT8 Revision;             //    8
+  UINT8 Checksum;             //    9
+  UINT8 OemId[6];             //   10
+  UINT8 OemTableId[8];        //   16
+  UINT32 OemRevision;         //   24
+  UINT32 CreatorId;           //   28
+  UINT32 CreatorRevision;     //   32
+  UINT8 DefinitionBlock[1];   //   36
+} ACPI_DSDT;
+
+
+typedef struct {
+  UINT32 Signature;           //    0
+  UINT32 Length;              //    4
+  UINT8 Revision;             //    8
+  UINT8 Checksum;             //    9
+  UINT8 OemId[6];             //   10
+  UINT8 OemTableId[8];        //   16
+  UINT32 OemRevision;         //   24
+  UINT32 CreatorId;           //   28
+  UINT32 CreatorRevision;     //   32
+  UINT32 FirmwareCtrl;        //   36
+  UINT32 DSDT;                //   40
+  UINT8 Reserved;             //   44
+  UINT8 PreferredPmProfile;   //   45
+  UINT16 SciInt;              //   46
+  UINT32 SmiCmd;              //   48
+  UINT8 AcpiEnable;           //   52
+  UINT8 AcpiDisable;          //   53
+  UINT8 S4BiosReq;            //   54
+  UINT8 PStateCnt;            //   55
+  UINT32 Pm1aEvtBlk;          //   56
+  UINT32 Pm1bEvtBlk;          //   60
+  UINT32 Pm1aCntBlk;          //   64
+  UINT32 Pm1bCntBlk;          //   68
+  UINT32 Pm2CntBlk;           //   72
+  UINT32 PmTmrBlk;            //   76
+  UINT32 Gpe0Blk;             //   80
+  UINT32 Gpe1Blk;             //   84
+  UINT8 Pm1EvtLen;            //   88
+  UINT8 Pm1CntLen;            //   89
+  UINT8 PM2CntLen;            //   90
+  UINT8 PmTmrLen;             //   91
+  UINT8 Gpe0BlkLen;           //   92
+  UINT8 Gpe1BlkLen;           //   93
+  UINT8 Gpe1Base;             //   94
+  UINT8 CstCnt;               //   95
+  UINT16 PLvl2Lat;            //   96
+  UINT16 PLvl3Lat;            //   98
+  UINT16 FlushSize;           //  100
+  UINT16 FlushStride;         //  102
+  UINT8 DutyOffset;           //  104
+  UINT8 DutyWidth;            //  105
+  UINT8 DayAlrm;              //  106
+  UINT8 MonAlrm;              //  107
+  UINT8 Century;              //  108
+  UINT16 IapcBootArch;        //  109
+  UINT8 Reserved2;            //  111
+  UINT32 Flags;               //  112
+  UINT32 ResetReg [3];        //  116
+  UINT8 ResetValue;           //  128
+  UINT8 Reserved3 [3];        //  129
+  UINT64 XFirmwareCtrl;       //  132
+  UINT64 XDsdt;               //  140
+  UINT32 XPm1aEvtBlk [3];     //  148
+  UINT32 XPm1bEvtBlk [3];     //  160
+  UINT32 XPm1aCntBlk [3];     //  172
+  UINT32 XPm1bCntBlk [3];     //  184
+  UINT32 XPm2CntBlk [3];      //  196
+  UINT32 XPmTmrBlk [3];       //  208
+  UINT32 XGpe0Blk [3];        //  220
+  UINT32 XGpe1Blk [3];        //  232
+} ACPI_FADT;
+
+
+typedef struct {
+  UINT32 Signature;
+  UINT32 Length;
+  UINT8 Revision;
+  UINT8 Checksum;
+  UINT8 OemId[6];
+  UINT8 OemTableId[8];
+  UINT32 OemRevision;
+  UINT32 CreatorId;
+  UINT32 CreatorRevision;
+  UINT32 Entry[1];
+} ACPI_RSDT;
+
+
+#pragma pack()
+
+
+typedef struct {
+  UINT32 Signature;
+  CONST CHAR8 * pTableName;
+  CONST CHAR16 * pWebPage;
+} TABLE_SIGNATURE;
+
+
+CONST TABLE_SIGNATURE mTableId [] = {
+  { DSDT_SIGNATURE, "DSDT", PAGE_ACPI_DSDT },
+  { FADT_SIGNATURE, "FADT", PAGE_ACPI_FADT }
+};
+
+
+/**
+  Locate the RSDT table
+
+  @returns Table address or NULL if not found
+
+**/
+CONST ACPI_RSDT *
+LocateRsdt (
+  VOID
+  )
+{
+  CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
+  CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
+  CONST ACPI_RSDT * pRsdt;
+  EFI_STATUS Status;
+
+  //
+  //  Use for/break instead of goto
+  //
+  pRsdt = NULL;
+  for ( ; ; ) {
+    //
+    //  Locate the RSDT
+    //
+    Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );
+    if ( !EFI_ERROR ( Status )) {
+      pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;
+    }
+    else {
+      Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;
+    }
+    break;
+  }
+
+  //
+  //  The entry was not found
+  //
+  return pRsdt;
+}
+
+
+/**
+  Locate the specified table
+
+  @param [in] Signature     Table signature
+
+  @returns Table address or NULL if not found
+
+**/
+CONST VOID *
+LocateTable (
+  IN UINT32 Signature
+  )
+{
+  CONST UINT32 * pEnd;
+  CONST UINT32 * pEntry;
+  CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
+  CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
+  CONST ACPI_RSDT * pRsdt;
+  CONST UINT32 * pSignature;
+  EFI_STATUS Status;
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Locate the RSDT
+    //
+    Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );
+    if ( !EFI_ERROR ( Status )) {
+      pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;
+    }
+    else {
+      Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;
+    }
+
+    //
+    //  Walk the list of entries
+    //
+    pEntry = &pRsdt->Entry [ 0 ];
+    pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];
+    while ( pEnd > pEntry ) {
+      //
+      //  The entry is actually a 32-bit physical table address
+      //  The first entry in the table is the 32-bit table signature
+      //
+      pSignature = (UINT32 *)*pEntry;
+      if ( *pSignature == Signature ) {
+        return (CONST VOID *) *pEntry;
+      }
+
+      //
+      //  Set the next entry
+      //
+      pEntry++;
+    }
+    break;
+  }
+
+  //
+  //  The entry was not found
+  //
+  return NULL;
+}
+
+
+/**
+  Display a row containing a hex value
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] Length        Length in bytes
+  @param [in] pChar         Address of the first character
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowAnsiArray (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN UINTN Length,
+  IN CONST CHAR8 * pChar
+  )
+{
+  CONST CHAR8 * pData;
+  CONST CHAR8 * pEnd;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Start the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the characters
+    //
+    pData = pChar;
+    pEnd = &pChar [ Length ];
+    while ( pEnd > pData ) {
+      Status = HttpSendCharacter ( SocketFD,
+                                   pPort,
+                                   *pData++,
+                                   " " );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the byte values
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<br/>0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    pData = pChar;
+    while ( pEnd > pData ) {
+      Status = HttpSendHexBits ( SocketFD,
+                                 pPort,
+                                 8,
+                                 *pData++ );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      if ( pEnd > pData ) {
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      " 0x" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+    }
+
+    //
+    //  Terminate the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Format a row with a list of bytes
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Zero terminated name string
+  @param [in] ByteCount     The number of bytes to display
+  @param [in] pData         Address of the byte array
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowBytes (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CHAR8 * pName,
+  IN UINTN ByteCount,
+  IN CONST UINT8 * pData
+  )
+{
+  CONST UINT8 * pEnd;
+  EFI_STATUS Status;
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Start the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the field name
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the field value
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    pEnd = &pData [ ByteCount ];
+    while ( pEnd > pData ) {
+      Status = HttpSendHexBits ( SocketFD,
+                                 pPort,
+                                 8,
+                                 *pData++ );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      if ( pEnd > pData ) {
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      " 0x" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+    }
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Terminate the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Format a row with a list of bytes
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Zero terminated name string
+  @param [in] ByteCount     The number of bytes to display
+  @param [in] pData         Address of the byte array
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowDump (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CHAR8 * pName,
+  IN UINTN ByteCount,
+  IN CONST UINT8 * pData
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Start the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the field name
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Start the field value
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Dump the buffer
+    //
+    Status = HttpSendDump ( SocketFD,
+                            pPort,
+                            ByteCount,
+                            pData );
+
+    //
+    //  Terminate the field value and row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Format a row with a general address
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Zero terminated name string
+  @param [in] pAddr         Address of the general address buffer
+  @param [in] pWebPage      Zero terminated web page address
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowGenericAddress (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CHAR8 * pName,
+  IN CONST UINT32 * pAddr,
+  IN CONST CHAR16 * pWebPage
+  )
+{
+  CONST GENERIC_ADDRESS * pGenericAddress;
+  EFI_STATUS Status;
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Start the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the field name
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the field value
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Determine the type of address
+    //
+    pGenericAddress = (CONST GENERIC_ADDRESS *)pAddr;
+    if ( 0 == pGenericAddress->AddressSpaceId ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "System Memory" );
+    }
+    else if ( 1 == pGenericAddress->AddressSpaceId ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "I/O Space" );
+    }
+    else if ( 2 == pGenericAddress->AddressSpaceId ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "PCI Configuration Space" );
+    }
+    else if ( 3 == pGenericAddress->AddressSpaceId ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "Embedded Controller" );
+    }
+    else if ( 4 == pGenericAddress->AddressSpaceId ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "SMBus" );
+    }
+    else if ( 0x7f == pGenericAddress->AddressSpaceId ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "Functional Fixed Hardware" );
+    }
+    else if (( 0xc0 <= pGenericAddress->AddressSpaceId )
+      && ( 0xff >= pGenericAddress->AddressSpaceId )) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "OEM Defined" );
+    }
+    else {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "Reserved" );
+    }
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<br/>Register Bit Width: " );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendValue ( SocketFD,
+                             pPort,
+                             pGenericAddress->RegisterBitWidth );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<br/>Register Bit Offset: " );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendHexValue ( SocketFD,
+                                pPort,
+                                pGenericAddress->RegisterBitOffset );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<br/>Access Size: " );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendValue ( SocketFD,
+                             pPort,
+                             pGenericAddress->AccessSize );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<br/>Address: " );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Add the web-page link if necessary
+    //
+    if ( NULL != pWebPage ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "<a target=\"_blank\" href=\"" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD,
+                                       pPort,
+                                       pWebPage );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "\">" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+
+    //
+    //  Display the address
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendHexBits ( SocketFD,
+                               pPort,
+                               64,
+                               pGenericAddress->Address );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Finish the web-page link if necessary
+    //
+    if ( NULL != pWebPage ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "</a>" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+
+    //
+    //  Terminate the row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Translate a table address into a web page
+
+  @param [in] pSignature      Address of the table signature
+  @param [out] ppTableName    Address to receive the table name address
+
+  @returns Zero terminated web page address or NULL if not found
+
+**/
+CONST CHAR16 *
+SignatureLookup (
+  IN UINT32 * pSignature,
+  OUT CONST CHAR8 ** ppTableName
+  )
+{
+  CONST TABLE_SIGNATURE * pTableId;
+  CONST TABLE_SIGNATURE * pEnd;
+  UINT32 Signature;
+
+  //
+  //  Walk the list of tables
+  //
+  Signature = *pSignature;
+  pTableId = &mTableId [ 0 ];
+  pEnd = &pTableId [ sizeof ( mTableId ) / sizeof ( mTableId [ 0 ])];
+  while ( pEnd > pTableId ) {
+    //
+    //  Attempt to locate the table signature
+    //
+    if ( pTableId->Signature == Signature ) {
+      //
+      //  The signature was found
+      //  Return the web page
+      //
+      *ppTableName = pTableId->pTableName;
+      return pTableId->pWebPage;
+    }
+
+    //
+    //  Set the next table
+    //
+    pTableId += 1;
+  }
+
+  //
+  //  The table was not found
+  //
+  *ppTableName = (CONST CHAR8 *)pSignature;
+  return NULL;
+}
+
+
+/**
+  Respond with the ACPI DSDT table
+
+  @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
+AcpiDsdtPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  CONST ACPI_DSDT * pDsdt;
+  CONST ACPI_FADT * pFadt;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the DADT page
+  //
+  for ( ; ; ) {
+    //
+    //  Locate the DADT
+    //
+    pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );
+    if ( NULL == pFadt ) {
+      Status = EFI_NOT_FOUND;
+      break;
+    }
+    pDsdt = (VOID *)pFadt->XDsdt;
+
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"DSDT - Differentiated System Description Table", pDsdt );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the DSDT header
+    //
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Signature",
+                            sizeof ( pDsdt->Signature ),
+                            (CHAR8 *)&pDsdt->Signature );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Length",
+                               pDsdt->Length );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Revision",
+                               pDsdt->Revision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Checksum",
+                           pDsdt->Checksum,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OEMID",
+                            sizeof ( pDsdt->OemId ),
+                            &pDsdt->OemId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OEM Table ID",
+                            sizeof ( pDsdt->OemTableId ),
+                            &pDsdt->OemTableId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "OEM Revision",
+                           pDsdt->OemRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Creator ID",
+                            sizeof ( pDsdt->CreatorId ),
+                            (CHAR8 *)&pDsdt->CreatorId );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "Creator Revision",
+                           pDsdt->CreatorRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the data from the DSDT
+    //
+    Status = RowDump ( SocketFD,
+                       pPort,
+                       "Definition Block",
+                       pDsdt->Length - sizeof ( *pDsdt ) + 1,
+                       &pDsdt->DefinitionBlock[0]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Respond with the ACPI FADT table
+
+  @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
+AcpiFadtPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  CONST ACPI_FADT * pFadt;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the FADT page
+  //
+  for ( ; ; ) {
+    //
+    //  Locate the FADT
+    //
+    pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );
+    if ( NULL == pFadt ) {
+      Status = EFI_NOT_FOUND;
+      break;
+    }
+
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"FADT - Fixed ACPI Description Table", pFadt );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the FSDT header
+    //
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Signature",
+                            sizeof ( pFadt->Signature ),
+                            (CHAR8 *)&pFadt->Signature );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Length",
+                               pFadt->Length );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Revision",
+                               pFadt->Revision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Checksum",
+                           pFadt->Checksum,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OEMID",
+                            sizeof ( pFadt->OemId ),
+                            &pFadt->OemId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OEM Table ID",
+                            sizeof ( pFadt->OemTableId ),
+                            &pFadt->OemTableId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "OEM Revision",
+                           pFadt->OemRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Creator ID",
+                            sizeof ( pFadt->CreatorId ),
+                            (CHAR8 *)&pFadt->CreatorId );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "Creator Revision",
+                           pFadt->CreatorRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the data from the FADT
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "FIRMWARE_CTRL",
+                          (CONST VOID *)pFadt->FirmwareCtrl,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "DSDT",
+                          (CONST VOID *)pFadt->DSDT,
+                          ( pFadt->DSDT == pFadt->XDsdt ) ? PAGE_ACPI_DSDT : NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Reserved",
+                           pFadt->Reserved,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Preferred_PM_Profile",
+                           pFadt->PreferredPmProfile,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "SCI_INT",
+                           pFadt->SciInt,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "SMI_CMD",
+                           pFadt->SmiCmd,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "ACPI_ENABLE",
+                           pFadt->AcpiEnable,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "ACPI_DISABLE",
+                           pFadt->AcpiDisable,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "S4BIOS_REQ",
+                           pFadt->S4BiosReq,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PSTATE_CNT",
+                           pFadt->PStateCnt,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PM1a_EVT_BLK",
+                           pFadt->Pm1aEvtBlk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PM1b_EVT_BLK",
+                           pFadt->Pm1bEvtBlk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PM1a_CNT_BLK",
+                           pFadt->Pm1aCntBlk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PM1b_CNT_BLK",
+                           pFadt->Pm1bCntBlk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PM2_CNT_BLK",
+                           pFadt->Pm2CntBlk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "PM_TMR_BLK",
+                           pFadt->PmTmrBlk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "GPE0_BLK",
+                           pFadt->Gpe0Blk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "GPE1_BLK",
+                           pFadt->Gpe1Blk,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "PM1_EVT_LEN",
+                               pFadt->Pm1EvtLen );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "PM1_CNT_LEN",
+                               pFadt->Pm1CntLen );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "PM2_CNT_LEN",
+                               pFadt->PM2CntLen );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "PM_TMR_LEN",
+                               pFadt->PmTmrLen );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "GPE0_BLK_LEN",
+                               pFadt->Gpe0BlkLen );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "GPE1_BLK_LEN",
+                               pFadt->Gpe1BlkLen );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "GPE1_BASE",
+                           pFadt->Gpe1Base,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "CST_CNT",
+                               pFadt->CstCnt );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "P_LVL2_LAT",
+                           pFadt->PLvl2Lat,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "P_LVL3_LAT",
+                           pFadt->PLvl3Lat,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "FLUSH_SIZE",
+                               pFadt->FlushSize );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "FLUSH_Stride",
+                               pFadt->FlushStride );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "DUTY_OFFSET",
+                           pFadt->DutyOffset,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "DUTY_WIDTH",
+                           pFadt->DutyWidth,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "DAY_ALRM",
+                           pFadt->DayAlrm,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "MON_ALRM",
+                           pFadt->MonAlrm,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "CENTURY",
+                           pFadt->Century,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "IAPC_BOOT_ARCH",
+                           pFadt->IapcBootArch,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Reserved",
+                           pFadt->Reserved2,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Flags",
+                           pFadt->Flags,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "RESET_REG",
+                                 &pFadt->ResetReg[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "RESET_VALUE",
+                           pFadt->ResetValue,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Reserved",
+                           pFadt->Reserved3[0],
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Reserved",
+                           pFadt->Reserved3[1],
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Reserved",
+                           pFadt->Reserved3[2],
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "X_FIRMWARE_CTRL",
+                           pFadt->XFirmwareCtrl,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "X_DSDT",
+                           pFadt->XDsdt,
+                           PAGE_ACPI_DSDT );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_PM1a_EVT_BLK",
+                                 &pFadt->XPm1aEvtBlk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_PM1b_EVT_BLK",
+                                 &pFadt->XPm1bEvtBlk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_PM1a_CNT_BLK",
+                                 &pFadt->XPm1aCntBlk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_PM1b_CNT_BLK",
+                                 &pFadt->XPm1bCntBlk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_PM2_CNT_BLK",
+                                 &pFadt->XPm2CntBlk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_PM_TMR_BLK",
+                                 &pFadt->XPmTmrBlk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_GPE0_BLK",
+                                 &pFadt->XGpe0Blk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowGenericAddress ( SocketFD,
+                                 pPort,
+                                 "X_GPE1_BLK",
+                                 &pFadt->XGpe1Blk[0],
+                                 NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Respond with the ACPI RSDP 1.0b table
+
+  @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
+AcpiRsdp10Page (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the RSDP page
+  //
+  for ( ; ; ) {
+    //
+    //  Locate the RSDP
+    //
+    Status = EfiGetSystemConfigurationTable ( &gEfiAcpi10TableGuid, (VOID **) &pRsdp10b );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 1.0b Root System Description Pointer", pRsdp10b );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the RSDP
+    //
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Signature",
+                            sizeof ( pRsdp10b->Signature ),
+                            (CHAR8 *)&pRsdp10b->Signature );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Checksum",
+                           pRsdp10b->Checksum,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OemId",
+                            sizeof ( pRsdp10b->OemId ),
+                            &pRsdp10b->OemId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Reserved",
+                           pRsdp10b->Reserved,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RsdtAddress",
+                          (VOID *)pRsdp10b->RsdtAddress,
+                          PAGE_ACPI_RSDT );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Respond with the ACPI RSDP 3.0 table
+
+  @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
+AcpiRsdp30Page (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the RSDP page
+  //
+  for ( ; ; ) {
+    //
+    //  Locate the RSDP
+    //
+    Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **) &pRsdp30 );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 3.0 Root System Description Pointer", pRsdp30 );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the RSDP
+    //
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Signature",
+                            sizeof ( pRsdp30->Signature ),
+                            (CHAR8 *)&pRsdp30->Signature );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Checksum",
+                           pRsdp30->Checksum,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OemId",
+                            sizeof ( pRsdp30->OemId ),
+                            &pRsdp30->OemId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Revision",
+                           pRsdp30->Revision,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RsdtAddress",
+                          (VOID *)pRsdp30->RsdtAddress,
+                          PAGE_ACPI_RSDT );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Length",
+                               pRsdp30->Length );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "XsdtAddress",
+                          (VOID *)pRsdp30->XsdtAddress,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "ExtendedChecksum",
+                           pRsdp30->ExtendedChecksum,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowBytes ( SocketFD,
+                        pPort,
+                        "Reserved",
+                        sizeof ( pRsdp30->Reserved ),
+                        &pRsdp30->Reserved [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Respond with the ACPI RSDT table
+
+  @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
+AcpiRsdtPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  CONST UINT32 * pEnd;
+  CONST UINT32 * pEntry;
+  CONST ACPI_RSDT * pRsdt;
+  CONST CHAR8 * pTableName;
+  CONST CHAR16 * pWebPage;
+  EFI_STATUS Status;
+  UINT32 TableName [ 2 ];
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the RSDT page
+  //
+  for ( ; ; ) {
+    //
+    //  Locate the RSDT
+    //
+    pRsdt = LocateRsdt ( );
+    if ( NULL == pRsdt ) {
+      Status = EFI_NOT_FOUND;
+      break;
+    }
+
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"RSDT - ACPI Root System Description Table", pRsdt );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the RSDT
+    //
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Signature",
+                            sizeof ( pRsdt->Signature ),
+                            (CHAR8 *)&pRsdt->Signature );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Length",
+                               pRsdt->Length );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Revision",
+                               pRsdt->Revision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Checksum",
+                           pRsdt->Checksum,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OEMID",
+                            sizeof ( pRsdt->OemId ),
+                            &pRsdt->OemId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "OEM Table ID",
+                            sizeof ( pRsdt->OemTableId ),
+                            &pRsdt->OemTableId [ 0 ]);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "OEM Revision",
+                           pRsdt->OemRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowAnsiArray ( SocketFD,
+                            pPort,
+                            "Creator ID",
+                            sizeof ( pRsdt->CreatorId ),
+                            (CHAR8 *)&pRsdt->CreatorId );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "Creator Revision",
+                           pRsdt->CreatorRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Walk the list of entries
+    //
+    pEntry = &pRsdt->Entry [ 0 ];
+    pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];
+    TableName [ 1 ] = 0;
+    while ( pEnd > pEntry ) {
+      //
+      //  The entry is actually a 32-bit physical table address
+      //  The first entry in the table is the 32-bit table signature
+      //
+      TableName [ 0 ] = *(UINT32 *)*pEntry;
+      pWebPage = SignatureLookup ( &TableName [ 0 ], &pTableName );
+
+      //
+      //  Display the table address
+      //
+      Status = RowPointer ( SocketFD,
+                            pPort,
+                            pTableName,
+                            (VOID *)*pEntry,
+                            pWebPage );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      pEntry++;
+    }
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
diff --git a/AppPkg/Applications/Sockets/WebServer/BootServicesTable.c b/AppPkg/Applications/Sockets/WebServer/BootServicesTable.c
new file mode 100644 (file)
index 0000000..ab01649
--- /dev/null
@@ -0,0 +1,481 @@
+/*++
+  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
+  Display the boot services table
+
+**/
+
+#include <WebServer.h>
+
+/**
+  Respond with the boot services table
+
+  @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
+BootServicesTablePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the boot services page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"Boot Services Table", gBS );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The table header for the EFI Boot Services Table.
+    ///
+    Status = EfiTableHeader ( SocketFD,
+                              pPort,
+                              &gBS->Hdr );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Task Priority Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RaiseTPL",
+                          (CONST VOID *)gBS->RaiseTPL,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RestoreTPL",
+                          (CONST VOID *)gBS->RestoreTPL,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Memory Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "AllocatePages",
+                          (CONST VOID *)gBS->AllocatePages,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "FreePages",
+                          (CONST VOID *)gBS->FreePages,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetMemoryMap",
+                          (CONST VOID *)gBS->GetMemoryMap,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "AllocatePool",
+                          (CONST VOID *)gBS->AllocatePool,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "FreePool",
+                          (CONST VOID *)gBS->FreePool,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Event & Timer Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CreateEvent",
+                          (CONST VOID *)gBS->CreateEvent,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetTimer",
+                          (CONST VOID *)gBS->SetTimer,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "WaitForEvent",
+                          (CONST VOID *)gBS->WaitForEvent,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SignalEvent",
+                          (CONST VOID *)gBS->SignalEvent,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CloseEvent",
+                          (CONST VOID *)gBS->CloseEvent,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CheckEvent",
+                          (CONST VOID *)gBS->CheckEvent,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Protocol Handler Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "InstallProtocolInterface",
+                          (CONST VOID *)gBS->InstallProtocolInterface,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ReinstallProtocolInterface",
+                          (CONST VOID *)gBS->ReinstallProtocolInterface,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "UninstallProtocolInterface",
+                          (CONST VOID *)gBS->UninstallProtocolInterface,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "HandleProtocol",
+                          (CONST VOID *)gBS->HandleProtocol,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "Reserved",
+                          (CONST VOID *)gBS->Reserved,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RegisterProtocolNotify",
+                          (CONST VOID *)gBS->RegisterProtocolNotify,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "LocateHandle",
+                          (CONST VOID *)gBS->LocateHandle,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "LocateDevicePath",
+                          (CONST VOID *)gBS->LocateDevicePath,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "InstallConfigurationTable",
+                          (CONST VOID *)gBS->InstallConfigurationTable,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Image Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "LoadImage",
+                          (CONST VOID *)gBS->LoadImage,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "StartImage",
+                          (CONST VOID *)gBS->StartImage,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "Exit",
+                          (CONST VOID *)gBS->Exit,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "UnloadImage",
+                          (CONST VOID *)gBS->UnloadImage,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ExitBootServices",
+                          (CONST VOID *)gBS->ExitBootServices,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Miscellaneous Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetNextMonotonicCount",
+                          (CONST VOID *)gBS->GetNextMonotonicCount,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "Stall",
+                          (CONST VOID *)gBS->Stall,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetWatchdogTimer",
+                          (CONST VOID *)gBS->SetWatchdogTimer,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // DriverSupport Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConnectController",
+                          (CONST VOID *)gBS->ConnectController,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "DisconnectController",
+                          (CONST VOID *)gBS->DisconnectController,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Open and Close Protocol Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "OpenProtocol",
+                          (CONST VOID *)gBS->OpenProtocol,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CloseProtocol",
+                          (CONST VOID *)gBS->CloseProtocol,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "OpenProtocolInformation",
+                          (CONST VOID *)gBS->OpenProtocolInformation,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Library Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ProtocolsPerHandle",
+                          (CONST VOID *)gBS->ProtocolsPerHandle,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "LocateHandleBuffer",
+                          (CONST VOID *)gBS->LocateHandleBuffer,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "LocateProtocol",
+                          (CONST VOID *)gBS->LocateProtocol,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "InstallMultipleProtocolInterfaces",
+                          (CONST VOID *)gBS->InstallMultipleProtocolInterfaces,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "UninstallMultipleProtocolInterfaces",
+                          (CONST VOID *)gBS->UninstallMultipleProtocolInterfaces,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // 32-bit CRC Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CalculateCrc32",
+                          (CONST VOID *)gBS->CalculateCrc32,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    // Miscellaneous Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CopyMem",
+                          (CONST VOID *)gBS->CopyMem,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetMem",
+                          (CONST VOID *)gBS->SetMem,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "CreateEventEx",
+                          (CONST VOID *)gBS->CreateEventEx,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/ConfigurationTable.c b/AppPkg/Applications/Sockets/WebServer/ConfigurationTable.c
new file mode 100644 (file)
index 0000000..8a3de87
--- /dev/null
@@ -0,0 +1,380 @@
+/*++
+  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
+  Display the configuration table
+
+**/
+
+#include <WebServer.h>
+#include <Guid\Acpi.h>
+#include <Guid\DebugImageInfoTable.h>
+#include <Guid\DxeServices.h>
+#include <Guid\HobList.h>
+#include <Guid\MemoryTypeInformation.h>
+#include <Guid\LoadModuleAtFixedAddress.h>
+
+
+typedef struct {
+  CHAR16 * GuidName;
+  EFI_GUID * pGuid;
+  CHAR16 * pWebPage;
+} GUID_NAME;
+
+CONST GUID_NAME mGuidName [] = {
+  { L"gEfiAcpi10TableGuid", &gEfiAcpi10TableGuid, PAGE_ACPI_RSDP_10B },
+  { L"gEfiAcpiTableGuid", &gEfiAcpiTableGuid, PAGE_ACPI_RSDP_30 },
+  { L"gEfiDebugImageInfoTableGuid", &gEfiDebugImageInfoTableGuid, NULL },
+  { L"gEfiDxeServicesTableGuid", &gEfiDxeServicesTableGuid, PAGE_DXE_SERVICES_TABLE },
+  { L"gEfiHobListGuid", &gEfiHobListGuid, NULL },
+  { L"gEfiMemoryTypeInformationGuid", &gEfiMemoryTypeInformationGuid, NULL },
+  { L"gLoadFixedAddressConfigurationTableGuid", &gLoadFixedAddressConfigurationTableGuid, NULL }
+};
+
+/**
+  Display a row containing a GUID value
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] pGuid         Address of the GUID to display
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowGuid (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN CONST EFI_GUID * pGuid
+  )
+{
+  CONST GUID_NAME * pGuidName;
+  CONST GUID_NAME * pGuidNameEnd;
+  EFI_STATUS Status;
+  UINTN Value;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Determine if this is a known GUID
+    //
+    pGuidName = &mGuidName[0];
+    pGuidNameEnd = &pGuidName [ sizeof ( mGuidName ) / sizeof ( mGuidName[0])];
+    while ( pGuidNameEnd > pGuidName ) {
+      if ( CompareGuid ( pGuidName->pGuid, pGuid )) {
+        //
+        //  Display the web link if available
+        //
+        if ( NULL != pGuidName->pWebPage ) {
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "<a target=\"_blank\" href=\"" );
+          if ( EFI_ERROR ( Status )) {
+            break;
+          }
+          Status = HttpSendUnicodeString ( SocketFD,
+                                           pPort,
+                                           pGuidName->pWebPage );
+          if ( EFI_ERROR ( Status )) {
+            break;
+          }
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "\">" );
+          if ( EFI_ERROR ( Status )) {
+            break;
+          }
+        }
+
+        //
+        //  Display the GUID name
+        //
+        Status = HttpSendUnicodeString ( SocketFD,
+                                         pPort,
+                                         pGuidName->GuidName );
+
+        //
+        //  Complete the web link if available
+        //
+        if ( NULL != pGuidName->pWebPage ) {
+          if ( EFI_ERROR ( Status )) {
+            break;
+          }
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "</a>" );
+        }
+        break;
+      }
+    
+      //
+      //  Set the next GUID name
+      //
+      pGuidName += 1;
+    }
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Only if the entry is not known, display the GUID and type
+    //
+    if ( pGuidNameEnd <= pGuidName ) {
+      //
+      //  Display the GUID
+      //
+      Status = HttpSendGuid ( SocketFD,
+                              pPort,
+                              pGuid );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Display the GUID type
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "<br/><a target=\"_blank\" href=\"http://www.ietf.org/rfc/rfc4122.txt\">Guid Type</a>: " );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Value = pGuid->Data4[1];
+      Value >>= 5;
+      if ( 3 >= Value ) {
+        //
+        //  Network type
+        //
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "Network " );
+      }
+      else if ( 5 >= Value ) {
+        //
+        //  Standard type
+        //
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "Standard " );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+
+        //
+        //  Decode the standard type using RFC 4122
+        //
+        Value = pGuid->Data3;
+        Value >>= 12;
+        switch ( Value ) {
+        default:
+          //
+          //  Display the MAC address
+          //
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "Version " );
+          if ( EFI_ERROR ( Status )) {
+            break;
+          }
+          Status = HttpSendValue ( SocketFD,
+                                   pPort,
+                                   pGuid->Data3 >> 12 );
+          break;
+
+        case 1:
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "MAC address" );
+          break;
+
+        case 2:
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "DCE Security" );
+          break;
+
+        case 3:
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "MD5 hash" );
+          break;
+
+        case 4:
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "Random" );
+          break;
+
+        case 5:
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "SHA-1 hash" );
+          break;
+        }
+      }
+      else if ( 6 == Value ) {
+        //
+        //  Microsoft's Component Object Model (COM) type
+        //
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "Microsoft COM" );
+      }
+      else {
+        //
+        //  Reserved type
+        //
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "Reserved" );
+      }
+    }
+
+    //
+    //  Done with this entry
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+  
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Respond with the configuration tables
+
+  @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
+ConfigurationTablePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_CONFIGURATION_TABLE * pEnd;
+  EFI_CONFIGURATION_TABLE * pTable;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the system table page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"Configuration Tables", gST );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the table size
+    //
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Entries",
+                               gST->NumberOfTableEntries );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Determine the location of the configuration tables
+    //
+    pTable = gST->ConfigurationTable;
+    pEnd = &pTable [ gST->NumberOfTableEntries ];
+    while ( pEnd > pTable ) {
+      Status = RowGuid ( SocketFD,
+                         pPort,
+                         "VendorGuid",
+                         &pTable->VendorGuid );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = RowPointer ( SocketFD,
+                            pPort,
+                            "VendorTable",
+                            (VOID *)pTable->VendorTable,
+                            NULL );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Set the next row
+      //
+      pTable += 1;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/DhcpOptions.c b/AppPkg/Applications/Sockets/WebServer/DhcpOptions.c
new file mode 100644 (file)
index 0000000..fe37d3d
--- /dev/null
@@ -0,0 +1,235 @@
+/*++
+  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
+  Display the DHCP options
+
+**/
+
+#include <WebServer.h>
+#include <Guid/DxeServices.h>
+#include <pi/PiDxeCis.h>
+
+#include <protocol/Dhcp4.h>
+#include <protocol/ServiceBinding.h>
+
+/**
+  Respond with the DHCP options
+
+  @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
+DhcpOptionsPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+//  EFI_HANDLE Dhcp4Handle;
+  EFI_DHCP4_MODE_DATA Dhcp4Mode;
+  UINTN HandleCount;
+  EFI_DHCP4_PROTOCOL * pDhcp4;
+  EFI_DHCP4_PACKET * pDhcp4Packet;
+  EFI_HANDLE * pEnd;
+  EFI_HANDLE * pHandle;
+//  EFI_SERVICE_BINDING_PROTOCOL * pService;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the DHCP options
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"DHCP Options" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    //  Build the header
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendUnicodeString ( SocketFD,
+                                     pPort,
+                                     L"DHCP Options" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</h1>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Attempt to locate DHCP clients
+    //
+    Status = gBS->LocateHandleBuffer ( ByProtocol,
+//                                       &gEfiDhcp4ServiceBindingProtocolGuid,
+                                       &gEfiDhcp4ProtocolGuid,
+                                       NULL,
+                                       &HandleCount,
+                                       &pHandle );
+    if ( EFI_ERROR ( Status )) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "DHCP not in use" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    else {
+      //
+      //  Walk the list of handles
+      //
+      pEnd = &pHandle [ HandleCount ];
+      while ( pEnd > pHandle ) {
+/*
+        //
+        //  Get the DHCP service binding
+        //
+        Status = gBS->OpenProtocol ( *pHandle,
+                                      &gEfiDhcp4ServiceBindingProtocolGuid,
+                                      &pService,
+                                      NULL,
+                                      gImageHandle,
+                                      EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+        if ( EFI_ERROR ( Status )) {
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "Failed to open gEfiDhcp4ServiceBindingProtocolGuid" );
+          break;
+        }
+
+        //
+        //  Get the DHCP handle
+        //
+        Status = pService->CreateChild ( pService,
+                                         &Dhcp4Handle );
+        if ( EFI_ERROR ( Status )) {
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "Failed to create DHCP4 child" );
+        }
+        else {
+*/
+          //
+          //  Get the DHCP protocol
+          //
+          Status = gBS->OpenProtocol ( *pHandle,
+//                                       Dhcp4Handle,
+                                       &gEfiDhcp4ProtocolGuid,
+                                       &pDhcp4,
+                                       NULL,
+                                       gImageHandle,
+                                       EFI_OPEN_PROTOCOL_GET_PROTOCOL );
+          if ( EFI_ERROR ( Status )) {
+            Status = HttpSendAnsiString ( SocketFD,
+                                          pPort,
+                                          "Failed to open gEfiDhcp4ProtocolGuid" );
+          }
+          else {
+            //
+            //  Get the DHCP packet
+            //
+            Status = pDhcp4->GetModeData ( pDhcp4,
+                                           &Dhcp4Mode );
+            if ( EFI_ERROR ( Status )) {
+              Status = HttpSendAnsiString ( SocketFD,
+                                            pPort,
+                                            "Failed to get DHCP4 mode" );
+            }
+            else {
+              //
+              //  Get the last packet
+              //
+              pDhcp4Packet = Dhcp4Mode.ReplyPacket;
+              if ( NULL == pDhcp4Packet ) {
+                Status = HttpSendAnsiString ( SocketFD,
+                                              pPort,
+                                              "No DHCP reply received!<br/>DHCP Mode:<br/>" );
+                if ( EFI_ERROR ( Status )) {
+                  break;
+                }
+
+                //
+                //  Display the DHCP mode data
+                //
+                Status = HttpSendDump ( SocketFD,
+                                        pPort,
+                                        sizeof ( Dhcp4Mode ),
+                                        (UINT8 *)&Dhcp4Mode );
+              }
+              else {
+                //
+                //  Display the DHCP packet
+                //
+                Status = HttpSendDump ( SocketFD,
+                                        pPort,
+                                        pDhcp4Packet->Length,
+                                        (UINT8 *)&pDhcp4Packet->Dhcp4 );
+              }
+            }
+/*
+          }
+
+          //
+          //  Done with the DHCP protocol
+          //
+          pService->DestroyChild ( pService,
+                                   Dhcp4Handle );
+*/
+        }
+
+        //
+        //  Set the next service binding
+        //
+        pHandle += 1;
+      }
+    }
+
+    //
+    //  Send the page trailer
+    //
+    Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/DxeServicesTable.c b/AppPkg/Applications/Sockets/WebServer/DxeServicesTable.c
new file mode 100644 (file)
index 0000000..bfe90cd
--- /dev/null
@@ -0,0 +1,245 @@
+/*++
+  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
+  Display the DXE services table
+
+**/
+
+#include <WebServer.h>
+#include <Guid/DxeServices.h>
+#include <pi/PiDxeCis.h>
+
+/**
+  Respond with the DXE services table
+
+  @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
+DxeServicesTablePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_DXE_SERVICES * pDS;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the DXE services page
+  //
+  for ( ; ; ) {
+    //
+    //  Get the DXE services table
+    //
+    Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &pDS);
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"DXE Services Table", pDS );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The table header for the DXE Services Table.
+    /// This header contains the DXE_SERVICES_SIGNATURE and DXE_SERVICES_REVISION values.
+    ///
+    Status = EfiTableHeader ( SocketFD,
+                              pPort,
+                              &pDS->Hdr );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    // Global Coherency Domain Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "AddMemorySpace",
+                          (VOID *)pDS->AddMemorySpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "AllocateMemorySpace",
+                          (VOID *)pDS->AllocateMemorySpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "FreeMemorySpace",
+                          (VOID *)pDS->FreeMemorySpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RemoveMemorySpace",
+                          (VOID *)pDS->RemoveMemorySpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetMemorySpaceDescriptor",
+                          (VOID *)pDS->GetMemorySpaceDescriptor,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetMemorySpaceAttributes",
+                          (VOID *)pDS->SetMemorySpaceAttributes,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetMemorySpaceMap",
+                          (VOID *)pDS->GetMemorySpaceMap,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "AddIoSpace",
+                          (VOID *)pDS->AddIoSpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "AllocateIoSpace",
+                          (VOID *)pDS->AllocateIoSpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "FreeIoSpace",
+                          (VOID *)pDS->FreeIoSpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RemoveIoSpace",
+                          (VOID *)pDS->RemoveIoSpace,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetIoSpaceDescriptor",
+                          (VOID *)pDS->GetIoSpaceDescriptor,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetIoSpaceMap",
+                          (VOID *)pDS->GetIoSpaceMap,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    // Dispatcher Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "Dispatch",
+                          (VOID *)pDS->Dispatch,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "Schedule",
+                          (VOID *)pDS->Schedule,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "Trust",
+                          (VOID *)pDS->Trust,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    // Service to process a single firmware volume found in a capsule
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ProcessFirmwareVolume",
+                          (VOID *)pDS->ProcessFirmwareVolume,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/Firmware.c b/AppPkg/Applications/Sockets/WebServer/Firmware.c
new file mode 100644 (file)
index 0000000..4d5aad6
--- /dev/null
@@ -0,0 +1,106 @@
+/*++
+  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
+  Display the firmware
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Respond with the firmware status
+
+  @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
+FirmwarePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the system table page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"Firmware", NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the firmware vendor and revision
+    //
+    Status = RowUnicodeString ( SocketFD,
+                                pPort,
+                                "Vendor",
+                                gST->FirmwareVendor );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "Revision",
+                           gST->FirmwareRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the UEFI version
+    //
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "UEFI",
+                           gST->Hdr.Revision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/HTTP.c b/AppPkg/Applications/Sockets/WebServer/HTTP.c
new file mode 100644 (file)
index 0000000..a1716b2
--- /dev/null
@@ -0,0 +1,1570 @@
+/*++
+  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
+  HTTP processing for the web server.
+
+**/
+
+#include <WebServer.h>
+
+/**
+  Get a UTF-8 character from the buffer
+
+  @param [in] pData     The address of the buffer containing the character
+  @param [out] ppData   The address to receive the next character address
+
+  @returns    The character value
+
+**/
+INTN
+HttpCharGet (
+  IN UINT8 * pData,
+  IN UINT8 ** ppData
+  )
+{
+  INTN Data;
+  INTN Character;
+  INTN Control;
+  INTN Mask;
+
+  //
+  //  Verify that there is some data left
+  //
+  if ( NULL == pData ) {
+    //
+    //  No data to return
+    //
+    pData = NULL;
+    Character = 0;
+  }
+  else {
+    //
+    //  Get the first portion of the character
+    //
+    Character = *pData++;
+    Control = Character;
+    Mask = 0xc0;
+
+    //
+    //  Append the rest of the character
+    //
+    if ( 0 != ( Control & 0x80 )) {
+      while ( 0 != ( Control & 0x40 )) {
+        Character &= Mask;
+        Mask <<= 5;
+        Control <<= 1;
+        Character <<= 6;
+        Data = *pData++ & 0x3f;
+        if ( 0x80 != ( Data & 0xc0 )) {
+          //
+          //  Invalid character
+          //
+          pData = NULL;
+          Character = 0;
+          break;
+        }
+        Character |= Data & 0x3f;
+      }
+    }
+  }
+
+  //
+  //  Return the next character location and the character
+  //
+  *ppData = pData;
+  return Character;
+}
+
+
+/**
+  Transmit a portion of the HTTP response
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpFlush (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort
+  )
+{
+  INTN LengthInBytes;
+  UINT8 * pBuffer;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+  pBuffer = &pPort->TxBuffer[0];
+  do {
+    //
+    //  Attempt to send the data
+    //
+    LengthInBytes = send ( SocketFD,
+                           pBuffer,
+                           pPort->TxBytes,
+                           0 );
+    if ( -1 != LengthInBytes ) {
+      //
+      //  Account for the data sent
+      //
+      pBuffer += LengthInBytes;
+      pPort->TxBytes -= LengthInBytes;
+    }
+    else {
+      //
+      //  Transmit error
+      //
+      Status = EFI_DEVICE_ERROR;
+      break;
+    }
+  } while ( 0 < pPort->TxBytes );
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Convert the ANSI character to lower case
+
+  @param [in] Character The character to convert to lower case.
+
+  @returns  The lower case character
+
+**/
+INTN
+HttpLowerCase (
+  IN INTN Character
+  )
+{
+  //
+  //  Determine if the character is upper case
+  //
+  if (( 'A' <= Character ) && ( 'Z' >= Character )) {
+    Character += 'a' - 'A';
+  }
+
+  //
+  //  Return the lower case value of the character
+  //
+  return Character;
+}
+
+
+/**
+  Match a Unicode string against a UTF-8 string
+
+  @param [in] pString     A zero terminated Unicode string
+  @param [in] pData       A zero terminated UTF-8 string
+  @param [in] bIgnoreCase TRUE if case is to be ignored
+
+  @returns    The difference between the last two characters tested.
+              Returns -1 for error.
+
+**/
+INTN
+HttpMatch (
+  IN UINT16 * pString,
+  IN UINT8 * pData,
+  IN BOOLEAN bIgnoreCase
+  )
+{
+  INTN Character1;
+  INTN Character2;
+  INTN Difference;
+
+  do {
+    //
+    //  Get the character from the comparison string
+    //
+    Character1 = *pString++;
+
+    //
+    //  Convert the character to lower case
+    //
+    if ( bIgnoreCase ) {
+      Character1 = HttpLowerCase ( Character1 );
+    }
+
+    //
+    //  Get the character from the request
+    //
+    Character2 = HttpCharGet ( pData, &pData );
+    if ( NULL == pData ) {
+       //
+       // Error getting character
+       //
+       Difference = -1;
+       break;
+    }
+
+    //
+    //  Convert the character to lower case
+    //
+    if ( bIgnoreCase ) {
+      Character2 = HttpLowerCase ( Character2 );
+    }
+
+    //
+    //  Compare the characters
+    //
+    Difference = Character1 - Character2;
+    if ( 0 != Difference ) {
+      return Difference;
+    }
+  } while ( 0 != Character1 );
+
+  //
+  //  Return the difference
+  //
+  return Difference;
+}
+
+
+/**
+  Buffer the HTTP page header
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pTitle        A zero terminated Unicode title string
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpPageHeader (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR16 * pTitle
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Build the page header
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<!DOCTYPE "
+                                  "HTML "
+                                  "PUBLIC "
+                                  "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+                                  "\"http://www.w3.org/TR/html4/loose.dtd\">\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD, pPort, "<html lang=\"en-US\">\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    if ( NULL != pTitle ) {
+      Status = HttpSendAnsiString ( SocketFD, pPort, "  <head>\r\n" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD, pPort, "    <title>" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD, pPort, "</title>\r\n" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD, pPort, "  </head>\r\n" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    Status = HttpSendAnsiString ( SocketFD, pPort, "  <body>\r\n" );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Respond with an error indicating that the page was not found
+
+  @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
+HttpPageNotFound (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Send the page not found
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"404 Not found" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Send the page body
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "ERROR <b>404</b><br />"
+                                  "Requested page is not available\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;
+}
+
+
+/**
+  Buffer and send the HTTP page trailer
+
+  @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
+HttpPageTrailer (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN BOOLEAN * pbDone
+  )
+{
+  int RetVal;
+  EFI_STATUS Status;
+  socklen_t LengthInBytes;
+  struct sockaddr_in LocalAddress;
+  struct sockaddr_in RemoteAddress;
+
+  DBG_ENTER ( );
+
+  //
+  //  Build the page header
+  //
+  for ( ; ; ) {
+    LengthInBytes = sizeof ( LocalAddress );
+    RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );
+    if ( 0 == RetVal ) {
+      RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );
+      if ( 0 == RetVal ) {
+        //
+        //  Seperate the body from the trailer
+        //
+        Status = HttpSendAnsiString ( SocketFD, pPort, "  <hr>\r\n" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+
+        //
+        //  Display the system addresses and the page transfer direction
+        //
+        Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendAnsiString ( SocketFD, pPort, "  -->  " );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendIpAddress ( SocketFD, pPort, &RemoteAddress );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+        Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+    }
+
+    //
+    //  Terminate the page
+    //
+    Status = HttpSendAnsiString ( SocketFD, pPort, "  </body>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD, pPort, "  </html>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Send the page trailer
+    //
+    Status = HttpFlush ( SocketFD, pPort );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Mark the page as complete
+    //
+    *pbDone = TRUE;
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Replace a space with a zero
+
+  @param [in] pData     The request buffer address
+  @param [in] pEnd      End of buffer address
+
+  @returns    The next character location
+
+**/
+UINT8 *
+HttpReplaceSpace (
+  IN UINT8 * pData,
+  IN UINT8 * pEnd
+  )
+{
+  INTN Character;
+  UINT8 * pSpace;
+
+  pSpace = pData;
+  while ( pEnd > pData ) {
+    //
+    //  Get the character from the request
+    //
+    Character = HttpCharGet ( pData, &pData );
+    if ( ' ' == Character ) {
+      break;
+    }
+    pSpace = pData;
+  }
+
+  //
+  //  Replace the space character with zero
+  //
+  ZeroMem ( pSpace, pData - pSpace );
+
+  //
+  //  Return the next character location
+  //
+  return pData;
+}
+
+
+/**
+  Process an HTTP request
+
+  @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
+HttpRequest (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  UINT8 * pData;
+  UINT8 * pEnd;
+  CONST DT_PAGE * pPage;
+  CONST DT_PAGE * pPageEnd;
+  UINT8 * pVerb;
+  UINT8 * pVersion;
+  UINT8 * pWebPage;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Assume the request is not finished
+  //
+  *pbDone = FALSE;
+  Status = EFI_SUCCESS;
+  for ( ; ; ) {
+
+    //
+    //  Attempt to parse the command
+    //
+    pData = &pPort->Request[0];
+    pEnd = &pData [ pPort->RequestLength ];
+    pVerb = pData;
+    pWebPage = HttpReplaceSpace ( pVerb, pEnd );
+    if ( pEnd <= pWebPage ) {
+      break;
+    }
+    pVersion = HttpReplaceSpace ( pWebPage, pEnd );
+    if ( pEnd <= pVersion ) {
+      break;
+    }
+
+    //
+    //  Validate the request
+    //
+    if ( 0 != HttpMatch ( L"GET", pVerb, TRUE )) {
+      //
+      //  Invalid request type
+      //
+      DEBUG (( DEBUG_REQUEST,
+                "HTTP: Invalid verb\r\n" ));
+      Status = EFI_NOT_FOUND;
+      break;
+    }
+
+    //
+    //  Walk the page table
+    //
+    pPage = &mPageList[0];
+    pPageEnd = &pPage [ mPageCount ];
+    while ( pPageEnd > pPage ) {
+      //
+      //  Determine if the page was located
+      //
+      if ( 0 == HttpMatch ( pPage->pPageName, pWebPage, FALSE )) {
+        break;
+      }
+
+      //
+      //  Set the next page
+      //
+      pPage += 1;
+    }
+    if ( pPageEnd <= pPage ) {
+      //
+      //  The page was not found
+      //
+      DEBUG (( DEBUG_REQUEST,
+                "HTTP: Page not found in page table\r\n" ));
+      Status = EFI_NOT_FOUND;
+      break;
+    }
+
+    //
+    //  Respond with the page contents
+    //
+    Status = pPage->pfnResponse ( SocketFD, pPort, pbDone );
+    break;
+  }
+
+  //
+  //  Return page not found if necessary
+  //
+  if ( EFI_NOT_FOUND == Status ) {
+    Status = HttpPageNotFound ( SocketFD, pPort, pbDone );
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Buffer data for sending
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] LengthInBytes Length of valid data in the buffer
+  @param [in] pBuffer       Buffer of data to send
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSend (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN size_t LengthInBytes,
+  IN CONST UINT8 * pBuffer
+  )
+{
+  size_t DataBytes;
+  size_t MaxBytes;
+  EFI_STATUS Status;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+  do {
+    //
+    //  Determine how much data fits into the buffer
+    //
+    MaxBytes = sizeof ( pPort->TxBuffer );
+    DataBytes = MaxBytes - pPort->TxBytes;
+    if ( DataBytes > LengthInBytes )
+    {
+      DataBytes = LengthInBytes;
+    }
+
+    //
+    //  Copy the data into the buffer
+    //
+    CopyMem ( &pPort->TxBuffer [ pPort->TxBytes ],
+              pBuffer,
+              DataBytes );
+
+    //
+    //  Account for the data copied
+    //
+    pPort->TxBytes += DataBytes;
+    LengthInBytes -= DataBytes;
+
+    //
+    //  Transmit the buffer if it is full
+    //
+    if ( MaxBytes <= pPort->TxBytes ) {
+      Status = HttpFlush ( SocketFD, pPort );
+    }
+  } while (( EFI_SUCCESS == Status ) && ( 0 < LengthInBytes ));
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Send an ANSI string
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pString       A zero terminated Unicode string
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSendAnsiString (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST char * pString
+  )
+{
+  CONST char * pData;
+  EFI_STATUS Status;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Walk the characters in he string
+  //
+  pData = pString;
+  while ( 0 != *pData ) {
+    pData += 1;
+  }
+
+  //
+  //  Send the string
+  //
+  Status = HttpSend ( SocketFD,
+                      pPort,
+                      pData - pString,
+                      (CONST UINT8 *)pString );
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Buffer a single byte
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] Data          The data byte to send
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSendByte (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN UINT8 Data
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  //  Send the data byte
+  //
+  Status = HttpSend ( SocketFD,
+                      pPort,
+                      1,
+                      &Data );
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Display a character
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] Character     Character to display
+  @param [in] pReplacement  Replacement character string
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSendCharacter (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CHAR8 Character,
+  IN CHAR8 * pReplacement
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  //  Determine if this is a printable character
+  //
+  if (( 0x20 <= Character ) && ( 0x7f > Character )) {
+    if ( '<' == Character ) {
+      //
+      //  Replace with HTML equivalent
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "&lt;" );
+    }
+    else if ( '>' == Character ) {
+      //
+      //  Replace with HTML equivalent
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "&gt;" );
+    }
+    else if ( '&' == Character ) {
+      //
+      //  Replace with HTML equivalent
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "&amp;" );
+    }
+    else if ( '\"' == Character ) {
+      //
+      //  Replace with HTML equivalent
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "&quot;" );
+    }
+    else {
+      //
+      //  Display the character
+      //
+      Status = HttpSendByte ( SocketFD,
+                              pPort,
+                              Character );
+    }
+  }
+  else {
+    //
+    //  Not a displayable character
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pReplacement );
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Send a buffer dump
+  
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] ByteCount     The number of bytes to display
+  @param [in] pData         Address of the byte array
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSendDump (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN UINTN ByteCount,
+  IN CONST UINT8 * pData
+  )
+{
+  INTN BytesToDisplay;
+  UINT8 Character;
+  INTN Index;
+  INTN InitialSpaces;
+  CONST UINT8 * pDataEnd;
+  CONST UINT8 * pEnd;
+  CONST UINT8 * pTemp;
+  EFI_STATUS Status;
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Start the field value
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Walk the bytes to be displayed
+    //
+    pEnd = &pData [ ByteCount ];
+    while ( pEnd > pData ) {
+      //
+      //  Display the address
+      //
+      Status = HttpSendHexBits ( SocketFD,
+                                 pPort,
+                                 sizeof ( pData ) * 8,
+                                 (UINT64)pData );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Separate the address and data
+      //
+      Status = HttpSendByte ( SocketFD, pPort, ':' );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      
+      //
+      //  Position the starting data correctly
+      //
+      InitialSpaces = (UINTN)pData;
+      InitialSpaces &= BYTES_ON_A_LINE - 1;
+      for ( Index = SPACES_ADDRESS_TO_DATA
+                  + (( 2 + SPACES_BETWEEN_BYTES )
+                        * InitialSpaces );
+            0 < Index; Index-- ) {
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "&nbsp;" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Display the data
+      //
+      BytesToDisplay = pEnd - pData;
+      if (( BYTES_ON_A_LINE - InitialSpaces ) < BytesToDisplay ) {
+        BytesToDisplay = BYTES_ON_A_LINE - InitialSpaces;
+      }
+      pDataEnd = &pData [ BytesToDisplay ];
+      pTemp = pData;
+      while ( pDataEnd > pTemp ) {
+        Status = HttpSendHexBits ( SocketFD,
+                                   pPort,
+                                   8,
+                                   *pTemp++ );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+
+        //
+        //  Separate the data bytes
+        //
+        for ( Index = SPACES_BETWEEN_BYTES; 0 < Index; Index-- ) {
+          Status = HttpSendAnsiString ( SocketFD,
+                                        pPort,
+                                        "&nbsp;" );
+          if ( EFI_ERROR ( Status )) {
+            break;
+          }
+        }
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Separate the data from the ASCII display
+      //
+      for ( Index = (( 2 + SPACES_BETWEEN_BYTES )
+                       * ( BYTES_ON_A_LINE - BytesToDisplay - InitialSpaces ))
+                  - SPACES_BETWEEN_BYTES
+                  + SPACES_DATA_TO_ASCII
+                  + InitialSpaces;
+            0 < Index; Index-- ) {
+        Status = HttpSendAnsiString ( SocketFD,
+                                      pPort,
+                                      "&nbsp;" );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Display the ASCII data
+      //
+      while ( pDataEnd > pData ) {
+        Character = *pData++;
+        Status = HttpSendCharacter ( SocketFD,
+                                     pPort,
+                                     Character,
+                                     "." );
+        if ( EFI_ERROR ( Status )) {
+          break;
+        }
+      }
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Terminate the line
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "<br/>\r\n" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+
+    //
+    //  Terminate the field value and row
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Display a row containing a GUID value
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pGuid         Address of the GUID to display
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSendGuid (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST EFI_GUID * pGuid
+  )
+{
+  UINT32 Index;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Display the GUID in a form found in the code
+    //
+    //  E.g. 0xca16005f, 0x11ec, 0x4bdc, { 0x99, 0x97, 0x27, 0x2c, 0xa9, 0xba, 0x15, 0xe5 }
+    //
+
+    //
+    //  Display the first 32 bits
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendHexBits ( SocketFD,
+                               pPort,
+                               32,
+                               pGuid->Data1 );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the second 16 bits
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  ", 0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendHexBits ( SocketFD,
+                               pPort,
+                               16,
+                               pGuid->Data2 );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Display the thrid 16 bits
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  ", 0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendHexBits ( SocketFD,
+                               pPort,
+                               16,
+                               pGuid->Data3 );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Place the last 64 bits in braces
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  ", { 0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    for ( Index = 0; 7 >= Index; Index++ ) {
+      //
+      //  Display the next 8 bits
+      //
+      Status = HttpSendHexBits ( SocketFD,
+                                 pPort,
+                                 8,
+                                 pGuid->Data4 [ Index ]);
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Separate the bytes
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    ( 7 != Index ) ? ", 0x" : " }" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Output a hex value to the HTML page
+
+  @param [in] SocketFD    Socket file descriptor
+  @param [in] pPort       The WSDT_PORT structure address
+  @param [in] Bits        Number of bits to display
+  @param [in] Value       Value to display
+
+  @retval EFI_SUCCESS Successfully displayed the address
+**/
+EFI_STATUS
+HttpSendHexBits (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN INT32 Bits,
+  IN UINT64 Value
+  )
+{
+  UINT32 Digit;
+  INT32 Shift;
+  EFI_STATUS Status;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Walk the list of divisors
+  //
+  Shift = (( Bits + 3 ) & ( ~3 )) - 4;
+  while ( 0 <= Shift ) {
+    //
+    //  Determine the next digit
+    //
+    Digit = (UINT32)(( Value >> Shift ) & 0xf );
+    if ( 10 <= Digit ) {
+      Digit += 'A' - '0' - 10;
+    }
+
+    //
+    //  Display the digit
+    //
+    Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Set the next shift
+    //
+    Shift -= 4;
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Output a hex value to the HTML page
+
+  @param [in] SocketFD    Socket file descriptor
+  @param [in] pPort       The WSDT_PORT structure address
+  @param [in] Value       Value to display
+
+  @retval EFI_SUCCESS Successfully displayed the address
+**/
+EFI_STATUS
+HttpSendHexValue (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN UINT64 Value
+  )
+{
+  BOOLEAN bDisplayZeros;
+  UINT32 Digit;
+  INT32 Shift;
+  EFI_STATUS Status;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Walk the list of divisors
+  //
+  bDisplayZeros = FALSE;
+  Shift = 60;
+  do {
+    //
+    //  Determine the next digit
+    //
+    Digit = (UINT32)(( Value >> Shift ) & 0xf );
+    if ( 10 <= Digit ) {
+      Digit += 'A' - '0' - 10;
+    }
+
+    //
+    //  Suppress leading zeros
+    //
+    if (( 0 != Digit ) || bDisplayZeros || ( 0 == Shift )) {
+      bDisplayZeros = TRUE;
+
+      //
+      //  Display the digit
+      //
+      Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+
+    //
+    //  Set the next shift
+    //
+    Shift -= 4;
+  } while ( 0 <= Shift );
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Output an IP address to the HTML page
+
+  @param [in] SocketFD    Socket file descriptor
+  @param [in] pPort       The WSDT_PORT structure address
+  @param [in] pAddress    Address of the socket address
+
+  @retval EFI_SUCCESS Successfully displayed the address
+**/
+EFI_STATUS
+HttpSendIpAddress (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN struct sockaddr_in * pAddress
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  //  Output the IPv4 address
+  //
+  Status = HttpSendValue ( SocketFD, pPort, (UINT8)pAddress->sin_addr.s_addr );
+  if ( !EFI_ERROR ( Status )) {
+    Status = HttpSendByte ( SocketFD, pPort, '.' );
+    if ( !EFI_ERROR ( Status )) {
+      Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 8 ));
+      if ( !EFI_ERROR ( Status )) {
+        Status = HttpSendByte ( SocketFD, pPort, '.' );
+        if ( !EFI_ERROR ( Status )) {
+          Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 16 ));
+          if ( !EFI_ERROR ( Status )) {
+            Status = HttpSendByte ( SocketFD, pPort, '.' );
+            if ( !EFI_ERROR ( Status )) {
+              Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 24 ));
+              if ( !EFI_ERROR ( Status )) {
+                //
+                //  Output the port number
+                //
+                Status = HttpSendByte ( SocketFD, pPort, ':' );
+                if ( !EFI_ERROR ( Status )) {
+                  Status = HttpSendValue ( SocketFD, pPort, htons ( pAddress->sin_port ));
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Send a Unicode string
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pString       A zero terminated Unicode string
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+HttpSendUnicodeString (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST UINT16 * pString
+  )
+{
+  UINT8 Data;
+  UINT16 Character;
+  EFI_STATUS Status;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Walk the characters in he string
+  //
+  while ( 0 != ( Character = *pString++ )) {
+    //
+    //  Convert the character to UTF-8
+    //
+    if ( 0 != ( Character & 0xf800 )) {
+      //
+      //  Send the upper 4 bits
+      //
+      Data = (UINT8)(( Character >> 12 ) & 0xf );
+      Data |= 0xe0;
+      Status = HttpSendByte ( SocketFD,
+                              pPort,
+                              Data );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Send the next 6 bits
+      //
+      Data = (UINT8)(( Character >> 6 ) & 0x3f );
+      Data |= 0x80;
+      Status = HttpSendByte ( SocketFD,
+                              pPort,
+                              Data );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Send the last 6 bits
+      //
+      Data = (UINT8)( Character & 0x3f );
+      Data |= 0x80;
+    }
+    else if ( 0 != ( Character & 0x0780 )) {
+      //
+      //  Send the upper 5 bits
+      //
+      Data = (UINT8)(( Character >> 6 ) & 0x1f );
+      Data |= 0xc0;
+      Status = HttpSendByte ( SocketFD,
+                              pPort,
+                              Data );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Send the last 6 bits
+      //
+      Data = (UINT8)( Character & 0x3f );
+      Data |= 0x80;
+    }
+    else {
+      Data = (UINT8)( Character & 0x7f );
+    }
+
+    //
+    //  Send the last data byte
+    //
+    Status = HttpSendByte ( SocketFD,
+                            pPort,
+                            Data );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
+
+
+/**
+  Output a value to the HTML page
+
+  @param [in] SocketFD    Socket file descriptor
+  @param [in] pPort       The WSDT_PORT structure address
+  @param [in] Value       Value to display
+
+  @retval EFI_SUCCESS Successfully displayed the address
+**/
+EFI_STATUS
+HttpSendValue (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN UINT64 Value
+  )
+{
+  BOOLEAN bDisplayZeros;
+  UINT64 Digit;
+  CONST UINT64 * pEnd;
+  CONST UINT64 * pDivisor;
+  CONST UINT64 pDivisors [ ] = {
+     10000000000000000000L,
+      1000000000000000000L,
+       100000000000000000L,
+        10000000000000000L,
+         1000000000000000L,
+          100000000000000L,
+           10000000000000L,
+            1000000000000L,
+             100000000000L,
+              10000000000L,
+               1000000000L,
+                100000000L,
+                 10000000L,
+                  1000000L,
+                   100000L,
+                    10000L,
+                     1000L,
+                      100L,
+                       10L
+  };
+  EFI_STATUS Status;
+  UINT64 Temp;
+
+  //
+  //  Assume success
+  //
+  Status = EFI_SUCCESS;
+
+  //
+  //  Walk the list of divisors
+  //
+  bDisplayZeros = FALSE;
+  pDivisor = &pDivisors[0];
+  pEnd = &pDivisor [ sizeof ( pDivisors ) / sizeof ( pDivisors [0])];
+  while ( pEnd > pDivisor ) {
+    //
+    //  Determine the next digit
+    //
+    Digit = Value / *pDivisor;
+
+    //
+    //  Suppress leading zeros
+    //
+    if (( 0 != Digit ) || bDisplayZeros ) {
+      bDisplayZeros = TRUE;
+
+      //
+      //  Display the digit
+      //
+      Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Determine the remainder
+      //
+      Temp = *pDivisor * Digit;
+      Value -= Temp;
+    }
+
+    //
+    //  Set the next divisor
+    //
+    pDivisor += 1;
+  }
+
+  //
+  //  Display the final digit
+  //
+  if ( !EFI_ERROR ( Status )) {
+    Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Value ));
+  }
+
+  //
+  //  Return the operation status
+  //
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/Handles.c b/AppPkg/Applications/Sockets/WebServer/Handles.c
new file mode 100644 (file)
index 0000000..f39620a
--- /dev/null
@@ -0,0 +1,294 @@
+/*++
+  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
+  Display the handles in the system
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Respond with the handles in the system
+
+  @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
+HandlePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  INTN Digit;
+  INTN Entries;
+  INTN Index;
+  UINTN GuidCount;
+  UINTN LengthInBytes;
+  UINT8 * pDigit;
+  EFI_HANDLE * pHandleArray;
+  EFI_HANDLE * pHandle;
+  EFI_HANDLE * pHandleEnd;
+  EFI_GUID ** ppGuidArray;
+  EFI_GUID ** ppGuid;
+  EFI_GUID ** ppGuidEnd;
+  INTN Shift;
+  EFI_STATUS Status;
+  UINTN Value;
+  CONST UINTN cDigit [] = {
+    3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
+  
+  DBG_ENTER ( );
+  
+  //
+  //  Send the handles page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"Handle Database" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table header
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>Handle Database</h1>\r\n"
+                                  "<table border=\"1\">\r\n"
+                                  "  <tr bgcolor=\"c0c0ff\"><th>Handle</th><th>Protocol Guids</th></tr>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Determine the number of handles in the database
+    //
+    LengthInBytes = 0;
+    Status = gBS->LocateHandle ( AllHandles,
+                                 NULL,
+                                 NULL,
+                                 &LengthInBytes,
+                                 NULL );
+    if ( EFI_BUFFER_TOO_SMALL == Status ) {
+      //
+      //  Allocate space for the handles
+      //
+      Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+                                   LengthInBytes,
+                                   (VOID **) &pHandleArray );
+      if ( !EFI_ERROR ( Status )) {
+        //
+        //  Get the list of handles
+        //
+        Status = gBS->LocateHandle ( AllHandles,
+                                     NULL,
+                                     NULL,
+                                     &LengthInBytes,
+                                     pHandleArray );
+        if ( !EFI_ERROR ( Status )) {
+          Entries = LengthInBytes / sizeof ( *pHandleArray );
+          pHandle = pHandleArray;
+          pHandleEnd = &pHandle [ Entries ];
+          while ( pHandleEnd > pHandle ) {
+            //
+            //  Build the table entry for this page
+            //
+            Status = HttpSendAnsiString ( SocketFD,
+                                          pPort,
+                                          "<tr><td><code>0x" );
+            if ( EFI_ERROR ( Status )) {
+              break;
+            }
+            Value = (UINTN) *pHandle;
+            for ( Shift = ( sizeof ( Shift ) << 3 ) - 4; 0 <= Shift; Shift -= 4 ) {
+              //
+              //  Convert the next address nibble to ANSI hex
+              //
+              Digit = (( Value >> Shift ) & 0xf ) | '0';
+              if ( '9' < Digit ) {
+                Digit += 'a' - '0' - 10;
+              }
+
+              //
+              //  Display the address digit
+              //
+              Status = HttpSendByte ( SocketFD,
+                                      pPort,
+                                      (UINT8) Digit );
+              if ( EFI_ERROR ( Status )) {
+                break;
+              }
+            }
+            if ( EFI_ERROR ( Status )) {
+              break;
+            }
+
+            //
+            //  Start the second column
+            //
+            Status = HttpSendAnsiString ( SocketFD,
+                                          pPort,
+                                          "</code></td><td><code>\r\n" );
+            if ( EFI_ERROR ( Status )) {
+              break;
+            }
+
+            //
+            //  Determine the number of protocols connected to this handle
+            //
+            Status = gBS->ProtocolsPerHandle ( *pHandle,
+                                               &ppGuidArray,
+                                               &GuidCount );
+            if ( EFI_ERROR ( Status )) {
+              break;
+            }
+            ppGuid = ppGuidArray;
+            ppGuidEnd = &ppGuid [ GuidCount ];
+            while ( ppGuidEnd > ppGuid ) {
+              //
+              //  Display the guid
+              //
+              pDigit = (UINT8 *) *ppGuid;
+              for ( Index = 0; 16 > Index; Index++ ) {
+                //
+                //  Separate the portions of the GUID
+                //  99E87DCF-6162-40c5-9FA1-32111F5197F7
+                //
+                if (( 4 == Index )
+                  || ( 6 == Index )
+                  || ( 8 == Index )
+                  || ( 10 == Index )) {
+                  Status = HttpSendByte ( SocketFD,
+                                          pPort,
+                                          '-' );
+                  if ( EFI_ERROR ( Status )) {
+                    break;
+                  }
+                }
+
+                //
+                //  Display the GUID digits
+                //
+                Value = pDigit [ cDigit [ Index ]];
+                for ( Shift = 4; 0 <= Shift; Shift -= 4 ) {
+                  //
+                  //  Convert the next address nibble to ANSI hex
+                  //
+                  Digit = (( Value >> Shift ) & 0xf ) | '0';
+                  if ( '9' < Digit ) {
+                    Digit += 'a' - '0' - 10;
+                  }
+                
+                  //
+                  //  Display the address digit
+                  //
+                  Status = HttpSendByte ( SocketFD,
+                                          pPort,
+                                          (UINT8) Digit );
+                  if ( EFI_ERROR ( Status )) {
+                    break;
+                  }
+                }
+                if ( EFI_ERROR ( Status )) {
+                  break;
+                }
+              }
+
+              //
+              //  Separate each GUID
+              //
+              Status = HttpSendAnsiString ( SocketFD,
+                                            pPort,
+                                            "<br/>\r\n" );
+              if ( EFI_ERROR ( Status )) {
+                break;
+              }
+
+              //
+              //  Set the next protocol
+              //
+              ppGuid+= 1;
+            }
+
+            //
+            //  Free the GUID array
+            //
+            gBS->FreePool ( ppGuidArray );
+            if ( EFI_ERROR ( Status )) {
+              break;
+            }
+
+            //
+            //  End the row
+            //
+            Status = HttpSendAnsiString ( SocketFD,
+                                          pPort,
+                                          "</code></td></tr>\r\n" );
+            if ( EFI_ERROR ( Status )) {
+              break;
+            }
+
+            //
+            //  Set the next handle
+            //
+            pHandle += 1;
+          }
+        }
+
+        //
+        //  Done with the handle array
+        //
+        gBS->FreePool ( pHandleArray );
+      }
+    }
+    
+    //
+    //  Build the table trailer
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</table>\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;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/Hello.c b/AppPkg/Applications/Sockets/WebServer/Hello.c
new file mode 100644 (file)
index 0000000..5f65133
--- /dev/null
@@ -0,0 +1,87 @@
+/*++
+  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
+  Hello World response page
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Respond with the Hello World 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
+HelloPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+  
+  DBG_ENTER ( );
+  
+  //
+  //  Send the Hello World page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"Hello World" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Send the page body
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>Hello World</h1>\r\n"
+                                  "<p>\r\n"
+                                  "  This response was generated by the UEFI 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;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/Index.c b/AppPkg/Applications/Sockets/WebServer/Index.c
new file mode 100644 (file)
index 0000000..688d197
--- /dev/null
@@ -0,0 +1,161 @@
+/*++
+  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
+  Generate the list of known pages.
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Respond with the list of known pages
+
+  @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
+IndexPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  CONST DT_PAGE * pPage;
+  CONST DT_PAGE * pPageEnd;
+  EFI_STATUS Status;
+  
+  DBG_ENTER ( );
+  
+  //
+  //  Send the index page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"Index" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table header
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>UEFI Web Server</h1>\r\n"
+                                  "<table border=\"1\">\r\n"
+                                  "  <tr bgcolor=\"c0c0ff\"><th>Page</th><th>Description</th></tr>\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Walk the list of pages
+    //  Skip the first page
+    //
+    pPage = &mPageList[0];
+    pPageEnd = &pPage[mPageCount];
+    pPage += 1;
+    while ( pPageEnd > pPage ) {
+      //
+      //  Build the table entry for this page
+      //
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "<tr><td><a target=\"_blank\" href=\"" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD,
+                                       pPort,
+                                       &pPage->pPageName[1]);
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "\">" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD,
+                                       pPort,
+                                       &pPage->pPageName[1]);
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "</a></td><td>" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD,
+                                       pPort,
+                                       pPage->pDescription );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "</td></tr>\r\n" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+
+      //
+      //  Set the next page
+      //
+      pPage += 1;
+    }
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Build the table trailer
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</table>\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;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/PageList.c b/AppPkg/Applications/Sockets/WebServer/PageList.c
new file mode 100644 (file)
index 0000000..5eccfb2
--- /dev/null
@@ -0,0 +1,59 @@
+/*++
+  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
+  List of pages to display
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  List of pages in the system
+**/
+CONST DT_PAGE mPageList [] = {
+
+  //
+  //  The index page must be first
+  //
+  { L"/", IndexPage, L"Index of pages" },   ///<  List the pages
+
+  //
+  //  All other pages follow in alphabetical order
+  //
+  { PAGE_BOOT_SERVICES_TABLE, BootServicesTablePage, L"Boot Services Table" },          ///<  Format boot services table
+  { PAGE_CONFIGURATION_TABLE, ConfigurationTablePage, L"Configuration Table" },         ///<  Format configuration 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
+  { 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"/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
+  { PAGE_ACPI_RSDT, AcpiRsdtPage, L"RSDT - ACPI Root System Description Table" },       ///<  Format RSDT
+  { PAGE_RUNTIME_SERVICES_TABLE, RuntimeSservicesTablePage, L"Runtime Services Table" },///<  Format runtime services table
+  { L"/SystemTable", SystemTablePage, L"System Table" } ///<  Format system table
+};
+
+CONST UINTN mPageCount = DIM ( mPageList );
diff --git a/AppPkg/Applications/Sockets/WebServer/Reboot.c b/AppPkg/Applications/Sockets/WebServer/Reboot.c
new file mode 100644 (file)
index 0000000..51c72d6
--- /dev/null
@@ -0,0 +1,105 @@
+/*++
+  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
+  Reboot the system
+
+**/
+
+#include <WebServer.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+
+/**
+  Page to reboot the system
+
+  @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
+RebootPage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+  
+  DBG_ENTER ( );
+  
+  //
+  //  Send the Hello World page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, L"Reboot" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Send the page body
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>Reboot</h1>\r\n"
+                                  "<p>\r\n"
+                                  "  Ouch!  The system is rebooting!\r\n" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+  
+    //
+    //  Send the page trailer
+    //
+    Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Deliver the data to the remote system by
+    //  closing the socket
+    //
+    close ( SocketFD );
+
+    //
+    //  Attempt to reboot the system
+    //
+    DEBUG (( DEBUG_REQUEST, "Reseting System\r\n" ));
+    gRT->ResetSystem ( EfiResetCold,
+                       EFI_SUCCESS,
+                       0,
+                       NULL );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/RuntimeServicesTable.c b/AppPkg/Applications/Sockets/WebServer/RuntimeServicesTable.c
new file mode 100644 (file)
index 0000000..778d3bb
--- /dev/null
@@ -0,0 +1,227 @@
+/*++
+  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
+  Display the runtime services table
+
+**/
+
+#include <WebServer.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+/**
+  Respond with the runtime services table
+
+  @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
+RuntimeSservicesTablePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the runtime services page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"Runtime Services Table", gRT );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The table header for the EFI Runtime Services Table.
+    ///
+    Status = EfiTableHeader ( SocketFD,
+                              pPort,
+                              &gRT->Hdr );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    // Time Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetTime",
+                          (VOID *)gRT->GetTime,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetTime",
+                          (VOID *)gRT->SetTime,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetWakeupTime",
+                          (VOID *)gRT->GetWakeupTime,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetWakeupTime",
+                          (VOID *)gRT->SetWakeupTime,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    // Virtual Memory Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetVirtualAddressMap",
+                          (VOID *)gRT->SetVirtualAddressMap,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConvertPointer",
+                          (VOID *)gRT->ConvertPointer,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    // Variable Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetVariable",
+                          (VOID *)gRT->GetVariable,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetNextVariableName",
+                          (VOID *)gRT->GetNextVariableName,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "SetVariable",
+                          (VOID *)gRT->SetVariable,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    // Miscellaneous Services
+    //
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "GetNextHighNonotonicCount",
+                          (VOID *)gRT->GetNextHighMonotonicCount,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ResetSystem",
+                          (VOID *)gRT->ResetSystem,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Determine if the structures supports 2.0 services
+    //
+    if ( 2 <= ( gRT->Hdr.Revision >> 16 )) {
+      //
+      // UEFI 2.0 Capsule Services
+      //
+      Status = RowPointer ( SocketFD,
+                            pPort,
+                            "UpdateCapsule",
+                            (VOID *)gRT->UpdateCapsule,
+                            NULL );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = RowPointer ( SocketFD,
+                            pPort,
+                            "QueryCapsuleCapabilities",
+                            (VOID *)gRT->QueryCapsuleCapabilities,
+                            NULL );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    
+      //
+      // Miscellaneous UEFI 2.0 Service
+      //
+      Status = RowPointer ( SocketFD,
+                            pPort,
+                            "QueryVariableInfo",
+                            (VOID *)gRT->QueryVariableInfo,
+                            NULL );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/SystemTable.c b/AppPkg/Applications/Sockets/WebServer/SystemTable.c
new file mode 100644 (file)
index 0000000..0d2a1f2
--- /dev/null
@@ -0,0 +1,863 @@
+/*++
+  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
+  Display the system table
+
+**/
+
+#include <WebServer.h>
+
+
+/**
+  Display the EFI Table Header
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pHeader       Address of the EFI_TABLE_HEADER structure
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+EfiTableHeader (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN EFI_TABLE_HEADER * pHeader
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the handles page
+  //
+  for ( ; ; ) {
+    ///
+    /// A 64-bit signature that identifies the type of table that follows.
+    /// Unique signatures have been generated for the EFI System Table,
+    /// the EFI Boot Services Table, and the EFI Runtime Services Table.
+    ///
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Hdr.Signature",
+                           pHeader->Signature,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The revision of the EFI Specification to which this table
+    /// conforms. The upper 16 bits of this field contain the major
+    /// revision value, and the lower 16 bits contain the minor revision
+    /// value. The minor revision values are limited to the range of 00..99.
+    ///
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "Hdr.Revision",
+                           pHeader->Revision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER.
+    ///
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "Hdr.HeaderSize",
+                               pHeader->HeaderSize );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The 32-bit CRC for the entire table. This value is computed by
+    /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes.
+    ///
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Hdr.CRC",
+                           pHeader->CRC32,
+                           NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// Reserved field that must be set to 0.
+    ///
+    Status = RowHexValue ( SocketFD,
+                           pPort,
+                           "Hdr.Reserved",
+                           pHeader->Reserved,
+                           NULL );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Display a row containing a decimal value
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] Value         The value to display
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowDecimalValue (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN UINT64 Value
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendValue ( SocketFD,
+                             pPort,
+                             Value );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Display a row containing a hex value
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] Value         The value to display
+  @param [in] pWebPage      Address of a zero terminated web page name
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowHexValue (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN UINT64 Value,
+  IN CONST CHAR16 * pWebPage
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    if ( NULL != pWebPage ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "<a target=\"_blank\" href=\"" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD,
+                                       pPort,
+                                       pWebPage );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "\">" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    Status = HttpSendHexValue ( SocketFD,
+                                pPort,
+                                Value );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    if ( NULL != pWebPage ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "</a>" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Display a row containing a pointer
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] pAddress      The address to display
+  @param [in] pWebPage      Address of a zero terminated web page name
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowPointer (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN CONST VOID * pAddress,
+  IN CONST CHAR16 * pWebPage
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    if ( NULL != pWebPage ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "<a target=\"_blank\" href=\"" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendUnicodeString ( SocketFD,
+                                       pPort,
+                                       pWebPage );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "\">" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "0x" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendHexBits ( SocketFD,
+                               pPort,
+                               sizeof ( pAddress ) * 8,
+                               (UINT64) pAddress );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    if ( NULL != pWebPage ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    "</a>" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Display a row containing a revision
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] Revision      The revision to display
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowRevision (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN UINT32 Revision
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td><code>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendValue ( SocketFD,
+                             pPort,
+                             Revision >> 16 );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendByte ( SocketFD,
+                            pPort,
+                            '.' );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendValue ( SocketFD,
+                             pPort,
+                             Revision & 0xFFFF );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</code></td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Display a row containing a unicode string
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] pString       Address of a zero terminated unicode string
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+RowUnicodeString (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR8 * pName,
+  IN CONST CHAR16 * pString
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<tr><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td><td>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendUnicodeString ( SocketFD,
+                                     pPort,
+                                     pString );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</td></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Start the table page
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+  @param [in] pPort         The WSDT_PORT structure address
+  @param [in] pName         Address of a zero terminated name string
+  @param [in] pTable        Address of the table
+
+  @retval EFI_SUCCESS       The request was successfully processed
+
+**/
+EFI_STATUS
+TableHeader (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  IN CONST CHAR16 * pName,
+  IN CONST VOID * pTable
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page header
+    //
+    Status = HttpPageHeader ( SocketFD, pPort, pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    
+    //
+    //  Build the table header
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "<h1>" );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    Status = HttpSendUnicodeString ( SocketFD,
+                                     pPort,
+                                     pName );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+    if ( NULL != pTable ) {
+      Status = HttpSendAnsiString ( SocketFD,
+                                    pPort,
+                                    ": 0x" );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+      Status = HttpSendHexBits ( SocketFD,
+                                 pPort,
+                                 sizeof ( pTable ) *  8,
+                                 (UINT64)pTable );
+      if ( EFI_ERROR ( Status )) {
+        break;
+      }
+    }
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</h1>\r\n"
+                                  "<table border=\"1\">\r\n"
+                                  "  <tr bgcolor=\"c0c0ff\"><th>Field Name</th><th>Value</th></tr>\r\n" );
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  End the table 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
+TableTrailer (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN *pbDone
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Build the table trailer
+    //
+    Status = HttpSendAnsiString ( SocketFD,
+                                  pPort,
+                                  "</table>\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;
+}
+
+
+/**
+  Respond with the system table
+
+  @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
+SystemTablePage (
+  IN int SocketFD,
+  IN WSDT_PORT * pPort,
+  OUT BOOLEAN * pbDone
+  )
+{
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+  
+  //
+  //  Send the system table page
+  //
+  for ( ; ; ) {
+    //
+    //  Send the page and table header
+    //
+    Status = TableHeader ( SocketFD, pPort, L"System Table", gST );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The table header for the EFI System Table.
+    ///
+    Status = EfiTableHeader ( SocketFD,
+                              pPort,
+                              &gST->Hdr );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A pointer to a null terminated string that identifies the vendor
+    /// that produces the system firmware for the platform.
+    ///
+    Status = RowUnicodeString ( SocketFD,
+                                pPort,
+                                "FirmwareVendor",
+                                gST->FirmwareVendor );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A firmware vendor specific value that identifies the revision
+    /// of the system firmware for the platform.
+    ///
+    Status = RowRevision ( SocketFD,
+                           pPort,
+                           "FirmwareRevision",
+                           gST->FirmwareRevision );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The handle for the active console input device. This handle must support
+    /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConsoleInHandle",
+                          (VOID *)gST->ConsoleInHandle,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is
+    /// associated with ConsoleInHandle.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConIn",
+                          (VOID *)gST->ConIn,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The handle for the active console output device.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConsoleOutHandle",
+                          (VOID *)gST->ConsoleOutHandle,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
+    /// that is associated with ConsoleOutHandle.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConOut",
+                          (VOID *)gST->ConOut,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The handle for the active standard error console device.
+    /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "StandardErrorHandle",
+                          (VOID *)gST->StandardErrorHandle,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
+    /// that is associated with StandardErrorHandle.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "StdErr",
+                          (VOID *)gST->StdErr,
+                          NULL );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A pointer to the EFI Runtime Services Table.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "RuntimeServices",
+                          (VOID *)gST->RuntimeServices,
+                          PAGE_RUNTIME_SERVICES_TABLE );
+
+    ///
+    /// A pointer to the EFI Boot Services Table.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "BootServices",
+                          (VOID *)gST->BootServices,
+                          PAGE_BOOT_SERVICES_TABLE );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// The number of system configuration tables in the buffer ConfigurationTable.
+    ///
+    Status = RowDecimalValue ( SocketFD,
+                               pPort,
+                               "NumberOfTableEntries",
+                               gST->NumberOfTableEntries );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    ///
+    /// A pointer to the system configuration tables.
+    /// The number of entries in the table is NumberOfTableEntries.
+    ///
+    Status = RowPointer ( SocketFD,
+                          pPort,
+                          "ConfigurationTable",
+                          (VOID *)gST->ConfigurationTable,
+                          PAGE_CONFIGURATION_TABLE );
+    if ( EFI_ERROR ( Status )) {
+      break;
+    }
+
+    //
+    //  Build the table trailer
+    //
+    Status = TableTrailer ( SocketFD,
+                            pPort,
+                            pbDone );
+    break;
+  }
+    
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/WebServer.c b/AppPkg/Applications/Sockets/WebServer/WebServer.c
new file mode 100644 (file)
index 0000000..00bf4b6
--- /dev/null
@@ -0,0 +1,853 @@
+/*++
+  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
+  This is a simple shell application
+
+  This should be executed with "/Param2 Val1" and "/Param1" as the 2 command line options!
+
+**/
+
+#include <WebServer.h>
+
+DT_WEB_SERVER mWebServer;   ///<  Web server's control structure
+
+
+/**
+  Add a port to the list of ports to be polled.
+
+  @param [in] pWebServer    The web server control structure address.
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+
+  @retval EFI_SUCCESS       The port was successfully added
+  @retval EFI_NO_RESOURCES  Insufficient memory to add the port
+
+**/
+EFI_STATUS
+PortAdd (
+  IN DT_WEB_SERVER * pWebServer,
+  IN int SocketFD
+  )
+{
+  nfds_t Index;
+  size_t LengthInBytes;
+  nfds_t MaxEntries;
+  nfds_t MaxEntriesNew;
+  struct pollfd * pFdList;
+  struct pollfd * pFdListNew;
+  WSDT_PORT ** ppPortListNew;
+  WSDT_PORT * pPort;
+  EFI_STATUS Status;
+
+  DBG_ENTER ( );
+
+  //
+  //  Use for/break instead of goto
+  //
+  for ( ; ; ) {
+    //
+    //  Assume success
+    //
+    Status = EFI_SUCCESS;
+
+    //
+    //  Create a new list if necessary
+    //
+    pFdList = pWebServer->pFdList;
+    MaxEntries = pWebServer->MaxEntries;
+    if ( pWebServer->Entries >= MaxEntries ) {
+      MaxEntriesNew = 16 + MaxEntries;
+
+      //
+      //  The current FD list is full
+      //  Allocate a new FD list
+      //
+      LengthInBytes = sizeof ( *pFdList ) * MaxEntriesNew;
+      Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+                                   LengthInBytes,
+                                   (VOID **)&pFdListNew );
+      if ( EFI_ERROR ( Status )) {
+        DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+                  "ERROR - Failed to allocate the FD list, Status: %r\r\n",
+                  Status ));
+        break;
+      }
+
+      //
+      //  Allocate a new port list
+      //
+      LengthInBytes = sizeof ( *ppPortListNew ) * MaxEntriesNew;
+      Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+                                   LengthInBytes,
+                                   (VOID **) &ppPortListNew );
+      if ( EFI_ERROR ( Status )) {
+        DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+                  "ERROR - Failed to allocate the port list, Status: %r\r\n",
+                  Status ));
+
+        //
+        //  Free the new FD list
+        //
+        gBS->FreePool ( pFdListNew );
+        break;
+      }
+
+      //
+      //  Duplicate the FD list
+      //
+      Index = MaxEntries;
+      if ( NULL != pFdList ) {
+        CopyMem ( pFdListNew,
+                  pFdList,
+                  Index * sizeof ( *pFdList ));
+      }
+
+      //
+      //  Initialize the new entries in the FD list
+      //
+      for ( ; MaxEntriesNew > Index; Index++ ) {
+        pFdListNew [ Index ].fd = -1;
+        pFdListNew [ Index ].events = 0;
+        pFdListNew [ Index ].revents = 0;
+      }
+
+      //
+      //  Free the old FD list
+      //
+      if ( NULL != pFdList ) {
+        gBS->FreePool ( pFdList );
+      }
+
+      //
+      //  Switch to the new FD list
+      //
+      pWebServer->pFdList = pFdListNew;
+      pFdList = pWebServer->pFdList;
+
+      //
+      //  Duplicate the port list
+      //
+      Index = MaxEntries;
+      if ( NULL != pWebServer->ppPortList ) {
+        CopyMem ( ppPortListNew,
+                  pWebServer->ppPortList,
+                  Index * sizeof ( *ppPortListNew ));
+      }
+      
+      //
+      //  Initialize the new entries in the port list
+      //
+      for ( ; MaxEntriesNew > Index; Index++ ) {
+        ppPortListNew [ Index ] = NULL;
+      }
+      
+      //
+      //  Free the old port list
+      //
+      if ( NULL != pWebServer->ppPortList ) {
+        gBS->FreePool ( pWebServer->ppPortList );
+      }
+      
+      //
+      //  Switch to the new port list
+      //
+      pWebServer->ppPortList = ppPortListNew;
+      
+      //
+      //  Update the list size
+      //
+      pWebServer->MaxEntries = MaxEntriesNew;
+    }
+
+    //
+    //  Allocate a new port
+    //
+    LengthInBytes = sizeof ( *pPort );
+    Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+                                 LengthInBytes,
+                                 (VOID **)&pPort );
+    if ( EFI_ERROR ( Status )) {
+      DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+                "ERROR - Failed to allocate the port, Status: %r\r\n",
+                Status ));
+      break;
+    }
+
+    //
+    //  Initialize the port
+    //
+    pPort->RequestLength = 0;
+    pPort->TxBytes = 0;
+
+    //
+    //  Add the socket to the FD list
+    //
+    pFdList [ pWebServer->Entries ].fd = SocketFD;
+    pFdList [ pWebServer->Entries ].events = POLLRDNORM
+                                             | POLLHUP;
+    pFdList [ pWebServer->Entries ].revents = 0;
+
+    //
+    //  Add the port to the port list
+    //
+    pWebServer->ppPortList [ pWebServer->Entries ] = pPort;
+
+    //
+    //  Account for the new entry
+    //
+    pWebServer->Entries += 1;
+    DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,
+              "WebServer handling %d ports\r\n",
+              pWebServer->Entries ));
+
+    //
+    //  All done
+    //
+    break;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  Remove a port from the list of ports to be polled.
+
+  @param [in] pWebServer    The web server control structure address.
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+
+**/
+VOID
+PortRemove (
+  IN DT_WEB_SERVER * pWebServer,
+  IN int SocketFD
+  )
+{
+  nfds_t Entries;
+  nfds_t Index;
+  struct pollfd * pFdList;
+  WSDT_PORT ** ppPortList;
+
+  DBG_ENTER ( );
+
+  //
+  //  Attempt to remove the entry from the list
+  //
+  Entries = pWebServer->Entries;
+  pFdList = pWebServer->pFdList;
+  ppPortList = pWebServer->ppPortList;
+  for ( Index = 0; Entries > Index; Index++ ) {
+    //
+    //  Locate the specified socket file descriptor
+    //
+    if ( SocketFD == pFdList [ Index ].fd ) {
+      //
+      //  Determine if this is the listen port
+      //
+      if ( SocketFD == pWebServer->HttpListenPort ) {
+        pWebServer->HttpListenPort = -1;
+      }
+
+      //
+      //  Close the socket
+      //
+      close ( SocketFD );
+
+      //
+      //  Free the port structure
+      //
+      gBS->FreePool ( ppPortList [ Index ]);
+
+      //
+      //  Remove this port from the list by copying
+      //  the rest of the list down one entry
+      //
+      Entries -= 1;
+      for ( ; Entries > Index; Index++ ) {
+        pFdList [ Index ] = pFdList [ Index + 1 ];
+        ppPortList [ Index ] = ppPortList [ Index + 1 ];
+      }
+      pFdList [ Index ].fd = -1;
+      pFdList [ Index ].events = 0;
+      pFdList [ Index ].revents = 0;
+      ppPortList [ Index ] = NULL;
+
+      //
+      //  Update the number of entries in the list
+      //
+      pWebServer->Entries = Entries;
+      DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,
+                "WebServer handling %d ports\r\n",
+                pWebServer->Entries ));
+      break;
+    }
+  }
+
+  DBG_EXIT ( );
+}
+
+
+/**
+  Process the work for the sockets.
+
+  @param [in] pWebServer    The web server control structure address.
+
+  @param [in] SocketFD      The socket's file descriptor to add to the list.
+
+  @param [in] events        everts is a bitmask of the work to be done
+
+  @param [in] pPort         The address of a WSDT_PORT structure
+
+  @retval EFI_SUCCESS       The operation was successful
+  @retval EFI_DEVICE_ERROR  Error, close the port
+
+**/
+EFI_STATUS
+PortWork (
+  IN DT_WEB_SERVER * pWebServer,
+  IN int SocketFD,
+  IN INTN events,
+  IN WSDT_PORT * pPort
+  )
+{
+  BOOLEAN bDone;
+  size_t LengthInBytes;
+  int NewSocket;
+  EFI_STATUS OpStatus;
+  struct sockaddr RemoteAddress;
+  socklen_t RemoteAddressLength;
+  EFI_STATUS Status;
+
+  DEBUG (( DEBUG_PORT_WORK, "Entering PortWork\r\n" ));
+
+  //
+  //  Assume success
+  //
+  OpStatus = EFI_SUCCESS;
+
+  //
+  //  Handle input events
+  //
+  if ( 0 != ( events & POLLRDNORM )) {
+    //
+    //  Determine if this is a connection attempt
+    //
+    if ( SocketFD == pWebServer->HttpListenPort ) {
+      //
+      //  Handle connection attempts
+      //  Accepts arrive as read events
+      //
+      RemoteAddressLength = sizeof ( RemoteAddress );
+      NewSocket = accept ( SocketFD,
+                           &RemoteAddress,
+                           &RemoteAddressLength );
+      if ( -1 != NewSocket ) {
+        if ( 0 != NewSocket ) {
+          //
+          //  Add this port to the list monitored by the web server
+          //
+          Status = PortAdd ( pWebServer, NewSocket );
+          if ( EFI_ERROR ( Status )) {
+            DEBUG (( DEBUG_ERROR,
+                      "ERROR - Failed to add the port 0x%08x, Status: %r\r\n",
+                      NewSocket,
+                      Status ));
+
+            //
+            //  Done with the new socket
+            //
+            close ( NewSocket );
+          }
+        }
+        else {
+          DEBUG (( DEBUG_ERROR,
+                    "ERROR - Socket not available!\r\n" ));
+        }
+
+        //
+        //  Leave the listen port open
+        //
+      }
+      else {
+        //
+        //  Listen port error
+        //  Close the listen port by returning error status
+        //
+        OpStatus = EFI_DEVICE_ERROR;
+        DEBUG (( DEBUG_ERROR,
+                  "ERROR - Failed to accept new connection, errno: 0x%08x\r\n",
+                  errno ));
+      }
+    }
+    else {
+      //
+      //  Handle the data received event
+      //
+      if ( 0 == pPort->RequestLength ) {
+        //
+        //  Receive the page request
+        //
+        pPort->RequestLength = recv ( SocketFD,
+                                      &pPort->Request[0],
+                                      DIM ( pPort->Request ),
+                                      0 );
+        if ( -1 == pPort->RequestLength ) {
+          //
+          //  Receive error detected
+          //  Close the port
+          //
+          OpStatus = EFI_DEVICE_ERROR;
+        }
+        else {
+          DEBUG (( DEBUG_REQUEST,
+                    "0x%08x: Socket - Received %d bytes of HTTP request\r\n",
+                    SocketFD,
+                    pPort->RequestLength ));
+
+          //
+          //  Process the request
+          //
+          OpStatus = HttpRequest ( SocketFD, pPort, &bDone );
+          if ( bDone ) {
+            //
+            //  Notify the upper layer to close the socket
+            //
+            OpStatus = EFI_DEVICE_ERROR;
+          }
+        }
+      }
+      else
+      {
+        //
+        //  Receive the file data
+        //
+        LengthInBytes = recv ( SocketFD,
+                               &pPort->RxBuffer[0],
+                               DIM ( pPort->RxBuffer ),
+                               0 );
+        if ( -1 == LengthInBytes ) {
+          //
+          //  Receive error detected
+          //  Close the port
+          //
+          OpStatus = EFI_DEVICE_ERROR;
+        }
+        else {
+          DEBUG (( DEBUG_REQUEST,
+                    "0x%08x: Socket - Received %d bytes of file data\r\n",
+                    SocketFD,
+                    LengthInBytes ));
+
+          //
+          // TODO: Process the file data
+          //
+        }
+      }
+    }
+  }
+
+  //
+  //  Handle the close event
+  //
+  if ( 0 != ( events & POLLHUP )) {
+    //
+    //  Close the port
+    //
+    OpStatus = EFI_DEVICE_ERROR;
+  }
+
+  //
+  //  Return the operation status
+  //
+  DEBUG (( DEBUG_PORT_WORK,
+            "Exiting PortWork, Status: %r\r\n",
+            OpStatus ));
+  return OpStatus;
+}
+
+
+/**
+  Scan the list of sockets and process any pending work
+
+  @param [in] pWebServer    The web server control structure address.
+
+**/
+VOID
+SocketPoll (
+  IN DT_WEB_SERVER * pWebServer
+  )
+{
+  int FDCount;
+  struct pollfd * pPoll;
+  WSDT_PORT ** ppPort;
+  EFI_STATUS Status;
+
+  DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));
+
+  //
+  //  Determine if any ports are active
+  //
+  FDCount = poll ( pWebServer->pFdList,
+                   pWebServer->Entries,
+                   CLIENT_POLL_DELAY );
+  if ( -1 == FDCount ) {
+    DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL,
+              "ERROR - errno: %d\r\n",
+              errno ));
+  }
+
+  pPoll = pWebServer->pFdList;
+  ppPort = pWebServer->ppPortList;
+  while ( 0 < FDCount ) {
+    //
+    //  Walk the list of ports to determine what work needs to be done
+    //
+    if ( 0 != pPoll->revents ) {
+      //
+      //  Process this port
+      //
+      Status = PortWork ( pWebServer,
+                          pPoll->fd,
+                          pPoll->revents,
+                          *ppPort );
+      pPoll->revents = 0;
+
+      //
+      //  Close the port if necessary
+      //
+      if ( EFI_ERROR ( Status )) {
+        PortRemove ( pWebServer, pPoll->fd );
+        pPoll -= 1;
+        ppPort -= 1;
+      }
+
+      //
+      //  Account for this file descriptor
+      //
+      FDCount -= 1;
+    }
+
+    //
+    //  Set the next port
+    //
+    pPoll += 1;
+    ppPort += 1;
+  }
+
+  DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));
+}
+
+
+/**
+  Create the HTTP port for the web server
+
+  This routine polls the network layer to create the 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.
+
+  After the HTTP port is created, the socket layer will manage the
+  coming and going of the network connections until the last network
+  connection is broken.
+
+  @param [in] pWebServer  The web server control structure address.
+
+**/
+VOID
+WebServerTimer (
+  IN DT_WEB_SERVER * pWebServer
+  )
+{
+  UINT16 HttpPort;
+  struct sockaddr_in WebServerAddress;
+  int SocketStatus;
+  EFI_STATUS Status;
+
+  DEBUG (( DEBUG_SERVER_TIMER, "Entering WebServerTimer\r\n" ));
+
+  //
+  //  Open the HTTP port on the server
+  //
+  do {
+    do {
+      //
+      //  Complete the client operations
+      //
+      SocketPoll ( pWebServer );
+
+      //
+      //  Wait for a while
+      //
+      Status = gBS->CheckEvent ( pWebServer->TimerEvent );
+    } while ( EFI_SUCCESS != Status );
+
+    //
+    //  Attempt to create the socket for the web server
+    //
+    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 );
+
+      //
+      //  Bind the socket to the HTTP port
+      //
+      SocketStatus = bind ( pWebServer->HttpListenPort,
+                            (struct sockaddr *) &WebServerAddress,
+                            WebServerAddress.sin_len );
+      if ( -1 != SocketStatus ) {
+        //
+        //  Enable connections to the HTTP port
+        //
+        SocketStatus = listen ( pWebServer->HttpListenPort,
+                                SOMAXCONN );
+      }
+  
+      //
+      //  Release the socket if necessary
+      //
+      if ( -1 == SocketStatus ) {
+        close ( pWebServer->HttpListenPort );
+        pWebServer->HttpListenPort = -1;
+      }
+    }
+
+    //
+    //  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
+    //
+    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 ));
+    }
+  }
+
+  //
+  //  Return the operation status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
+
+
+/**
+  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.
+
+  @param [in] Argc  The number of arguments
+  @param [in] Argv  The argument value array
+
+  @retval  0        The application exited normally.
+  @retval  Other    An error occurred.
+**/
+int
+main (
+  IN int Argc,
+  IN char **Argv
+  )
+{
+  DT_WEB_SERVER * pWebServer;
+  EFI_STATUS Status;
+
+  //
+  //  Create a timer event to start HTTP port
+  //
+  pWebServer = &mWebServer;
+  Status = gBS->CreateEvent ( EVT_TIMER,
+                              TPL_WEB_SERVER,
+                              NULL,
+                              NULL,
+                              &pWebServer->TimerEvent );
+  if ( !EFI_ERROR ( Status )) {
+    Status = WebServerTimerStart ( pWebServer );
+    if ( !EFI_ERROR ( Status )) {
+      //
+      //  Run the web server forever
+      //
+      for ( ; ; ) {
+        //
+        //  Poll the network layer to create the 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.
+        //
+        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
+          //
+          do {
+            SocketPoll ( pWebServer );
+          } while ( -1 != pWebServer->HttpListenPort );
+
+          //
+          //  The HTTP port failed the accept and was closed
+          //
+        }
+
+        //
+        //  Close the HTTP port if necessary
+        //
+        if ( -1 != pWebServer->HttpListenPort ) {
+          close ( pWebServer->HttpListenPort );
+          pWebServer->HttpListenPort = -1;
+        }
+//
+// TODO: Remove the following test code
+//  Exit when the network connection is broken
+//
+break;
+      }
+
+      //
+      //  Done with the timer event
+      //
+      WebServerTimerStop ( pWebServer );
+      Status = gBS->CloseEvent ( pWebServer->TimerEvent );
+    }
+  }
+
+  //
+  //  Return the final status
+  //
+  DBG_EXIT_STATUS ( Status );
+  return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/WebServer.h b/AppPkg/Applications/Sockets/WebServer/WebServer.h
new file mode 100644 (file)
index 0000000..6078df0
--- /dev/null
@@ -0,0 +1,1105 @@
+/** @file\r
+  Definitions for the web server.\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
+#ifndef _WEB_SERVER_H_\r
+#define _WEB_SERVER_H_\r
+\r
+#include <errno.h>\r
+#include <Uefi.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.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
+\r
+#include <sys/EfiSysCall.h>\r
+#include <sys/poll.h>\r
+#include <sys/socket.h>\r
+\r
+#pragma warning ( disable : 4054 )\r
+#pragma warning ( disable : 4152 )\r
+\r
+//------------------------------------------------------------------------------\r
+//  Pages\r
+//------------------------------------------------------------------------------\r
+\r
+#define PAGE_ACPI_DSDT                  L"/DSDT"\r
+#define PAGE_ACPI_FADT                  L"/FADT"\r
+#define PAGE_ACPI_RSDP_10B              L"/RSDP1.0b"\r
+#define PAGE_ACPI_RSDP_30               L"/RSDP3.0"\r
+#define PAGE_ACPI_RSDT                  L"/RSDT"\r
+#define PAGE_BOOT_SERVICES_TABLE        L"/BootServicesTable"\r
+#define PAGE_CONFIGURATION_TABLE        L"/ConfigurationTable"\r
+#define PAGE_DXE_SERVICES_TABLE         L"/DxeServicesTable"\r
+#define PAGE_RUNTIME_SERVICES_TABLE     L"/RuntimeServicesTable"\r
+\r
+//------------------------------------------------------------------------------\r
+//  Signatures\r
+//------------------------------------------------------------------------------\r
+\r
+#define DSDT_SIGNATURE        0x54445344\r
+#define FADT_SIGNATURE        0x50434146\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
+#else   //  _MSC_VER\r
+#define DBG_ENTER()\r
+#define DBG_EXIT()\r
+#define DBG_EXIT_DEC(Status)\r
+#define DBG_EXIT_HEX(Status)\r
+#define DBG_EXIT_STATUS(Status)\r
+#define DBG_EXIT_TF(Status)\r
+#endif  //  _MSC_VER\r
+\r
+#define DIM(x)    ( sizeof ( x ) / sizeof ( x[0] ))   ///<  Compute the number of entries in an array\r
+\r
+//------------------------------------------------------------------------------\r
+//  Constants\r
+//------------------------------------------------------------------------------\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_HTTP_PORT         0x00010000  ///<  Display HTTP port related messages\r
+#define DEBUG_REQUEST           0x00008000  ///<  Display the HTTP request messages\r
+\r
+#define HTTP_PORT_POLL_DELAY  ( 2 * 1000 )  ///<  Delay in milliseconds for attempts to open the HTTP port\r
+#define CLIENT_POLL_DELAY     50            ///<  Delay in milliseconds between client polls\r
+\r
+#define TPL_WEB_SERVER        TPL_CALLBACK  ///<  TPL for routine synchronization\r
+\r
+/**\r
+  Verify new TPL value\r
+\r
+  This macro which is enabled when debug is enabled verifies that\r
+  the new TPL value is >= the current TPL value.\r
+**/\r
+#ifdef VERIFY_TPL\r
+#undef VERIFY_TPL\r
+#endif  //  VERIFY_TPL\r
+\r
+#if !defined(MDEPKG_NDEBUG)\r
+\r
+#define VERIFY_TPL(tpl)                           \\r
+{                                                 \\r
+  EFI_TPL PreviousTpl;                            \\r
+                                                  \\r
+  PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \\r
+  gBS->RestoreTPL ( PreviousTpl );                \\r
+  if ( PreviousTpl > tpl ) {                      \\r
+    DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl ));  \\r
+    ASSERT ( PreviousTpl <= tpl );                \\r
+  }                                               \\r
+}\r
+\r
+#else   //  MDEPKG_NDEBUG\r
+\r
+#define VERIFY_TPL(tpl)\r
+\r
+#endif  //  MDEPKG_NDEBUG\r
+\r
+#define WEB_SERVER_SIGNATURE        SIGNATURE_32('W','e','b','S') ///<  DT_WEB_SERVER memory signature\r
+\r
+#define SPACES_ADDRESS_TO_DATA      2\r
+#define BYTES_ON_A_LINE             16\r
+#define SPACES_BETWEEN_BYTES        1\r
+#define SPACES_DATA_TO_ASCII        2\r
+\r
+\r
+//------------------------------------------------------------------------------\r
+// Protocol Declarations\r
+//------------------------------------------------------------------------------\r
+\r
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;    ///<  Component name protocol declaration\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;  ///<  Component name 2 protocol declaration\r
+extern EFI_DRIVER_BINDING_PROTOCOL gDriverBinding;    ///<  Driver binding protocol declaration\r
+\r
+//------------------------------------------------------------------------------\r
+//  Data Types\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Port control structure\r
+**/\r
+typedef struct {\r
+  //\r
+  //  Buffer management\r
+  //\r
+  size_t    RequestLength;      ///<  Request length in bytes\r
+  size_t    TxBytes;            ///<  Bytes in the TX buffer\r
+  UINT8     Request [ 65536 ];  ///<  Page request\r
+  UINT8     RxBuffer [ 65536 ]; ///<  Receive buffer\r
+  UINT8     TxBuffer [ 65536 ]; ///<  Transmit buffer\r
+} WSDT_PORT;\r
+\r
+/**\r
+  Web server control structure\r
+**/\r
+typedef struct {\r
+  UINTN Signature;              ///<  Structure identification\r
+\r
+  //\r
+  //  Image attributes\r
+  //\r
+  EFI_HANDLE ImageHandle;       ///<  Image handle\r
+\r
+  //\r
+  //  HTTP port management\r
+  //\r
+  BOOLEAN   bTimerRunning;      ///<  Port creation timer status\r
+  EFI_EVENT TimerEvent;         ///<  Timer to open HTTP port\r
+  int       HttpListenPort;     ///<  File descriptor for the HTTP listen port\r
+\r
+  //\r
+  //  Client port management\r
+  //\r
+  nfds_t    MaxEntries;         ///<  Maximum entries in the PortList array\r
+  nfds_t    Entries;            ///<  The current number of entries in the PortList array\r
+  struct pollfd * pFdList;      ///<  List of socket file descriptors\r
+  WSDT_PORT ** ppPortList;      ///<  List of port management structures\r
+} DT_WEB_SERVER;\r
+\r
+//#define SERVER_FROM_SERVICE(a) CR(a, DT_WEB_SERVER, ServiceBinding, WEB_SERVER_SIGNATURE) ///< Locate DT_LAYER from service binding\r
+\r
+extern DT_WEB_SERVER mWebServer;\r
+\r
+/**\r
+  Process an HTTP request\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
+typedef\r
+EFI_STATUS\r
+(* PFN_RESPONSE) (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Data structure to delcare page support routines\r
+**/\r
+typedef struct {\r
+  UINT16 * pPageName;         ///<  Name of the page\r
+  PFN_RESPONSE pfnResponse;   ///<  Routine to generate the response\r
+  UINT16 * pDescription;      ///<  Description of the page\r
+} DT_PAGE;\r
+\r
+extern CONST DT_PAGE mPageList [];  ///<  List of pages\r
+extern CONST UINTN mPageCount;      ///<  Number of pages\r
+\r
+//------------------------------------------------------------------------------\r
+// Web Pages\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Respond with the ACPI DSDT table\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
+AcpiDsdtPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the ACPI FADT table\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
+AcpiFadtPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the ACPI RSDP 1.0b table\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
+AcpiRsdp10Page (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the ACPI RSDP 3.0 table\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
+AcpiRsdp30Page (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the ACPI RSDT table\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
+AcpiRsdtPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the boot services table\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
+BootServicesTablePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the configuration tables\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
+ConfigurationTablePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the DHCP options\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
+DhcpOptionsPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the DXE services table\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
+DxeServicesTablePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the firmware status\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
+FirmwarePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the handles in the system\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
+HandlePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the Hello World 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
+HelloPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the list of known pages\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
+IndexPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Page to reboot the system\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
+RebootPage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the runtime services table\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
+RuntimeSservicesTablePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Respond with the system table\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
+SystemTablePage (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN * pbDone\r
+  );\r
+\r
+//------------------------------------------------------------------------------\r
+// Support routines\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Display the EFI Table Header\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 [in] pHeader       Address of the EFI_TABLE_HEADER structure\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+EfiTableHeader (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN EFI_TABLE_HEADER * pHeader\r
+  );\r
+\r
+/**\r
+  Buffer the HTTP page header\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 [in] pTitle        A zero terminated Unicode title string\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpPageHeader (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR16 * pTitle\r
+  );\r
+\r
+/**\r
+  Buffer and send the HTTP page trailer\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
+HttpPageTrailer (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Process an HTTP request\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
+HttpRequest (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN BOOLEAN * pbDone\r
+  );\r
+\r
+/**\r
+  Buffer data for sending\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 [in] LengthInBytes Length of valid data in the buffer\r
+  @param [in] pBuffer       Buffer of data to send\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSend (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN size_t LengthInBytes,\r
+  IN CONST UINT8 * pBuffer\r
+  );\r
+\r
+/**\r
+  Send an ANSI string\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 [in] pString       A zero terminated Unicode string\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendAnsiString (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST char * pString\r
+  );\r
+\r
+/**\r
+  Buffer a single byte\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 [in] Data          The data byte to send\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendByte (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN UINT8 Data\r
+  );\r
+\r
+/**\r
+  Display a character\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 [in] Character     Character to display\r
+  @param [in] pReplacement  Replacement character string\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendCharacter (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CHAR8 Character,\r
+  IN CHAR8 * pReplacement\r
+  );\r
+\r
+/**\r
+  Send a buffer dump\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 [in] ByteCount     The number of bytes to display\r
+  @param [in] pData         Address of the byte array\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendDump (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN UINTN ByteCount,\r
+  IN CONST UINT8 * pData\r
+  );\r
+\r
+/**\r
+  Display a row containing a GUID value\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 [in] pGuid         Address of the GUID to display\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendGuid (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST EFI_GUID * pGuid\r
+  );\r
+\r
+/**\r
+  Output a hex 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] Bits        Number of bits to display\r
+  @param [in] Value       Value to display\r
+\r
+  @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendHexBits (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN INT32 Bits,\r
+  IN UINT64 Value\r
+  );\r
+\r
+/**\r
+  Output a hex 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
+\r
+  @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendHexValue (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN UINT64 Value\r
+  );\r
+\r
+/**\r
+  Output an IP address to the HTML page\r
+\r
+  @param [in] SocketFD    Socket file descriptor\r
+  @param [in] pPort       The WSDT_PORT structure address\r
+  @param [in] pAddress    Address of the socket address\r
+\r
+  @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendIpAddress (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN struct sockaddr_in * pAddress\r
+  );\r
+\r
+/**\r
+  Send a Unicode string\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 [in] pString       A zero terminated Unicode string\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendUnicodeString (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST UINT16 * pString\r
+  );\r
+\r
+/**\r
+  Output a 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
+\r
+  @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendValue (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN UINT64 Value\r
+  );\r
+\r
+/**\r
+  Display a row containing a decimal value\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 [in] pName         Address of a zero terminated name string\r
+  @param [in] Value         The value to display\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowDecimalValue (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR8 * pName,\r
+  IN UINT64 Value\r
+  );\r
+\r
+/**\r
+  Display a row containing a GUID value\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 [in] pName         Address of a zero terminated name string\r
+  @param [in] pGuid         Address of the GUID to display\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowGuid (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR8 * pName,\r
+  IN CONST EFI_GUID * pGuid\r
+  );\r
+\r
+/**\r
+  Display a row containing a hex value\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 [in] pName         Address of a zero terminated name string\r
+  @param [in] Value         The value to display\r
+  @param [in] pWebPage      Address of a zero terminated web page name\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowHexValue (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR8 * pName,\r
+  IN UINT64 Value,\r
+  IN CONST CHAR16 * pWebPage\r
+  );\r
+\r
+/**\r
+  Display a row containing a pointer\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 [in] pName         Address of a zero terminated name string\r
+  @param [in] pAddress      The address to display\r
+  @param [in] pWebPage      Address of a zero terminated web page name\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowPointer (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR8 * pName,\r
+  IN CONST VOID * pAddress,\r
+  IN CONST CHAR16 * pWebPage\r
+  );\r
+\r
+/**\r
+  Display a row containing a revision\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 [in] pName         Address of a zero terminated name string\r
+  @param [in] Revision      The revision to display\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowRevision (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR8 * pName,\r
+  IN UINT32 Revision\r
+  );\r
+\r
+/**\r
+  Display a row containing a unicode string\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 [in] pName         Address of a zero terminated name string\r
+  @param [in] pString       Address of a zero terminated unicode string\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowUnicodeString (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR8 * pName,\r
+  IN CONST CHAR16 * pString\r
+  );\r
+\r
+/**\r
+  Start the table 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 [in] pName         Address of a zero terminated name string\r
+  @param [in] pTable        Address of the table\r
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+TableHeader (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN CONST CHAR16 * pName,\r
+  IN CONST VOID * pTable\r
+  );\r
+\r
+/**\r
+  End the table 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
+TableTrailer (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  OUT BOOLEAN *pbDone\r
+  );\r
+\r
+/**\r
+  HTTP 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 HTTP 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
+\r
+  @param [in] pWebServer  The web server control structure address.\r
+\r
+**/\r
+VOID\r
+WebServerTimer (\r
+  IN DT_WEB_SERVER * pWebServer\r
+  );\r
+\r
+/**\r
+  Start the web server port creation timer\r
+\r
+  @param [in] pWebServer  The web 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
+\r
+**/\r
+EFI_STATUS\r
+WebServerTimerStart (\r
+  IN DT_WEB_SERVER * pWebServer\r
+  );\r
+\r
+/**\r
+  Stop the web server port creation timer\r
+\r
+  @param [in] pWebServer  The web server control structure address.\r
+\r
+  @retval EFI_SUCCESS   The HTTP port timer is stopped\r
+  @retval Other         Failed to stop the HTTP port timer\r
+\r
+**/\r
+EFI_STATUS\r
+WebServerTimerStop (\r
+  IN DT_WEB_SERVER * pWebServer\r
+  );\r
+\r
+//------------------------------------------------------------------------------\r
+// Driver Binding Protocol Support\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and\r
+  closing the DevicePath and PciIo protocols on Controller.\r
+\r
+  @param [in] pThis                Protocol instance pointer.\r
+  @param [in] Controller           Handle of device to stop driver on.\r
+  @param [in] NumberOfChildren     How many children need to be stopped.\r
+  @param [in] pChildHandleBuffer   Not used.\r
+\r
+  @retval EFI_SUCCESS          This driver is removed Controller.\r
+  @retval EFI_DEVICE_ERROR     The device could not be stopped due to a device error.\r
+  @retval other                This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL * pThis,\r
+  IN  EFI_HANDLE Controller,\r
+  IN  UINTN NumberOfChildren,\r
+  IN  EFI_HANDLE * pChildHandleBuffer\r
+  );\r
+\r
+//------------------------------------------------------------------------------\r
+// EFI Component Name Protocol Support\r
+//------------------------------------------------------------------------------\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language,\r
+  then EFI_UNSUPPORTED is returned.\r
+\r
+  @param [in] pThis             A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param [in] pLanguage         A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 3066 or ISO 639-2 language code format.\r
+  @param [out] ppDriverName     A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                driver specified by This in the language\r
+                                specified by Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,\r
+  IN  CHAR8 * pLanguage,\r
+  OUT CHAR16 ** ppDriverName\r
+  );\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified by\r
+  Language, then a pointer to the controller name is returned in ControllerName,\r
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently\r
+  managing the controller specified by ControllerHandle and ChildHandle,\r
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not\r
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
+\r
+  @param [in] pThis             A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
+                                EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param [in] ControllerHandle  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+  @param [in] ChildHandle       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter that\r
+                                may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus drivers\r
+                                that wish to retrieve the name of the bus\r
+                                controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+  @param [in] pLanguage         A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 3066 or ISO 639-2 language code format.\r
+  @param [out] ppControllerName A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in\r
+                                the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,\r
+  IN  EFI_HANDLE ControllerHandle,\r
+  IN OPTIONAL EFI_HANDLE ChildHandle,\r
+  IN  CHAR8 * pLanguage,\r
+  OUT CHAR16 ** ppControllerName\r
+  );\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+#endif  //  _WEB_SERVER_H_\r
diff --git a/AppPkg/Applications/Sockets/WebServer/WebServer.inf b/AppPkg/Applications/Sockets/WebServer/WebServer.inf
new file mode 100644 (file)
index 0000000..308e4bf
--- /dev/null
@@ -0,0 +1,97 @@
+#/** @file\r
+#  Web Server 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)  20011 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                      = WebServer\r
+  FILE_GUID                      = 99E87DCF-6162-40c5-9FA1-32111F5197F7\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
+  ACPI.c\r
+  BootServicesTable.c\r
+  ConfigurationTable.c\r
+  DhcpOptions.c\r
+  DxeServicesTable.c\r
+  Firmware.c\r
+  Handles.c\r
+  Hello.c\r
+  HTTP.c\r
+  Index.c\r
+  PageList.c\r
+  Reboot.c\r
+  RuntimeServicesTable.c\r
+  SystemTable.c\r
+  WebServer.c\r
+\r
+\r
+[Pcd]\r
+  gStdLibTokenSpaceGuid.WebServer_HttpPort\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  StdLib/StdLib.dec\r
+\r
+\r
+[LibraryClasses]\r
+  BaseMemoryLib\r
+  BsdSocketLib\r
+  DebugLib\r
+  DevShell\r
+#  EfiSocketLib\r
+  LibC\r
+  ShellLib\r
+  ShellCEntryLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\r
+  UefiRuntimeServicesTableLib\r
+  UseSocketDxe\r
+\r
+[Guids]\r
+  gEfiAcpi10TableGuid\r
+  gEfiAcpiTableGuid\r
+  gEfiDebugImageInfoTableGuid\r
+  gEfiDxeServicesTableGuid\r
+  gEfiHobListGuid\r
+  gEfiMemoryTypeInformationGuid\r
+  gLoadFixedAddressConfigurationTableGuid\r
+\r
+[Protocols]\r
+  gEfiDhcp4ServiceBindingProtocolGuid           # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDhcp4ProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\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