+++ /dev/null
-/**\r
- @file\r
- HTTP processing for the web server.\r
-\r
- Copyright (c) 2011-2012, Intel Corporation. All rights reserved.\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <WebServer.h>\r
-\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_in6 LocalAddress;\r
- struct sockaddr_in6 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
- LengthInBytes = sizeof ( LocalAddress );\r
- RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );\r
- if ( 0 == RetVal ) {\r
- //\r
- // Seperate the body from the trailer\r
- //\r
- Status = HttpSendAnsiString ( SocketFD, pPort, " <hr>\r\n<code>" );\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, "</code>\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
- 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
- "<" );\r
- }\r
- else if ( '>' == Character ) {\r
- //\r
- // Replace with HTML equivalent\r
- //\r
- Status = HttpSendAnsiString ( SocketFD,\r
- pPort,\r
- ">" );\r
- }\r
- else if ( '&' == Character ) {\r
- //\r
- // Replace with HTML equivalent\r
- //\r
- Status = HttpSendAnsiString ( SocketFD,\r
- pPort,\r
- "&" );\r
- }\r
- else if ( '\"' == Character ) {\r
- //\r
- // Replace with HTML equivalent\r
- //\r
- Status = HttpSendAnsiString ( SocketFD,\r
- pPort,\r
- """ );\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)(UINTN)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
- " " );\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
- " " );\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
- " " );\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 IP6 address value to the HTML page\r
-\r
- @param [in] SocketFD Socket file descriptor\r
- @param [in] pPort The WSDT_PORT structure address\r
- @param [in] Value Value to display\r
- @param [in] bFirstValue TRUE if first value\r
- @param [in] bLastValue TRUE if last value\r
- @param [in] bZeroSuppression TRUE while zeros are being suppressed\r
- @param [in] pbZeroSuppression Address to receive TRUE when zero suppression\r
- has started, use NULL if next colon value not\r
- needed.\r
-\r
- @retval EFI_SUCCESS Successfully displayed the address\r
-**/\r
-EFI_STATUS\r
-HttpSendIp6Value (\r
- IN int SocketFD,\r
- IN WSDT_PORT * pPort,\r
- IN UINT16 Value,\r
- IN BOOLEAN bFirstValue,\r
- IN BOOLEAN bLastValue,\r
- IN BOOLEAN bZeroSuppression,\r
- IN BOOLEAN * pbZeroSuppression\r
- )\r
-{\r
- BOOLEAN bZeroSuppressionStarting;\r
- UINT32 Digit;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Use break instead of goto\r
- //\r
- bZeroSuppressionStarting = FALSE;\r
- Status = EFI_SUCCESS;\r
- for ( ; ; ) {\r
- //\r
- // Display the leading colon if necessary\r
- //\r
- if ( bZeroSuppression && ( bLastValue || ( 0 != Value ))) {\r
- Status = HttpSendByte ( SocketFD, pPort, ':' );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Skip over a series of zero values\r
- //\r
- bZeroSuppressionStarting = (BOOLEAN)( 0 == Value );\r
- if ( !bZeroSuppressionStarting ) {\r
- //\r
- // Display the value\r
- //\r
- Digit = ( Value >> 4 ) & 0xf;\r
- Status = HttpSendHexValue ( SocketFD,\r
- pPort,\r
- Digit );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Digit = Value & 0xf;\r
- Status = HttpSendHexValue ( SocketFD,\r
- pPort,\r
- Digit );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Digit = ( Value >> 12 ) & 0xf;\r
- Status = HttpSendHexValue ( SocketFD,\r
- pPort,\r
- Digit );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Digit = ( Value >> 8 ) & 0xf;\r
- Status = HttpSendHexValue ( SocketFD,\r
- pPort,\r
- Digit );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Display the trailing colon if necessary\r
- //\r
- if (( !bLastValue ) && ( bFirstValue || ( 0 != Value ))) {\r
- Status = HttpSendByte ( SocketFD, pPort, ':' );\r
- }\r
- break;\r
- }\r
-\r
- //\r
- // Return the next colon display\r
- if ( NULL != pbZeroSuppression ) {\r
- *pbZeroSuppression = bZeroSuppressionStarting;\r
- }\r
-\r
- //\r
- // Return the operation status\r
- //\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Output an IP address to the HTML page\r
-\r
- @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_in6 * pAddress\r
- )\r
-{\r
- BOOLEAN bZeroSuppression;\r
- UINT32 Index;\r
- struct sockaddr_in * pIpv4;\r
- struct sockaddr_in6 * pIpv6;\r
- UINT16 PortNumber;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Use break instead of goto\r
- //\r
- for ( ; ; ) {\r
- //\r
- // Determine the type of address\r
- //\r
- if ( AF_INET6 == pAddress->sin6_family ) {\r
- pIpv6 = pAddress;\r
-\r
- //\r
- // Display the address in RFC2732 format\r
- //\r
- bZeroSuppression = FALSE;\r
- Status = HttpSendByte ( SocketFD, pPort, '[' );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- for ( Index = 0; 8 > Index; Index++ ) {\r
- Status = HttpSendIp6Value ( SocketFD,\r
- pPort,\r
- pIpv6->sin6_addr.__u6_addr.__u6_addr16[ Index ],\r
- (BOOLEAN)( 0 == Index ),\r
- (BOOLEAN)( 7 == Index ),\r
- bZeroSuppression,\r
- &bZeroSuppression );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- }\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
-\r
- //\r
- // Separate the port number\r
- //\r
- Status = HttpSendByte ( SocketFD, pPort, ']' );\r
-\r
- //\r
- // Get the port number\r
- //\r
- PortNumber = pIpv6->sin6_port;\r
- }\r
- else {\r
- //\r
- // Output the IPv4 address\r
- //\r
- pIpv4 = (struct sockaddr_in *)pAddress;\r
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)pIpv4->sin_addr.s_addr );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendByte ( SocketFD, pPort, '.' );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 8 ));\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendByte ( SocketFD, pPort, '.' );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 16 ));\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendByte ( SocketFD, pPort, '.' );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pIpv4->sin_addr.s_addr >> 24 ));\r
-\r
- //\r
- // Get the port number\r
- //\r
- PortNumber = pIpv4->sin_port;\r
- }\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
-\r
- //\r
- // Display the port number\r
- //\r
- Status = HttpSendByte ( SocketFD, pPort, ':' );\r
- if ( EFI_ERROR ( Status )) {\r
- break;\r
- }\r
- Status = HttpSendValue ( SocketFD, pPort, htons ( PortNumber ));\r
- break;\r
- }\r
-\r
- //\r
- // 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
- 10000000000000000000ULL,\r
- 1000000000000000000ULL,\r
- 100000000000000000ULL,\r
- 10000000000000000ULL,\r
- 1000000000000000ULL,\r
- 100000000000000ULL,\r
- 10000000000000ULL,\r
- 1000000000000ULL,\r
- 100000000000ULL,\r
- 10000000000ULL,\r
- 1000000000ULL,\r
- 100000000ULL,\r
- 10000000ULL,\r
- 1000000ULL,\r
- 100000ULL,\r
- 10000ULL,\r
- 1000ULL,\r
- 100ULL,\r
- 10ULL\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