]> git.proxmox.com Git - mirror_edk2.git/blobdiff - AppPkg/Applications/Sockets/WebServer/HTTP.c
Fix @return Doxygen commands to be singular instead of plural.
[mirror_edk2.git] / AppPkg / Applications / Sockets / WebServer / HTTP.c
index a1716b2dbf0632747f6cea4e98933043f953142a..314705b68f9189ecf9b0e591c490d70a8a58cc2c 100644 (file)
-/*++
-  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;
-}
+/*++\r
+  This file contains an 'Intel UEFI Application' and is\r
+  licensed for Intel CPUs and chipsets under the terms of your\r
+  license agreement with Intel or your vendor.  This file may\r
+  be modified by the user, subject to additional terms of the\r
+  license agreement\r
+--*/\r
+/*++\r
+\r
+Copyright (c)  2011 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+--*/\r
+\r
+/** @file\r
+  HTTP processing for the web server.\r
+\r
+**/\r
+\r
+#include <WebServer.h>\r
+\r
+/**\r
+  Get a UTF-8 character from the buffer\r
+\r
+  @param [in] pData     The address of the buffer containing the character\r
+  @param [out] ppData   The address to receive the next character address\r
+\r
+  @return     The character value\r
+\r
+**/\r
+INTN\r
+HttpCharGet (\r
+  IN UINT8 * pData,\r
+  IN UINT8 ** ppData\r
+  )\r
+{\r
+  INTN Data;\r
+  INTN Character;\r
+  INTN Control;\r
+  INTN Mask;\r
+\r
+  //\r
+  //  Verify that there is some data left\r
+  //\r
+  if ( NULL == pData ) {\r
+    //\r
+    //  No data to return\r
+    //\r
+    pData = NULL;\r
+    Character = 0;\r
+  }\r
+  else {\r
+    //\r
+    //  Get the first portion of the character\r
+    //\r
+    Character = *pData++;\r
+    Control = Character;\r
+    Mask = 0xc0;\r
+\r
+    //\r
+    //  Append the rest of the character\r
+    //\r
+    if ( 0 != ( Control & 0x80 )) {\r
+      while ( 0 != ( Control & 0x40 )) {\r
+        Character &= Mask;\r
+        Mask <<= 5;\r
+        Control <<= 1;\r
+        Character <<= 6;\r
+        Data = *pData++ & 0x3f;\r
+        if ( 0x80 != ( Data & 0xc0 )) {\r
+          //\r
+          //  Invalid character\r
+          //\r
+          pData = NULL;\r
+          Character = 0;\r
+          break;\r
+        }\r
+        Character |= Data & 0x3f;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the next character location and the character\r
+  //\r
+  *ppData = pData;\r
+  return Character;\r
+}\r
+\r
+\r
+/**\r
+  Transmit a portion of the HTTP response\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
+\r
+  @retval EFI_SUCCESS       The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpFlush (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort\r
+  )\r
+{\r
+  INTN LengthInBytes;\r
+  UINT8 * pBuffer;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  pBuffer = &pPort->TxBuffer[0];\r
+  do {\r
+    //\r
+    //  Attempt to send the data\r
+    //\r
+    LengthInBytes = send ( SocketFD,\r
+                           pBuffer,\r
+                           pPort->TxBytes,\r
+                           0 );\r
+    if ( -1 != LengthInBytes ) {\r
+      //\r
+      //  Account for the data sent\r
+      //\r
+      pBuffer += LengthInBytes;\r
+      pPort->TxBytes -= LengthInBytes;\r
+    }\r
+    else {\r
+      //\r
+      //  Transmit error\r
+      //\r
+      Status = EFI_DEVICE_ERROR;\r
+      break;\r
+    }\r
+  } while ( 0 < pPort->TxBytes );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Convert the ANSI character to lower case\r
+\r
+  @param [in] Character The character to convert to lower case.\r
+\r
+  @return   The lower case character\r
+\r
+**/\r
+INTN\r
+HttpLowerCase (\r
+  IN INTN Character\r
+  )\r
+{\r
+  //\r
+  //  Determine if the character is upper case\r
+  //\r
+  if (( 'A' <= Character ) && ( 'Z' >= Character )) {\r
+    Character += 'a' - 'A';\r
+  }\r
+\r
+  //\r
+  //  Return the lower case value of the character\r
+  //\r
+  return Character;\r
+}\r
+\r
+\r
+/**\r
+  Match a Unicode string against a UTF-8 string\r
+\r
+  @param [in] pString     A zero terminated Unicode string\r
+  @param [in] pData       A zero terminated UTF-8 string\r
+  @param [in] bIgnoreCase TRUE if case is to be ignored\r
+\r
+  @return     The difference between the last two characters tested.\r
+              Returns -1 for error.\r
+\r
+**/\r
+INTN\r
+HttpMatch (\r
+  IN UINT16 * pString,\r
+  IN UINT8 * pData,\r
+  IN BOOLEAN bIgnoreCase\r
+  )\r
+{\r
+  INTN Character1;\r
+  INTN Character2;\r
+  INTN Difference;\r
+\r
+  do {\r
+    //\r
+    //  Get the character from the comparison string\r
+    //\r
+    Character1 = *pString++;\r
+\r
+    //\r
+    //  Convert the character to lower case\r
+    //\r
+    if ( bIgnoreCase ) {\r
+      Character1 = HttpLowerCase ( Character1 );\r
+    }\r
+\r
+    //\r
+    //  Get the character from the request\r
+    //\r
+    Character2 = HttpCharGet ( pData, &pData );\r
+    if ( NULL == pData ) {\r
+       //\r
+       // Error getting character\r
+       //\r
+       Difference = -1;\r
+       break;\r
+    }\r
+\r
+    //\r
+    //  Convert the character to lower case\r
+    //\r
+    if ( bIgnoreCase ) {\r
+      Character2 = HttpLowerCase ( Character2 );\r
+    }\r
+\r
+    //\r
+    //  Compare the characters\r
+    //\r
+    Difference = Character1 - Character2;\r
+    if ( 0 != Difference ) {\r
+      return Difference;\r
+    }\r
+  } while ( 0 != Character1 );\r
+\r
+  //\r
+  //  Return the difference\r
+  //\r
+  return Difference;\r
+}\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
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Build the page header\r
+  //\r
+  for ( ; ; ) {\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  "<!DOCTYPE "\r
+                                  "HTML "\r
+                                  "PUBLIC "\r
+                                  "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "\r
+                                  "\"http://www.w3.org/TR/html4/loose.dtd\">\r\n" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    Status = HttpSendAnsiString ( SocketFD, pPort, "<html lang=\"en-US\">\r\n" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    if ( NULL != pTitle ) {\r
+      Status = HttpSendAnsiString ( SocketFD, pPort, "  <head>\r\n" );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendAnsiString ( SocketFD, pPort, "    <title>" );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendAnsiString ( SocketFD, pPort, "</title>\r\n" );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+      Status = HttpSendAnsiString ( SocketFD, pPort, "  </head>\r\n" );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+    Status = HttpSendAnsiString ( SocketFD, pPort, "  <body>\r\n" );\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Respond with an error indicating that the page was not found\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
+HttpPageNotFound (\r
+  IN int SocketFD,\r
+  IN WSDT_PORT * pPort,\r
+  IN BOOLEAN * pbDone\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Send the page not found\r
+  //\r
+  for ( ; ; ) {\r
+    //\r
+    //  Send the page header\r
+    //\r
+    Status = HttpPageHeader ( SocketFD, pPort, L"404 Not found" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Send the page body\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  "ERROR <b>404</b><br />"\r
+                                  "Requested page is not available\r\n" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Send the page trailer\r
+    //\r
+    Status = HttpPageTrailer ( SocketFD, pPort, pbDone );\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\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
+  int RetVal;\r
+  EFI_STATUS Status;\r
+  socklen_t LengthInBytes;\r
+  struct sockaddr_in LocalAddress;\r
+  struct sockaddr_in RemoteAddress;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Build the page header\r
+  //\r
+  for ( ; ; ) {\r
+    LengthInBytes = sizeof ( LocalAddress );\r
+    RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );\r
+    if ( 0 == RetVal ) {\r
+      RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );\r
+      if ( 0 == RetVal ) {\r
+        //\r
+        //  Seperate the body from the trailer\r
+        //\r
+        Status = HttpSendAnsiString ( SocketFD, pPort, "  <hr>\r\n" );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Display the system addresses and the page transfer direction\r
+        //\r
+        Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+        Status = HttpSendAnsiString ( SocketFD, pPort, "  -->  " );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+        Status = HttpSendIpAddress ( SocketFD, pPort, &RemoteAddress );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+        Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Terminate the page\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD, pPort, "  </body>\r\n" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    Status = HttpSendAnsiString ( SocketFD, pPort, "  </html>\r\n" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Send the page trailer\r
+    //\r
+    Status = HttpFlush ( SocketFD, pPort );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Mark the page as complete\r
+    //\r
+    *pbDone = TRUE;\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Replace a space with a zero\r
+\r
+  @param [in] pData     The request buffer address\r
+  @param [in] pEnd      End of buffer address\r
+\r
+  @return     The next character location\r
+\r
+**/\r
+UINT8 *\r
+HttpReplaceSpace (\r
+  IN UINT8 * pData,\r
+  IN UINT8 * pEnd\r
+  )\r
+{\r
+  INTN Character;\r
+  UINT8 * pSpace;\r
+\r
+  pSpace = pData;\r
+  while ( pEnd > pData ) {\r
+    //\r
+    //  Get the character from the request\r
+    //\r
+    Character = HttpCharGet ( pData, &pData );\r
+    if ( ' ' == Character ) {\r
+      break;\r
+    }\r
+    pSpace = pData;\r
+  }\r
+\r
+  //\r
+  //  Replace the space character with zero\r
+  //\r
+  ZeroMem ( pSpace, pData - pSpace );\r
+\r
+  //\r
+  //  Return the next character location\r
+  //\r
+  return pData;\r
+}\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
+  OUT BOOLEAN * pbDone\r
+  )\r
+{\r
+  UINT8 * pData;\r
+  UINT8 * pEnd;\r
+  CONST DT_PAGE * pPage;\r
+  CONST DT_PAGE * pPageEnd;\r
+  UINT8 * pVerb;\r
+  UINT8 * pVersion;\r
+  UINT8 * pWebPage;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume the request is not finished\r
+  //\r
+  *pbDone = FALSE;\r
+  Status = EFI_SUCCESS;\r
+  for ( ; ; ) {\r
+\r
+    //\r
+    //  Attempt to parse the command\r
+    //\r
+    pData = &pPort->Request[0];\r
+    pEnd = &pData [ pPort->RequestLength ];\r
+    pVerb = pData;\r
+    pWebPage = HttpReplaceSpace ( pVerb, pEnd );\r
+    if ( pEnd <= pWebPage ) {\r
+      break;\r
+    }\r
+    pVersion = HttpReplaceSpace ( pWebPage, pEnd );\r
+    if ( pEnd <= pVersion ) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Validate the request\r
+    //\r
+    if ( 0 != HttpMatch ( L"GET", pVerb, TRUE )) {\r
+      //\r
+      //  Invalid request type\r
+      //\r
+      DEBUG (( DEBUG_REQUEST,\r
+                "HTTP: Invalid verb\r\n" ));\r
+      Status = EFI_NOT_FOUND;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Walk the page table\r
+    //\r
+    pPage = &mPageList[0];\r
+    pPageEnd = &pPage [ mPageCount ];\r
+    while ( pPageEnd > pPage ) {\r
+      //\r
+      //  Determine if the page was located\r
+      //\r
+      if ( 0 == HttpMatch ( pPage->pPageName, pWebPage, FALSE )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Set the next page\r
+      //\r
+      pPage += 1;\r
+    }\r
+    if ( pPageEnd <= pPage ) {\r
+      //\r
+      //  The page was not found\r
+      //\r
+      DEBUG (( DEBUG_REQUEST,\r
+                "HTTP: Page not found in page table\r\n" ));\r
+      Status = EFI_NOT_FOUND;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Respond with the page contents\r
+    //\r
+    Status = pPage->pfnResponse ( SocketFD, pPort, pbDone );\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return page not found if necessary\r
+  //\r
+  if ( EFI_NOT_FOUND == Status ) {\r
+    Status = HttpPageNotFound ( SocketFD, pPort, pbDone );\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\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
+  size_t DataBytes;\r
+  size_t MaxBytes;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+  do {\r
+    //\r
+    //  Determine how much data fits into the buffer\r
+    //\r
+    MaxBytes = sizeof ( pPort->TxBuffer );\r
+    DataBytes = MaxBytes - pPort->TxBytes;\r
+    if ( DataBytes > LengthInBytes )\r
+    {\r
+      DataBytes = LengthInBytes;\r
+    }\r
+\r
+    //\r
+    //  Copy the data into the buffer\r
+    //\r
+    CopyMem ( &pPort->TxBuffer [ pPort->TxBytes ],\r
+              pBuffer,\r
+              DataBytes );\r
+\r
+    //\r
+    //  Account for the data copied\r
+    //\r
+    pPort->TxBytes += DataBytes;\r
+    LengthInBytes -= DataBytes;\r
+\r
+    //\r
+    //  Transmit the buffer if it is full\r
+    //\r
+    if ( MaxBytes <= pPort->TxBytes ) {\r
+      Status = HttpFlush ( SocketFD, pPort );\r
+    }\r
+  } while (( EFI_SUCCESS == Status ) && ( 0 < LengthInBytes ));\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  CONST char * pData;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Walk the characters in he string\r
+  //\r
+  pData = pString;\r
+  while ( 0 != *pData ) {\r
+    pData += 1;\r
+  }\r
+\r
+  //\r
+  //  Send the string\r
+  //\r
+  Status = HttpSend ( SocketFD,\r
+                      pPort,\r
+                      pData - pString,\r
+                      (CONST UINT8 *)pString );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Send the data byte\r
+  //\r
+  Status = HttpSend ( SocketFD,\r
+                      pPort,\r
+                      1,\r
+                      &Data );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Determine if this is a printable character\r
+  //\r
+  if (( 0x20 <= Character ) && ( 0x7f > Character )) {\r
+    if ( '<' == Character ) {\r
+      //\r
+      //  Replace with HTML equivalent\r
+      //\r
+      Status = HttpSendAnsiString ( SocketFD,\r
+                                    pPort,\r
+                                    "&lt;" );\r
+    }\r
+    else if ( '>' == Character ) {\r
+      //\r
+      //  Replace with HTML equivalent\r
+      //\r
+      Status = HttpSendAnsiString ( SocketFD,\r
+                                    pPort,\r
+                                    "&gt;" );\r
+    }\r
+    else if ( '&' == Character ) {\r
+      //\r
+      //  Replace with HTML equivalent\r
+      //\r
+      Status = HttpSendAnsiString ( SocketFD,\r
+                                    pPort,\r
+                                    "&amp;" );\r
+    }\r
+    else if ( '\"' == Character ) {\r
+      //\r
+      //  Replace with HTML equivalent\r
+      //\r
+      Status = HttpSendAnsiString ( SocketFD,\r
+                                    pPort,\r
+                                    "&quot;" );\r
+    }\r
+    else {\r
+      //\r
+      //  Display the character\r
+      //\r
+      Status = HttpSendByte ( SocketFD,\r
+                              pPort,\r
+                              Character );\r
+    }\r
+  }\r
+  else {\r
+    //\r
+    //  Not a displayable character\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  pReplacement );\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  INTN BytesToDisplay;\r
+  UINT8 Character;\r
+  INTN Index;\r
+  INTN InitialSpaces;\r
+  CONST UINT8 * pDataEnd;\r
+  CONST UINT8 * pEnd;\r
+  CONST UINT8 * pTemp;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Use for/break instead of goto\r
+  //\r
+  for ( ; ; ) {\r
+    //\r
+    //  Start the field value\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  "<code>" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Walk the bytes to be displayed\r
+    //\r
+    pEnd = &pData [ ByteCount ];\r
+    while ( pEnd > pData ) {\r
+      //\r
+      //  Display the address\r
+      //\r
+      Status = HttpSendHexBits ( SocketFD,\r
+                                 pPort,\r
+                                 sizeof ( pData ) * 8,\r
+                                 (UINT64)pData );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Separate the address and data\r
+      //\r
+      Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Position the starting data correctly\r
+      //\r
+      InitialSpaces = (UINTN)pData;\r
+      InitialSpaces &= BYTES_ON_A_LINE - 1;\r
+      for ( Index = SPACES_ADDRESS_TO_DATA\r
+                  + (( 2 + SPACES_BETWEEN_BYTES )\r
+                        * InitialSpaces );\r
+            0 < Index; Index-- ) {\r
+        Status = HttpSendAnsiString ( SocketFD,\r
+                                      pPort,\r
+                                      "&nbsp;" );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+      }\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Display the data\r
+      //\r
+      BytesToDisplay = pEnd - pData;\r
+      if (( BYTES_ON_A_LINE - InitialSpaces ) < BytesToDisplay ) {\r
+        BytesToDisplay = BYTES_ON_A_LINE - InitialSpaces;\r
+      }\r
+      pDataEnd = &pData [ BytesToDisplay ];\r
+      pTemp = pData;\r
+      while ( pDataEnd > pTemp ) {\r
+        Status = HttpSendHexBits ( SocketFD,\r
+                                   pPort,\r
+                                   8,\r
+                                   *pTemp++ );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+\r
+        //\r
+        //  Separate the data bytes\r
+        //\r
+        for ( Index = SPACES_BETWEEN_BYTES; 0 < Index; Index-- ) {\r
+          Status = HttpSendAnsiString ( SocketFD,\r
+                                        pPort,\r
+                                        "&nbsp;" );\r
+          if ( EFI_ERROR ( Status )) {\r
+            break;\r
+          }\r
+        }\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+      }\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Separate the data from the ASCII display\r
+      //\r
+      for ( Index = (( 2 + SPACES_BETWEEN_BYTES )\r
+                       * ( BYTES_ON_A_LINE - BytesToDisplay - InitialSpaces ))\r
+                  - SPACES_BETWEEN_BYTES\r
+                  + SPACES_DATA_TO_ASCII\r
+                  + InitialSpaces;\r
+            0 < Index; Index-- ) {\r
+        Status = HttpSendAnsiString ( SocketFD,\r
+                                      pPort,\r
+                                      "&nbsp;" );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+      }\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Display the ASCII data\r
+      //\r
+      while ( pDataEnd > pData ) {\r
+        Character = *pData++;\r
+        Status = HttpSendCharacter ( SocketFD,\r
+                                     pPort,\r
+                                     Character,\r
+                                     "." );\r
+        if ( EFI_ERROR ( Status )) {\r
+          break;\r
+        }\r
+      }\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Terminate the line\r
+      //\r
+      Status = HttpSendAnsiString ( SocketFD,\r
+                                    pPort,\r
+                                    "<br/>\r\n" );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Terminate the field value and row\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  "</code>\r\n" );\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  UINT32 Index;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Use for/break instead of goto\r
+  //\r
+  for ( ; ; ) {\r
+    //\r
+    //  Display the GUID in a form found in the code\r
+    //\r
+    //  E.g. 0xca16005f, 0x11ec, 0x4bdc, { 0x99, 0x97, 0x27, 0x2c, 0xa9, 0xba, 0x15, 0xe5 }\r
+    //\r
+\r
+    //\r
+    //  Display the first 32 bits\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  "0x" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    Status = HttpSendHexBits ( SocketFD,\r
+                               pPort,\r
+                               32,\r
+                               pGuid->Data1 );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Display the second 16 bits\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  ", 0x" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    Status = HttpSendHexBits ( SocketFD,\r
+                               pPort,\r
+                               16,\r
+                               pGuid->Data2 );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Display the thrid 16 bits\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  ", 0x" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    Status = HttpSendHexBits ( SocketFD,\r
+                               pPort,\r
+                               16,\r
+                               pGuid->Data3 );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Place the last 64 bits in braces\r
+    //\r
+    Status = HttpSendAnsiString ( SocketFD,\r
+                                  pPort,\r
+                                  ", { 0x" );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+    for ( Index = 0; 7 >= Index; Index++ ) {\r
+      //\r
+      //  Display the next 8 bits\r
+      //\r
+      Status = HttpSendHexBits ( SocketFD,\r
+                                 pPort,\r
+                                 8,\r
+                                 pGuid->Data4 [ Index ]);\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Separate the bytes\r
+      //\r
+      Status = HttpSendAnsiString ( SocketFD,\r
+                                    pPort,\r
+                                    ( 7 != Index ) ? ", 0x" : " }" );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\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
+  UINT32 Digit;\r
+  INT32 Shift;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Walk the list of divisors\r
+  //\r
+  Shift = (( Bits + 3 ) & ( ~3 )) - 4;\r
+  while ( 0 <= Shift ) {\r
+    //\r
+    //  Determine the next digit\r
+    //\r
+    Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
+    if ( 10 <= Digit ) {\r
+      Digit += 'A' - '0' - 10;\r
+    }\r
+\r
+    //\r
+    //  Display the digit\r
+    //\r
+    Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Set the next shift\r
+    //\r
+    Shift -= 4;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  BOOLEAN bDisplayZeros;\r
+  UINT32 Digit;\r
+  INT32 Shift;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Walk the list of divisors\r
+  //\r
+  bDisplayZeros = FALSE;\r
+  Shift = 60;\r
+  do {\r
+    //\r
+    //  Determine the next digit\r
+    //\r
+    Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
+    if ( 10 <= Digit ) {\r
+      Digit += 'A' - '0' - 10;\r
+    }\r
+\r
+    //\r
+    //  Suppress leading zeros\r
+    //\r
+    if (( 0 != Digit ) || bDisplayZeros || ( 0 == Shift )) {\r
+      bDisplayZeros = TRUE;\r
+\r
+      //\r
+      //  Display the digit\r
+      //\r
+      Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Set the next shift\r
+    //\r
+    Shift -= 4;\r
+  } while ( 0 <= Shift );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Output an IP address to the HTML page\r
+\r
+  @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
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Output the IPv4 address\r
+  //\r
+  Status = HttpSendValue ( SocketFD, pPort, (UINT8)pAddress->sin_addr.s_addr );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+    if ( !EFI_ERROR ( Status )) {\r
+      Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 8 ));\r
+      if ( !EFI_ERROR ( Status )) {\r
+        Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+        if ( !EFI_ERROR ( Status )) {\r
+          Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 16 ));\r
+          if ( !EFI_ERROR ( Status )) {\r
+            Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+            if ( !EFI_ERROR ( Status )) {\r
+              Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 24 ));\r
+              if ( !EFI_ERROR ( Status )) {\r
+                //\r
+                //  Output the port number\r
+                //\r
+                Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+                if ( !EFI_ERROR ( Status )) {\r
+                  Status = HttpSendValue ( SocketFD, pPort, htons ( pAddress->sin_port ));\r
+                }\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  UINT8 Data;\r
+  UINT16 Character;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Walk the characters in he string\r
+  //\r
+  while ( 0 != ( Character = *pString++ )) {\r
+    //\r
+    //  Convert the character to UTF-8\r
+    //\r
+    if ( 0 != ( Character & 0xf800 )) {\r
+      //\r
+      //  Send the upper 4 bits\r
+      //\r
+      Data = (UINT8)(( Character >> 12 ) & 0xf );\r
+      Data |= 0xe0;\r
+      Status = HttpSendByte ( SocketFD,\r
+                              pPort,\r
+                              Data );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Send the next 6 bits\r
+      //\r
+      Data = (UINT8)(( Character >> 6 ) & 0x3f );\r
+      Data |= 0x80;\r
+      Status = HttpSendByte ( SocketFD,\r
+                              pPort,\r
+                              Data );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Send the last 6 bits\r
+      //\r
+      Data = (UINT8)( Character & 0x3f );\r
+      Data |= 0x80;\r
+    }\r
+    else if ( 0 != ( Character & 0x0780 )) {\r
+      //\r
+      //  Send the upper 5 bits\r
+      //\r
+      Data = (UINT8)(( Character >> 6 ) & 0x1f );\r
+      Data |= 0xc0;\r
+      Status = HttpSendByte ( SocketFD,\r
+                              pPort,\r
+                              Data );\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Send the last 6 bits\r
+      //\r
+      Data = (UINT8)( Character & 0x3f );\r
+      Data |= 0x80;\r
+    }\r
+    else {\r
+      Data = (UINT8)( Character & 0x7f );\r
+    }\r
+\r
+    //\r
+    //  Send the last data byte\r
+    //\r
+    Status = HttpSendByte ( SocketFD,\r
+                            pPort,\r
+                            Data );\r
+    if ( EFI_ERROR ( Status )) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\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
+  BOOLEAN bDisplayZeros;\r
+  UINT64 Digit;\r
+  CONST UINT64 * pEnd;\r
+  CONST UINT64 * pDivisor;\r
+  CONST UINT64 pDivisors [ ] = {\r
+     10000000000000000000L,\r
+      1000000000000000000L,\r
+       100000000000000000L,\r
+        10000000000000000L,\r
+         1000000000000000L,\r
+          100000000000000L,\r
+           10000000000000L,\r
+            1000000000000L,\r
+             100000000000L,\r
+              10000000000L,\r
+               1000000000L,\r
+                100000000L,\r
+                 10000000L,\r
+                  1000000L,\r
+                   100000L,\r
+                    10000L,\r
+                     1000L,\r
+                      100L,\r
+                       10L\r
+  };\r
+  EFI_STATUS Status;\r
+  UINT64 Temp;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  //  Walk the list of divisors\r
+  //\r
+  bDisplayZeros = FALSE;\r
+  pDivisor = &pDivisors[0];\r
+  pEnd = &pDivisor [ sizeof ( pDivisors ) / sizeof ( pDivisors [0])];\r
+  while ( pEnd > pDivisor ) {\r
+    //\r
+    //  Determine the next digit\r
+    //\r
+    Digit = Value / *pDivisor;\r
+\r
+    //\r
+    //  Suppress leading zeros\r
+    //\r
+    if (( 0 != Digit ) || bDisplayZeros ) {\r
+      bDisplayZeros = TRUE;\r
+\r
+      //\r
+      //  Display the digit\r
+      //\r
+      Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
+      if ( EFI_ERROR ( Status )) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      //  Determine the remainder\r
+      //\r
+      Temp = *pDivisor * Digit;\r
+      Value -= Temp;\r
+    }\r
+\r
+    //\r
+    //  Set the next divisor\r
+    //\r
+    pDivisor += 1;\r
+  }\r
+\r
+  //\r
+  //  Display the final digit\r
+  //\r
+  if ( !EFI_ERROR ( Status )) {\r
+    Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Value ));\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return Status;\r
+}\r