summaryrefslogtreecommitdiffstats
path: root/AppPkg/Applications/Sockets/WebServer/HTTP.c
diff options
context:
space:
mode:
Diffstat (limited to 'AppPkg/Applications/Sockets/WebServer/HTTP.c')
-rw-r--r--AppPkg/Applications/Sockets/WebServer/HTTP.c3140
1 files changed, 1570 insertions, 1570 deletions
diff --git a/AppPkg/Applications/Sockets/WebServer/HTTP.c b/AppPkg/Applications/Sockets/WebServer/HTTP.c
index a1716b2dbf..314705b68f 100644
--- a/AppPkg/Applications/Sockets/WebServer/HTTP.c
+++ b/AppPkg/Applications/Sockets/WebServer/HTTP.c
@@ -1,1570 +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;
-}
+/*++
+ 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
+
+ @return 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.
+
+ @return 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
+
+ @return 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
+
+ @return 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;
+}