diff options
author | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-08-05 23:57:34 +0000 |
---|---|---|
committer | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-08-05 23:57:34 +0000 |
commit | 7dc1329100c370992cdd430359512443bd1ee9f2 (patch) | |
tree | 045e04a1051626910da63fba85cf208a5a517734 /AppPkg | |
parent | 59d13433e7cbc810a6268d38141b0d1db353fa6e (diff) | |
download | edk2-platforms-7dc1329100c370992cdd430359512443bd1ee9f2.tar.xz |
Fix @return Doxygen commands to be singular instead of plural.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12094 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'AppPkg')
-rw-r--r-- | AppPkg/Applications/Sockets/DataSource/DataSource.c | 8 | ||||
-rw-r--r-- | AppPkg/Applications/Sockets/TftpServer/TftpServer.c | 3054 | ||||
-rw-r--r-- | AppPkg/Applications/Sockets/WebServer/ACPI.c | 3836 | ||||
-rw-r--r-- | AppPkg/Applications/Sockets/WebServer/HTTP.c | 3140 |
4 files changed, 5019 insertions, 5019 deletions
diff --git a/AppPkg/Applications/Sockets/DataSource/DataSource.c b/AppPkg/Applications/Sockets/DataSource/DataSource.c index d8f7f05d5c..9add3f24e7 100644 --- a/AppPkg/Applications/Sockets/DataSource/DataSource.c +++ b/AppPkg/Applications/Sockets/DataSource/DataSource.c @@ -131,7 +131,7 @@ ControlCCheck ( @param [in] pDigit The address of the next digit
@param [out] pValue The address to receive the value
- @returns Returns the address of the separator
+ @return Returns the address of the separator
**/
CHAR8 *
@@ -775,7 +775,7 @@ Tcp4Locate ( //
if ( HandleCount <= Tcp4Index ) {
Tcp4Index = 0;
-
+
//
// Wait for the next timer tick
//
@@ -797,7 +797,7 @@ Tcp4Locate ( htons ( RemoteHostAddress.sin_port ));
bTcp4Connecting = FALSE;
}
-
+
//
// Open the network controller's service protocol
//
@@ -1110,7 +1110,7 @@ Tcp4Open ( Status = pTcp4Protocol->Configure ( pTcp4Protocol,
&Tcp4ConfigData );
if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR,
+ DEBUG (( DEBUG_ERROR,
"ERROR - Failed to configure TCP port, Status: %r\r\n",
Status ));
break;
diff --git a/AppPkg/Applications/Sockets/TftpServer/TftpServer.c b/AppPkg/Applications/Sockets/TftpServer/TftpServer.c index a1e19c26f9..9b522d1b55 100644 --- a/AppPkg/Applications/Sockets/TftpServer/TftpServer.c +++ b/AppPkg/Applications/Sockets/TftpServer/TftpServer.c @@ -1,1527 +1,1527 @@ -/*++ - This file contains an 'Intel UEFI Application' and is - licensed for Intel CPUs and chipsets under the terms of your - license agreement with Intel or your vendor. This file may - be modified by the user, subject to additional terms of the - license agreement ---*/ -/*++ - -Copyright (c) 2011 Intel Corporation. All rights reserved -This software and associated documentation (if any) is furnished -under a license and may only be used or copied in accordance -with the terms of the license. Except as permitted by such -license, no part of this software or documentation may be -reproduced, stored in a retrieval system, or transmitted in any -form or by any means without the express written consent of -Intel Corporation. - ---*/ - -/** @file - This is a simple TFTP server application - -**/ - -#include <TftpServer.h> - -TSDT_TFTP_SERVER mTftpServer; ///< TFTP server's control structure - - -/** - Add a connection context to the list of connection contexts. - - @param [in] pTftpServer The TFTP server control structure address. - - @retval Context structure address, NULL if allocation fails - -**/ -TSDT_CONNECTION_CONTEXT * -ContextAdd ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - size_t LengthInBytes; - TSDT_CONNECTION_CONTEXT * pContext; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Allocate a new context - // - LengthInBytes = sizeof ( *pContext ); - Status = gBS->AllocatePool ( EfiRuntimeServicesData, - LengthInBytes, - (VOID **)&pContext ); - if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DEBUG_POOL, - "ERROR - Failed to allocate the context, Status: %r\r\n", - Status )); - pContext = NULL; - break; - } - - // - // Initialize the context - // - ZeroMem ( pContext, LengthInBytes ); - CopyMem ( &pContext->RemoteAddress, - &pTftpServer->RemoteAddress, - sizeof ( pContext->RemoteAddress )); - pContext->BlockSize = TFTP_MAX_BLOCK_SIZE; - pContext->pBuffer = &pContext->FileData[0]; - pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )]; - pContext->MaxTransferSize = 0; - pContext->MaxTransferSize -= 1; - - // - // Display the new context - // - DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO, - "0x%08x: Context for %d.%d.%d.%d:%d\r\n", - pContext, - (UINT8)pContext->RemoteAddress.sin_addr.s_addr, - (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ), - (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ), - (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ), - htons ( pContext->RemoteAddress.sin_port ))); - - // - // Add the context to the context list - // - pContext->pNext = pTftpServer->pContextList; - pTftpServer->pContextList = pContext; - - // - // All done - // - break; - } - - // - // Return the connection context - // - DBG_EXIT_STATUS ( pContext ); - return pContext; -} - - -/** - Locate a remote connection context. - - @param [in] pTftpServer The TFTP server control structure address. - - @param [in] pIpAddress The start of the remote IP address in network order - - @param [in] Port The remote port number - - @retval Context structure address, NULL if not found - -**/ -TSDT_CONNECTION_CONTEXT * -ContextFind ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - TSDT_CONNECTION_CONTEXT * pContext; - - DBG_ENTER ( ); - - // - // Walk the list of connection contexts - // - pContext = pTftpServer->pContextList; - while ( NULL != pContext ) { - // - // Attempt to locate the remote network connection - // - if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr ) - && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) { - // - // The connection was found - // - DEBUG (( DEBUG_TFTP_REQUEST, - "0x%08x: pContext found\r\n", - pContext )); - break; - } - - // - // Set the next context - // - pContext = pContext->pNext; - } - - // - // Return the connection context structure address - // - DBG_EXIT_HEX ( pContext ); - return pContext; -} - - -/** - Remove a context from the list. - - @param [in] pTftpServer The TFTP server control structure address. - - @param [in] pContext The context structure address. - -**/ -VOID -ContextRemove ( - IN TSDT_TFTP_SERVER * pTftpServer, - IN TSDT_CONNECTION_CONTEXT * pContext - ) -{ - TSDT_CONNECTION_CONTEXT * pNextContext; - TSDT_CONNECTION_CONTEXT * pPreviousContext; - - DBG_ENTER ( ); - - // - // Attempt to locate the context in the list - // - pPreviousContext = NULL; - pNextContext = pTftpServer->pContextList; - while ( NULL != pNextContext ) { - // - // Determine if the context was found - // - if ( pNextContext == pContext ) { - // - // Remove the context from the list - // - if ( NULL == pPreviousContext ) { - pTftpServer->pContextList = pContext->pNext; - } - else { - pPreviousContext->pNext = pContext->pNext; - } - break; - } - - // - // Set the next context - // - pPreviousContext = pNextContext; - pNextContext = pNextContext->pNext; - } - - // - // Determine if the context was found - // - if ( NULL != pContext ) { - // - // Return the resources - // - gBS->FreePool ( pContext ); - } - - DBG_EXIT ( ); -} - - -/** - Process the work for the sockets. - - @param [in] pTftpServer The TFTP server control structure address. - -**/ -VOID -PortWork ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - TSDT_CONNECTION_CONTEXT * pContext; - socklen_t RemoteAddressLength; - - DBG_ENTER ( ); - - // - // Handle input events - // - if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) { - // - // Receive the message from the remote system - // - RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress ); - pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd, - &pTftpServer->RxBuffer[0], - sizeof ( pTftpServer->RxBuffer ), - 0, - (struct sockaddr *) &pTftpServer->RemoteAddress, - &RemoteAddressLength ); - if ( -1 != pTftpServer->RxBytes ) { - pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength; - DEBUG (( DEBUG_TFTP_PORT, - "Received %d bytes from %d.%d.%d.%d:%d\r\n", - pTftpServer->RxBytes, - pTftpServer->RemoteAddress.sin_addr.s_addr & 0xff, - ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff, - ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff, - ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff, - htons ( pTftpServer->RemoteAddress.sin_port ))); - - // - // Lookup connection context using the remote system address and port - // to determine if an existing connection to this remote - // system exists - // - pContext = ContextFind ( pTftpServer ); - - // - // Process the received message - // - TftpProcessRequest ( pTftpServer, pContext ); - } - else { - // - // Receive error on the TFTP server port - // Close the server socket - // - DEBUG (( DEBUG_ERROR, - "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n", - errno )); - pTftpServer->TftpPort.revents |= POLLHUP; - } - } - - // - // Handle the close event - // - if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) { - // - // Close the port - // - close ( pTftpServer->TftpPort.fd ); - pTftpServer->TftpPort.fd = -1; - } - - DBG_EXIT ( ); -} - - -/** - Scan the list of sockets and process any pending work - - @param [in] pTftpServer The TFTP server control structure address. - -**/ -VOID -SocketPoll ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - int FDCount; - - DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" )); - - // - // Determine if any ports are active - // - FDCount = poll ( &pTftpServer->TftpPort, - 1, - CLIENT_POLL_DELAY ); - if ( -1 == FDCount ) { - DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL, - "ERROR - errno: %d\r\n", - errno )); - } - - if ( 0 < FDCount ) { - // - // Process this port - // - PortWork ( pTftpServer ); - pTftpServer->TftpPort.revents = 0; - } - - DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" )); -} - - -/** - Convert a character to lower case - - @param [in] Character The character to convert - - @returns The lower case equivalent of the character - -**/ -int -tolower ( - int Character - ) -{ - // - // Determine if the character is upper case - // - if (( 'A' <= Character ) && ( 'Z' >= Character )) { - // - // Convert the character to lower caes - // - Character += 'a' - 'A'; - } - - // - // Return the converted character - // - return Character; -} - - -/** - Case independent string comparison - - @param [in] pString1 Zero terminated string address - @param [in] pString2 Zero terminated string address - - @returns Returns the first character difference between string 1 - and string 2. - -**/ -int -stricmp ( - char * pString1, - char * pString2 - ) -{ - int Char1; - int Char2; - int Difference; - - // - // Walk the length of the strings - // - do { - // - // Get the next characters - // - Char1 = (UINT8)*pString1++; - Char2 = (UINT8)*pString2++; - - // - // Convert them to lower case - // - Char1 = tolower ( Char1 ); - Char2 = tolower ( Char2 ); - - // - // Done when the characters differ - // - Difference = Char1 - Char2; - if ( 0 != Difference ) { - break; - } - - // - // Done at the end of the string - // - } while ( 0 != Char1 ); - - // - // Return the difference - // - return Difference; -} - - -/** - Get the next TFTP option - - @param [in] pOption Address of a zero terminated option string - @param [in] pEnd End of buffer address - @param [in] ppNextOption Address to receive the address of the next - zero terminated option string - - @retval EFI_SUCCESS Message processed successfully - -**/ -EFI_STATUS -TftpOptionGet ( - IN UINT8 * pOption, - IN UINT8 * pEnd, - IN UINT8 ** ppNextOption - ) -{ - UINT8 * pNextOption; - EFI_STATUS Status; - - // - // Locate the end of the option - // - pNextOption = pOption; - while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) { - pNextOption += 1; - } - if ( pEnd <= pNextOption ) { - // - // Error - end of buffer reached - // - DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST, - "ERROR - Option without zero termination received!\r\n" )); - Status = EFI_INVALID_PARAMETER; - } - else { - // - // Zero terminated option found - // - pNextOption += 1; - - // - // Display the zero terminated ASCII option string - // - DEBUG (( DEBUG_TFTP_REQUEST, - "Option: %a\r\n", - pOption )); - Status = EFI_SUCCESS; - } - - // - // Return the next option address - // - *ppNextOption = pNextOption; - - // - // Return the operation status - // - return Status; -} - - -/** - Place an option value into the option acknowledgement - - @param [in] pOack Option acknowledgement address - @param [in] Value Value to translate into ASCII decimal - - @returns Option acknowledgement address - -**/ -UINT8 * -TftpOptionSet ( - IN UINT8 * pOack, - IN UINT64 Value - ) -{ - UINT64 NextValue; - - // - // Determine the next value - // - NextValue = Value / 10; - - // - // Supress leading zeros - // - if ( 0 != NextValue ) { - pOack = TftpOptionSet ( pOack, NextValue ); - } - - // - // Output this digit - // - *pOack++ = (UINT8)( Value - ( NextValue * 10 ) + '0' ); - - // - // Return the next option acknowledgement location - // - return pOack; -} - - -/** - Process the TFTP request - - @param [in] pContext The context structure address. - @param [in] pOption Address of the first zero terminated option string - @param [in] pEnd End of buffer address - -**/ -VOID -TftpOptions ( - IN TSDT_CONNECTION_CONTEXT * pContext, - IN UINT8 * pOption, - IN UINT8 * pEnd - ) -{ - UINT8 * pNextOption; - UINT8 * pOack; - UINT8 * pTemp; - UINT8 * pValue; - EFI_STATUS Status; - INT32 Value; - - // - // Start the OACK packet - // Let the OACK handle the parsing errors - // See http://tools.ietf.org/html/rfc2347 - // - pOack = &pContext->TxBuffer[0]; - *pOack++ = 0; - *pOack++ = TFTP_OP_OACK; - pContext->TxBytes = 2; - - // - // Walk the list of options - // - do { - // - // Get the next option, skip junk at end of message - // - Status = TftpOptionGet ( pOption, pEnd, &pNextOption ); - if ( !EFI_ERROR ( Status )) { - // - // Process the option - // - - // - // blksize - See http://tools.ietf.org/html/rfc2348 - // - pValue = pNextOption; - if ( 0 == stricmp ((char *)pOption, "blksize" )) { - // - // Get the value - // - Status = TftpOptionGet ( pValue, pEnd, &pNextOption ); - if ( !EFI_ERROR ( Status )) { - // - // Validate the block size, skip non-numeric block sizes - // - Status = TftpOptionValue ( pValue, &Value ); - if ( !EFI_ERROR ( Status )) { - // - // Propose a smaller block size if necessary - // - if ( Value > TFTP_MAX_BLOCK_SIZE ) { - Value = TFTP_MAX_BLOCK_SIZE; - } - - // - // Set the new block size - // - pContext->BlockSize = Value; - DEBUG (( DEBUG_TFTP_REQUEST, - "Using block size of %d bytes\r\n", - pContext->BlockSize )); - - // - // Update the OACK - // - pTemp = pOack; - *pOack++ = 'b'; - *pOack++ = 'l'; - *pOack++ = 'k'; - *pOack++ = 's'; - *pOack++ = 'i'; - *pOack++ = 'z'; - *pOack++ = 'e'; - *pOack++ = 0; - pOack = TftpOptionSet ( pOack, pContext->BlockSize ); - *pOack++ = 0; - pContext->TxBytes += pOack - pTemp; - } - } - } - - // - // timeout - See http://tools.ietf.org/html/rfc2349 - // - else if ( 0 == stricmp ((char *)pOption, "timeout" )) { - // - // Get the value - // - Status = TftpOptionGet ( pValue, pEnd, &pNextOption ); - if ( !EFI_ERROR ( Status )) { - Status = TftpOptionValue ( pValue, &Value ); - if ( !EFI_ERROR ( Status )) { - // - // Set the timeout value - // - pContext->Timeout = Value; - DEBUG (( DEBUG_TFTP_REQUEST, - "Using timeout of %d seconds\r\n", - pContext->Timeout )); - - // - // Update the OACK - // - pTemp = pOack; - *pOack++ = 't'; - *pOack++ = 'i'; - *pOack++ = 'm'; - *pOack++ = 'e'; - *pOack++ = 'o'; - *pOack++ = 'u'; - *pOack++ = 't'; - *pOack++ = 0; - pOack = TftpOptionSet ( pOack, pContext->Timeout ); - *pOack++ = 0; - pContext->TxBytes += pOack - pTemp; - } - } - } - - // - // tsize - See http://tools.ietf.org/html/rfc2349 - // - else if ( 0 == stricmp ((char *)pOption, "tsize" )) { - // - // Get the value - // - Status = TftpOptionGet ( pValue, pEnd, &pNextOption ); - if ( !EFI_ERROR ( Status )) { - Status = TftpOptionValue ( pValue, &Value ); - if ( !EFI_ERROR ( Status )) { - // - // Return the file size - // - DEBUG (( DEBUG_TFTP_REQUEST, - "Returning file size of %Ld bytes\r\n", - pContext->LengthInBytes )); - - // - // Update the OACK - // - pTemp = pOack; - *pOack++ = 't'; - *pOack++ = 's'; - *pOack++ = 'i'; - *pOack++ = 'z'; - *pOack++ = 'e'; - *pOack++ = 0; - pOack = TftpOptionSet ( pOack, pContext->LengthInBytes ); - *pOack++ = 0; - pContext->TxBytes += pOack - pTemp; - } - } - } - else { - // - // Unknown option - Ignore it - // - DEBUG (( DEBUG_WARN | DEBUG_TFTP_REQUEST, - "WARNING - Skipping unknown option: %a\r\n", - pOption )); - } - } - - // - // Set the next option - // - pOption = pNextOption; - } while ( pEnd > pOption ); -} - - -/** - Process the TFTP request - - @param [in] pOption Address of the first zero terminated option string - @param [in] pValue Address to receive the value - - @retval EFI_SUCCESS Option translated into a value - -**/ -EFI_STATUS -TftpOptionValue ( - IN UINT8 * pOption, - IN INT32 * pValue - ) -{ - UINT8 Digit; - EFI_STATUS Status; - INT32 Value; - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Walk the characters in the option - // - Value = 0; - while ( 0 != *pOption ) { - // - // Convert the next digit to binary - // - Digit = *pOption++; - if (( '0' <= Digit ) && ( '9' >= Digit )) { - Value *= 10; - Value += Digit - '0'; - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST, - "ERROR - Invalid character '0x%02x' in the value\r\n", - Digit )); - Status = EFI_INVALID_PARAMETER; - break; - } - } - - // - // Return the value - // - *pValue = Value; - - // - // Return the conversion status - // - return Status; -} - - -/** - Process the TFTP request - - @param [in] pTftpServer The TFTP server control structure address. - @param [in] pContext Connection context structure address - -**/ -VOID -TftpProcessRequest ( - IN TSDT_TFTP_SERVER * pTftpServer, - IN TSDT_CONNECTION_CONTEXT * pContext - ) -{ - BOOLEAN bCloseContext; - BOOLEAN bIgnorePacket; - UINT16 BlockNumber; - UINT16 Opcode; - UINT8 * pBuffer; - UINT8 * pEnd; - UINT8 * pFileName; - UINT8 * pMode; - UINT8 * pOption; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Get the opcode - // - pBuffer = &pTftpServer->RxBuffer[0]; - Opcode = HTONS ( *(UINT16 *)&pBuffer[0]); -Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode ); - - // - // Validate the parameters - // - bCloseContext = FALSE; - bIgnorePacket = FALSE; - switch ( Opcode ) { - default: - DEBUG (( DEBUG_TFTP_REQUEST, - "ERROR - Unknown TFTP opcode: %d\r\n", - Opcode )); - bIgnorePacket = TRUE; - break; - - case TFTP_OP_READ_REQUEST: - break; - - case TFTP_OP_DATA: - if ( NULL == pContext ) { - DEBUG (( DEBUG_ERROR, - "ERROR - File not open for %d.%d.%d.%d:%d\r\n", - (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr, - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ), - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ), - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ), - htons ( pTftpServer->RemoteAddress.sin_port ))); - bIgnorePacket = TRUE; - break; - } - if ( pContext->bExpectAck ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n", - pContext )); - bIgnorePacket = TRUE; - break; - } - if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 )) - { - DEBUG (( DEBUG_ERROR, - "ERROR - Receive data length of %d > %d bytes (maximum block size) for pContext 0x%08x\r\n", - pTftpServer->RxBytes - 2 - 2, - pContext->BlockSize, - pContext )); - bIgnorePacket = TRUE; - break; - } - break; - - case TFTP_OP_ACK: - if ( NULL == pContext ) { - DEBUG (( DEBUG_ERROR, - "ERROR - File not open for %d.%d.%d.%d:%d\r\n", - (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr, - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ), - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ), - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ), - htons ( pTftpServer->RemoteAddress.sin_port ))); - bIgnorePacket = TRUE; - } - if ( !pContext->bExpectAck ) { - DEBUG (( DEBUG_ERROR, - "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n", - pContext )); - bIgnorePacket = TRUE; - break; - } - break; - - case TFTP_OP_ERROR: - if ( NULL == pContext ) { - DEBUG (( DEBUG_ERROR, - "ERROR - File not open for %d.%d.%d.%d:%d\r\n", - (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr, - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ), - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ), - (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ), - htons ( pTftpServer->RemoteAddress.sin_port ))); - bIgnorePacket = TRUE; - } - break; - } - if ( !bIgnorePacket ) { - // - // Process the request - // - switch ( Opcode ) { - default: - DEBUG (( DEBUG_TFTP_REQUEST, - "ERROR - Unable to process TFTP opcode: %d\r\n", - Opcode )); - break; - - case TFTP_OP_READ_REQUEST: - - // - // Close the context if necessary - // - if ( NULL != pContext ) { - ContextRemove ( pTftpServer, pContext ); - } - - // - // Create the connection context - // - pContext = ContextAdd ( pTftpServer ); - if ( NULL == pContext ) { - break; - } - - // - // Locate the mode - // - pFileName = &pBuffer[2]; - pEnd = &pBuffer[pTftpServer->RxBytes]; - pMode = pFileName; - while (( pEnd > pMode ) && ( 0 != *pMode )) { - pMode += 1; - } - if ( pEnd <= pMode ) { - // - // Mode not found - // - DEBUG (( DEBUG_ERROR | DEBUG_RX, - "ERROR - File mode not found\r\n" )); - // - // Tell the client of the error - // - TftpSendError ( pTftpServer, - pContext, - 0, - (UINT8 *)"File open mode not found" ); - break; - } - pMode += 1; - DEBUG (( DEBUG_TFTP_REQUEST, - "TFTP - FileName: %a\n", - pFileName )); - - // - // Locate the options - // - pOption = pMode; - while (( pEnd > pOption ) && ( 0 != *pOption )) { - pOption += 1; - } - if ( pEnd <= pOption ) { - // - // End of mode not found - // - DEBUG (( DEBUG_ERROR | DEBUG_RX, - "ERROR - File mode not valid\r\n" )); - // - // Tell the client of the error - // - TftpSendError ( pTftpServer, - pContext, - 0, - (UINT8 *)"File open mode not valid" ); - break; - } - pOption += 1; - DEBUG (( DEBUG_TFTP_REQUEST, - "TFTP - Mode: %a\r\n", - pMode )); - - // - // Verify the mode is supported - // - if ( 0 != stricmp ((char *)pMode, "octet" )) { - // - // File access mode not supported - // - DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST, - "ERROR - File mode %a not supported\r\n", - pMode )); - - // - // Tell the client of the error - // - TftpSendError ( pTftpServer, - pContext, - 0, - (UINT8 *)"File open mode not supported" ); - break; - } - - // - // Open the file, close the context on error - // -// TODO: Remove the following line -pContext->File = (EFI_HANDLE)1; - - // - // Determine the file length - // -//fstat - - // - // Process the options - // - TftpOptions ( pContext, pOption, pEnd ); - - // - // Read in the first portion of the file - // - - // - // Send the first block - // - pContext->bExpectAck = TRUE; - if ( 2 < pContext->TxBytes ) { - // - // Send the OACK - // - Status = TftpTxPacket ( pTftpServer, pContext ); - } - else { - // - // Send the first block of data - // - Status = TftpSendNextBlock ( pTftpServer, pContext ); - } - break; - - case TFTP_OP_ACK: - // - // Get the block number that is being ACKed - // - BlockNumber = pTftpServer->RxBuffer[2]; - BlockNumber <<= 8; - BlockNumber |= pTftpServer->RxBuffer[3]; - - // - // Determine if this is the correct ACK - // - DEBUG (( DEBUG_TFTP_ACK, - "ACK for block 0x%04x received\r\n", - BlockNumber )); - if (( !pContext->bExpectAck ) - || ( BlockNumber != pContext->AckNext )) - { - DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK, - "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n", - pContext->AckNext, - BlockNumber )); - } - else { - // - // Process the expected ACK - // - if ( pContext->bEofSent ) { - bCloseContext = TRUE; - } - else { - // - // Set the next expected ACK - // - pContext->AckNext += 1; - - // - // Send the next packet of data - // - Status = TftpSendNextBlock ( pTftpServer, pContext ); - } - } - break; - } - } - - // - // Determine if the context should be closed - // - if ( bCloseContext ) { - ContextRemove ( pTftpServer, pContext ); - } - - DBG_EXIT ( ); -} - - -/** - Build and send an error packet - - @param [in] pTftpServer The TFTP server control structure address. - @param [in] pContext The context structure address. - @param [in] Error Error number for the packet - @param [in] pError Zero terminated error string address - - @retval EFI_SUCCESS Message processed successfully - -**/ -EFI_STATUS -TftpSendError ( - IN TSDT_TFTP_SERVER * pTftpServer, - IN TSDT_CONNECTION_CONTEXT * pContext, - IN UINT16 Error, - IN UINT8 * pError - ) -{ - UINT8 Character; - UINT8 * pBuffer; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Build the error packet - // - pBuffer = &pContext->TxBuffer[0]; - pBuffer[0] = 0; - pBuffer[1] = TFTP_OP_ERROR; - pBuffer[2] = (UINT8)( Error >> 8 ); - pBuffer[3] = (UINT8)Error; - - // - // Copy the zero terminated string into the buffer - // - pBuffer += 4; - do { - Character = *pError++; - *pBuffer++ = Character; - } while ( 0 != Character ); - - // - // Send the error message - // - pContext->TxBytes = pBuffer - &pContext->TxBuffer[0]; - Status = TftpTxPacket ( pTftpServer, pContext ); - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Send the next block of file system data - - @param [in] pTftpServer The TFTP server control structure address. - @param [in] pContext The context structure address. - - @retval EFI_SUCCESS Message processed successfully - -**/ -EFI_STATUS -TftpSendNextBlock ( - IN TSDT_TFTP_SERVER * pTftpServer, - IN TSDT_CONNECTION_CONTEXT * pContext - ) -{ - ssize_t LengthInBytes; - UINT8 * pBuffer; - EFI_STATUS Status; - - // - // Determine how much data needs to be sent - // - LengthInBytes = pContext->BlockSize; - if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE ) - || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) { - LengthInBytes = (ssize_t)pContext->LengthInBytes; - pContext->bEofSent = TRUE; - } - - // - // Set the TFTP opcode and block number - // - pBuffer = &pContext->TxBuffer[0]; - *pBuffer++ = 0; - *pBuffer++ = TFTP_OP_DATA; - *pBuffer++ = (UINT8)( pContext->AckNext >> 8 ); - *pBuffer++ = (UINT8)pContext->AckNext; - - // - // Copy the file data into the transmit buffer - // - pContext->TxBytes = 2 + 2 + LengthInBytes; - if ( 0 < LengthInBytes ) { - CopyMem ( &pBuffer, - pContext->pBuffer, - LengthInBytes ); - } - - // - // Send the next block - // - Status = TftpTxPacket ( pTftpServer, pContext ); - - // - // Return the operation status - // - return Status; -} - - -/** - Create the port for the TFTP server - - This routine polls the network layer to create the TFTP port for the - TFTP server. More than one attempt may be necessary since it may take - some time to get the IP address and initialize the upper layers of - the network stack. - - @param [in] pTftpServer The TFTP server control structure address. - -**/ -VOID -TftpServerTimer ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - UINT16 TftpPort; - int SocketStatus; - EFI_STATUS Status; - - DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" )); - - // - // Open the TFTP port on the server - // - do { - do { - // - // Wait for a while - // - Status = gBS->CheckEvent ( pTftpServer->TimerEvent ); - } while ( EFI_SUCCESS != Status ); - - // - // Attempt to create the socket for the TFTP server - // - pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP; - pTftpServer->TftpPort.revents = 0; - pTftpServer->TftpPort.fd = socket ( AF_INET, - SOCK_DGRAM, - IPPROTO_UDP ); - if ( -1 != pTftpServer->TftpPort.fd ) - { - // - // Set the socket address - // - ZeroMem ( &pTftpServer->TftpServerAddress, - sizeof ( pTftpServer->TftpServerAddress )); - TftpPort = 69; - DEBUG (( DEBUG_TFTP_PORT, - "TFTP Port: %d\r\n", - TftpPort )); - pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress ); - pTftpServer->TftpServerAddress.sin_family = AF_INET; - pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY; - pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort ); - - // - // Bind the socket to the TFTP port - // - SocketStatus = bind ( pTftpServer->TftpPort.fd, - (struct sockaddr *) &pTftpServer->TftpServerAddress, - pTftpServer->TftpServerAddress.sin_len ); - if ( -1 != SocketStatus ) { - DEBUG (( DEBUG_TFTP_PORT, - "0x%08x: Socket bound to port %d\r\n", - pTftpServer->TftpPort.fd, - TftpPort )); - } - - // - // Release the socket if necessary - // - if ( -1 == SocketStatus ) { - close ( pTftpServer->TftpPort.fd ); - pTftpServer->TftpPort.fd = -1; - } - } - - // - // Wait until the socket is open - // - }while ( -1 == pTftpServer->TftpPort.fd ); - - DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" )); -} - - -/** - Start the TFTP server port creation timer - - @param [in] pTftpServer The TFTP server control structure address. - - @retval EFI_SUCCESS The timer was successfully started. - @retval EFI_ALREADY_STARTED The timer is already running. - @retval Other The timer failed to start. - -**/ -EFI_STATUS -TftpServerTimerStart ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - EFI_STATUS Status; - UINT64 TriggerTime; - - DBG_ENTER ( ); - - // - // Assume the timer is already running - // - Status = EFI_ALREADY_STARTED; - if ( !pTftpServer->bTimerRunning ) { - // - // Compute the poll interval - // - TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 ); - Status = gBS->SetTimer ( pTftpServer->TimerEvent, - TimerPeriodic, - TriggerTime ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" )); - - // - // Mark the timer running - // - pTftpServer->bTimerRunning = TRUE; - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT, - "ERROR - Failed to start TFTP port timer, Status: %r\r\n", - Status )); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Stop the TFTP server port creation timer - - @param [in] pTftpServer The TFTP server control structure address. - - @retval EFI_SUCCESS The TFTP port timer is stopped - @retval Other Failed to stop the TFTP port timer - -**/ -EFI_STATUS -TftpServerTimerStop ( - IN TSDT_TFTP_SERVER * pTftpServer - ) -{ - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume the timer is stopped - // - Status = EFI_SUCCESS; - if ( pTftpServer->bTimerRunning ) { - // - // Stop the port creation polling - // - Status = gBS->SetTimer ( pTftpServer->TimerEvent, - TimerCancel, - 0 ); - if ( !EFI_ERROR ( Status )) { - DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" )); - - // - // Mark the timer stopped - // - pTftpServer->bTimerRunning = FALSE; - } - else { - DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT, - "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n", - Status )); - } - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - -/** - Send the next TFTP packet - - @param [in] pTftpServer The TFTP server control structure address. - @param [in] pContext The context structure address. - - @retval EFI_SUCCESS Message processed successfully - -**/ -EFI_STATUS -TftpTxPacket ( - IN TSDT_TFTP_SERVER * pTftpServer, - IN TSDT_CONNECTION_CONTEXT * pContext - ) -{ - ssize_t LengthInBytes; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Assume success - // - Status = EFI_SUCCESS; - - // - // Send the TFTP packet - // - DEBUG (( DEBUG_TX, - "0x%08x: pContext sending 0x%08x bytes\r\n", - pContext, - pContext->TxBytes )); - LengthInBytes = sendto ( pTftpServer->TftpPort.fd, - &pContext->TxBuffer[0], - pContext->TxBytes, - 0, - (struct sockaddr *)&pContext->RemoteAddress, - pContext->RemoteAddress.sin_len ); - if ( -1 == LengthInBytes ) { - DEBUG (( DEBUG_ERROR | DEBUG_TX, - "ERROR - Transmit failure, errno: 0x%08x\r\n", - errno )); - Status = EFI_DEVICE_ERROR; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Entry point for the TFTP server application. - - @param [in] Argc The number of arguments - @param [in] Argv The argument value array - - @retval 0 The application exited normally. - @retval Other An error occurred. -**/ -int -main ( - IN int Argc, - IN char **Argv - ) -{ - TSDT_TFTP_SERVER * pTftpServer; - EFI_STATUS Status; - - // - // Create a timer event to start TFTP port - // - pTftpServer = &mTftpServer; - Status = gBS->CreateEvent ( EVT_TIMER, - TPL_TFTP_SERVER, - NULL, - NULL, - &pTftpServer->TimerEvent ); - if ( !EFI_ERROR ( Status )) { - Status = TftpServerTimerStart ( pTftpServer ); - if ( !EFI_ERROR ( Status )) { - // - // Run the TFTP server forever - // - for ( ; ; ) { - // - // Poll the network layer to create the TFTP port - // for the tftp server. More than one attempt may - // be necessary since it may take some time to get - // the IP address and initialize the upper layers - // of the network stack. - // - TftpServerTimer ( pTftpServer ); - - // - // Poll the socket for activity - // - do { - SocketPoll ( pTftpServer ); - } while ( -1 != pTftpServer->TftpPort.fd ); - -// -// TODO: Remove the following test code -// Exit when the network connection is broken -// -break; - } - - // - // Done with the timer event - // - TftpServerTimerStop ( pTftpServer ); - Status = gBS->CloseEvent ( pTftpServer->TimerEvent ); - } - } - - // - // Return the final status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} +/*++
+ This file contains an 'Intel UEFI Application' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+--*/
+/*++
+
+Copyright (c) 2011 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+--*/
+
+/** @file
+ This is a simple TFTP server application
+
+**/
+
+#include <TftpServer.h>
+
+TSDT_TFTP_SERVER mTftpServer; ///< TFTP server's control structure
+
+
+/**
+ Add a connection context to the list of connection contexts.
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+ @retval Context structure address, NULL if allocation fails
+
+**/
+TSDT_CONNECTION_CONTEXT *
+ContextAdd (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ size_t LengthInBytes;
+ TSDT_CONNECTION_CONTEXT * pContext;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Allocate a new context
+ //
+ LengthInBytes = sizeof ( *pContext );
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **)&pContext );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+ "ERROR - Failed to allocate the context, Status: %r\r\n",
+ Status ));
+ pContext = NULL;
+ break;
+ }
+
+ //
+ // Initialize the context
+ //
+ ZeroMem ( pContext, LengthInBytes );
+ CopyMem ( &pContext->RemoteAddress,
+ &pTftpServer->RemoteAddress,
+ sizeof ( pContext->RemoteAddress ));
+ pContext->BlockSize = TFTP_MAX_BLOCK_SIZE;
+ pContext->pBuffer = &pContext->FileData[0];
+ pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )];
+ pContext->MaxTransferSize = 0;
+ pContext->MaxTransferSize -= 1;
+
+ //
+ // Display the new context
+ //
+ DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,
+ "0x%08x: Context for %d.%d.%d.%d:%d\r\n",
+ pContext,
+ (UINT8)pContext->RemoteAddress.sin_addr.s_addr,
+ (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ),
+ (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ),
+ (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ),
+ htons ( pContext->RemoteAddress.sin_port )));
+
+ //
+ // Add the context to the context list
+ //
+ pContext->pNext = pTftpServer->pContextList;
+ pTftpServer->pContextList = pContext;
+
+ //
+ // All done
+ //
+ break;
+ }
+
+ //
+ // Return the connection context
+ //
+ DBG_EXIT_STATUS ( pContext );
+ return pContext;
+}
+
+
+/**
+ Locate a remote connection context.
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+ @param [in] pIpAddress The start of the remote IP address in network order
+
+ @param [in] Port The remote port number
+
+ @retval Context structure address, NULL if not found
+
+**/
+TSDT_CONNECTION_CONTEXT *
+ContextFind (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ TSDT_CONNECTION_CONTEXT * pContext;
+
+ DBG_ENTER ( );
+
+ //
+ // Walk the list of connection contexts
+ //
+ pContext = pTftpServer->pContextList;
+ while ( NULL != pContext ) {
+ //
+ // Attempt to locate the remote network connection
+ //
+ if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr )
+ && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) {
+ //
+ // The connection was found
+ //
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "0x%08x: pContext found\r\n",
+ pContext ));
+ break;
+ }
+
+ //
+ // Set the next context
+ //
+ pContext = pContext->pNext;
+ }
+
+ //
+ // Return the connection context structure address
+ //
+ DBG_EXIT_HEX ( pContext );
+ return pContext;
+}
+
+
+/**
+ Remove a context from the list.
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+ @param [in] pContext The context structure address.
+
+**/
+VOID
+ContextRemove (
+ IN TSDT_TFTP_SERVER * pTftpServer,
+ IN TSDT_CONNECTION_CONTEXT * pContext
+ )
+{
+ TSDT_CONNECTION_CONTEXT * pNextContext;
+ TSDT_CONNECTION_CONTEXT * pPreviousContext;
+
+ DBG_ENTER ( );
+
+ //
+ // Attempt to locate the context in the list
+ //
+ pPreviousContext = NULL;
+ pNextContext = pTftpServer->pContextList;
+ while ( NULL != pNextContext ) {
+ //
+ // Determine if the context was found
+ //
+ if ( pNextContext == pContext ) {
+ //
+ // Remove the context from the list
+ //
+ if ( NULL == pPreviousContext ) {
+ pTftpServer->pContextList = pContext->pNext;
+ }
+ else {
+ pPreviousContext->pNext = pContext->pNext;
+ }
+ break;
+ }
+
+ //
+ // Set the next context
+ //
+ pPreviousContext = pNextContext;
+ pNextContext = pNextContext->pNext;
+ }
+
+ //
+ // Determine if the context was found
+ //
+ if ( NULL != pContext ) {
+ //
+ // Return the resources
+ //
+ gBS->FreePool ( pContext );
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Process the work for the sockets.
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+**/
+VOID
+PortWork (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ TSDT_CONNECTION_CONTEXT * pContext;
+ socklen_t RemoteAddressLength;
+
+ DBG_ENTER ( );
+
+ //
+ // Handle input events
+ //
+ if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) {
+ //
+ // Receive the message from the remote system
+ //
+ RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );
+ pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd,
+ &pTftpServer->RxBuffer[0],
+ sizeof ( pTftpServer->RxBuffer ),
+ 0,
+ (struct sockaddr *) &pTftpServer->RemoteAddress,
+ &RemoteAddressLength );
+ if ( -1 != pTftpServer->RxBytes ) {
+ pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength;
+ DEBUG (( DEBUG_TFTP_PORT,
+ "Received %d bytes from %d.%d.%d.%d:%d\r\n",
+ pTftpServer->RxBytes,
+ pTftpServer->RemoteAddress.sin_addr.s_addr & 0xff,
+ ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
+ ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
+ ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
+ htons ( pTftpServer->RemoteAddress.sin_port )));
+
+ //
+ // Lookup connection context using the remote system address and port
+ // to determine if an existing connection to this remote
+ // system exists
+ //
+ pContext = ContextFind ( pTftpServer );
+
+ //
+ // Process the received message
+ //
+ TftpProcessRequest ( pTftpServer, pContext );
+ }
+ else {
+ //
+ // Receive error on the TFTP server port
+ // Close the server socket
+ //
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",
+ errno ));
+ pTftpServer->TftpPort.revents |= POLLHUP;
+ }
+ }
+
+ //
+ // Handle the close event
+ //
+ if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) {
+ //
+ // Close the port
+ //
+ close ( pTftpServer->TftpPort.fd );
+ pTftpServer->TftpPort.fd = -1;
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Scan the list of sockets and process any pending work
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+**/
+VOID
+SocketPoll (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ int FDCount;
+
+ DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));
+
+ //
+ // Determine if any ports are active
+ //
+ FDCount = poll ( &pTftpServer->TftpPort,
+ 1,
+ CLIENT_POLL_DELAY );
+ if ( -1 == FDCount ) {
+ DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL,
+ "ERROR - errno: %d\r\n",
+ errno ));
+ }
+
+ if ( 0 < FDCount ) {
+ //
+ // Process this port
+ //
+ PortWork ( pTftpServer );
+ pTftpServer->TftpPort.revents = 0;
+ }
+
+ DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));
+}
+
+
+/**
+ Convert a character to lower case
+
+ @param [in] Character The character to convert
+
+ @return The lower case equivalent of the character
+
+**/
+int
+tolower (
+ int Character
+ )
+{
+ //
+ // Determine if the character is upper case
+ //
+ if (( 'A' <= Character ) && ( 'Z' >= Character )) {
+ //
+ // Convert the character to lower caes
+ //
+ Character += 'a' - 'A';
+ }
+
+ //
+ // Return the converted character
+ //
+ return Character;
+}
+
+
+/**
+ Case independent string comparison
+
+ @param [in] pString1 Zero terminated string address
+ @param [in] pString2 Zero terminated string address
+
+ @return Returns the first character difference between string 1
+ and string 2.
+
+**/
+int
+stricmp (
+ char * pString1,
+ char * pString2
+ )
+{
+ int Char1;
+ int Char2;
+ int Difference;
+
+ //
+ // Walk the length of the strings
+ //
+ do {
+ //
+ // Get the next characters
+ //
+ Char1 = (UINT8)*pString1++;
+ Char2 = (UINT8)*pString2++;
+
+ //
+ // Convert them to lower case
+ //
+ Char1 = tolower ( Char1 );
+ Char2 = tolower ( Char2 );
+
+ //
+ // Done when the characters differ
+ //
+ Difference = Char1 - Char2;
+ if ( 0 != Difference ) {
+ break;
+ }
+
+ //
+ // Done at the end of the string
+ //
+ } while ( 0 != Char1 );
+
+ //
+ // Return the difference
+ //
+ return Difference;
+}
+
+
+/**
+ Get the next TFTP option
+
+ @param [in] pOption Address of a zero terminated option string
+ @param [in] pEnd End of buffer address
+ @param [in] ppNextOption Address to receive the address of the next
+ zero terminated option string
+
+ @retval EFI_SUCCESS Message processed successfully
+
+**/
+EFI_STATUS
+TftpOptionGet (
+ IN UINT8 * pOption,
+ IN UINT8 * pEnd,
+ IN UINT8 ** ppNextOption
+ )
+{
+ UINT8 * pNextOption;
+ EFI_STATUS Status;
+
+ //
+ // Locate the end of the option
+ //
+ pNextOption = pOption;
+ while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {
+ pNextOption += 1;
+ }
+ if ( pEnd <= pNextOption ) {
+ //
+ // Error - end of buffer reached
+ //
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
+ "ERROR - Option without zero termination received!\r\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else {
+ //
+ // Zero terminated option found
+ //
+ pNextOption += 1;
+
+ //
+ // Display the zero terminated ASCII option string
+ //
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "Option: %a\r\n",
+ pOption ));
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // Return the next option address
+ //
+ *ppNextOption = pNextOption;
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Place an option value into the option acknowledgement
+
+ @param [in] pOack Option acknowledgement address
+ @param [in] Value Value to translate into ASCII decimal
+
+ @return Option acknowledgement address
+
+**/
+UINT8 *
+TftpOptionSet (
+ IN UINT8 * pOack,
+ IN UINT64 Value
+ )
+{
+ UINT64 NextValue;
+
+ //
+ // Determine the next value
+ //
+ NextValue = Value / 10;
+
+ //
+ // Supress leading zeros
+ //
+ if ( 0 != NextValue ) {
+ pOack = TftpOptionSet ( pOack, NextValue );
+ }
+
+ //
+ // Output this digit
+ //
+ *pOack++ = (UINT8)( Value - ( NextValue * 10 ) + '0' );
+
+ //
+ // Return the next option acknowledgement location
+ //
+ return pOack;
+}
+
+
+/**
+ Process the TFTP request
+
+ @param [in] pContext The context structure address.
+ @param [in] pOption Address of the first zero terminated option string
+ @param [in] pEnd End of buffer address
+
+**/
+VOID
+TftpOptions (
+ IN TSDT_CONNECTION_CONTEXT * pContext,
+ IN UINT8 * pOption,
+ IN UINT8 * pEnd
+ )
+{
+ UINT8 * pNextOption;
+ UINT8 * pOack;
+ UINT8 * pTemp;
+ UINT8 * pValue;
+ EFI_STATUS Status;
+ INT32 Value;
+
+ //
+ // Start the OACK packet
+ // Let the OACK handle the parsing errors
+ // See http://tools.ietf.org/html/rfc2347
+ //
+ pOack = &pContext->TxBuffer[0];
+ *pOack++ = 0;
+ *pOack++ = TFTP_OP_OACK;
+ pContext->TxBytes = 2;
+
+ //
+ // Walk the list of options
+ //
+ do {
+ //
+ // Get the next option, skip junk at end of message
+ //
+ Status = TftpOptionGet ( pOption, pEnd, &pNextOption );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Process the option
+ //
+
+ //
+ // blksize - See http://tools.ietf.org/html/rfc2348
+ //
+ pValue = pNextOption;
+ if ( 0 == stricmp ((char *)pOption, "blksize" )) {
+ //
+ // Get the value
+ //
+ Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Validate the block size, skip non-numeric block sizes
+ //
+ Status = TftpOptionValue ( pValue, &Value );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Propose a smaller block size if necessary
+ //
+ if ( Value > TFTP_MAX_BLOCK_SIZE ) {
+ Value = TFTP_MAX_BLOCK_SIZE;
+ }
+
+ //
+ // Set the new block size
+ //
+ pContext->BlockSize = Value;
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "Using block size of %d bytes\r\n",
+ pContext->BlockSize ));
+
+ //
+ // Update the OACK
+ //
+ pTemp = pOack;
+ *pOack++ = 'b';
+ *pOack++ = 'l';
+ *pOack++ = 'k';
+ *pOack++ = 's';
+ *pOack++ = 'i';
+ *pOack++ = 'z';
+ *pOack++ = 'e';
+ *pOack++ = 0;
+ pOack = TftpOptionSet ( pOack, pContext->BlockSize );
+ *pOack++ = 0;
+ pContext->TxBytes += pOack - pTemp;
+ }
+ }
+ }
+
+ //
+ // timeout - See http://tools.ietf.org/html/rfc2349
+ //
+ else if ( 0 == stricmp ((char *)pOption, "timeout" )) {
+ //
+ // Get the value
+ //
+ Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
+ if ( !EFI_ERROR ( Status )) {
+ Status = TftpOptionValue ( pValue, &Value );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Set the timeout value
+ //
+ pContext->Timeout = Value;
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "Using timeout of %d seconds\r\n",
+ pContext->Timeout ));
+
+ //
+ // Update the OACK
+ //
+ pTemp = pOack;
+ *pOack++ = 't';
+ *pOack++ = 'i';
+ *pOack++ = 'm';
+ *pOack++ = 'e';
+ *pOack++ = 'o';
+ *pOack++ = 'u';
+ *pOack++ = 't';
+ *pOack++ = 0;
+ pOack = TftpOptionSet ( pOack, pContext->Timeout );
+ *pOack++ = 0;
+ pContext->TxBytes += pOack - pTemp;
+ }
+ }
+ }
+
+ //
+ // tsize - See http://tools.ietf.org/html/rfc2349
+ //
+ else if ( 0 == stricmp ((char *)pOption, "tsize" )) {
+ //
+ // Get the value
+ //
+ Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
+ if ( !EFI_ERROR ( Status )) {
+ Status = TftpOptionValue ( pValue, &Value );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Return the file size
+ //
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "Returning file size of %Ld bytes\r\n",
+ pContext->LengthInBytes ));
+
+ //
+ // Update the OACK
+ //
+ pTemp = pOack;
+ *pOack++ = 't';
+ *pOack++ = 's';
+ *pOack++ = 'i';
+ *pOack++ = 'z';
+ *pOack++ = 'e';
+ *pOack++ = 0;
+ pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );
+ *pOack++ = 0;
+ pContext->TxBytes += pOack - pTemp;
+ }
+ }
+ }
+ else {
+ //
+ // Unknown option - Ignore it
+ //
+ DEBUG (( DEBUG_WARN | DEBUG_TFTP_REQUEST,
+ "WARNING - Skipping unknown option: %a\r\n",
+ pOption ));
+ }
+ }
+
+ //
+ // Set the next option
+ //
+ pOption = pNextOption;
+ } while ( pEnd > pOption );
+}
+
+
+/**
+ Process the TFTP request
+
+ @param [in] pOption Address of the first zero terminated option string
+ @param [in] pValue Address to receive the value
+
+ @retval EFI_SUCCESS Option translated into a value
+
+**/
+EFI_STATUS
+TftpOptionValue (
+ IN UINT8 * pOption,
+ IN INT32 * pValue
+ )
+{
+ UINT8 Digit;
+ EFI_STATUS Status;
+ INT32 Value;
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Walk the characters in the option
+ //
+ Value = 0;
+ while ( 0 != *pOption ) {
+ //
+ // Convert the next digit to binary
+ //
+ Digit = *pOption++;
+ if (( '0' <= Digit ) && ( '9' >= Digit )) {
+ Value *= 10;
+ Value += Digit - '0';
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
+ "ERROR - Invalid character '0x%02x' in the value\r\n",
+ Digit ));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ //
+ // Return the value
+ //
+ *pValue = Value;
+
+ //
+ // Return the conversion status
+ //
+ return Status;
+}
+
+
+/**
+ Process the TFTP request
+
+ @param [in] pTftpServer The TFTP server control structure address.
+ @param [in] pContext Connection context structure address
+
+**/
+VOID
+TftpProcessRequest (
+ IN TSDT_TFTP_SERVER * pTftpServer,
+ IN TSDT_CONNECTION_CONTEXT * pContext
+ )
+{
+ BOOLEAN bCloseContext;
+ BOOLEAN bIgnorePacket;
+ UINT16 BlockNumber;
+ UINT16 Opcode;
+ UINT8 * pBuffer;
+ UINT8 * pEnd;
+ UINT8 * pFileName;
+ UINT8 * pMode;
+ UINT8 * pOption;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Get the opcode
+ //
+ pBuffer = &pTftpServer->RxBuffer[0];
+ Opcode = HTONS ( *(UINT16 *)&pBuffer[0]);
+Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode );
+
+ //
+ // Validate the parameters
+ //
+ bCloseContext = FALSE;
+ bIgnorePacket = FALSE;
+ switch ( Opcode ) {
+ default:
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "ERROR - Unknown TFTP opcode: %d\r\n",
+ Opcode ));
+ bIgnorePacket = TRUE;
+ break;
+
+ case TFTP_OP_READ_REQUEST:
+ break;
+
+ case TFTP_OP_DATA:
+ if ( NULL == pContext ) {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
+ (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
+ htons ( pTftpServer->RemoteAddress.sin_port )));
+ bIgnorePacket = TRUE;
+ break;
+ }
+ if ( pContext->bExpectAck ) {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",
+ pContext ));
+ bIgnorePacket = TRUE;
+ break;
+ }
+ if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 ))
+ {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Receive data length of %d > %d bytes (maximum block size) for pContext 0x%08x\r\n",
+ pTftpServer->RxBytes - 2 - 2,
+ pContext->BlockSize,
+ pContext ));
+ bIgnorePacket = TRUE;
+ break;
+ }
+ break;
+
+ case TFTP_OP_ACK:
+ if ( NULL == pContext ) {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
+ (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
+ htons ( pTftpServer->RemoteAddress.sin_port )));
+ bIgnorePacket = TRUE;
+ }
+ if ( !pContext->bExpectAck ) {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",
+ pContext ));
+ bIgnorePacket = TRUE;
+ break;
+ }
+ break;
+
+ case TFTP_OP_ERROR:
+ if ( NULL == pContext ) {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
+ (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
+ htons ( pTftpServer->RemoteAddress.sin_port )));
+ bIgnorePacket = TRUE;
+ }
+ break;
+ }
+ if ( !bIgnorePacket ) {
+ //
+ // Process the request
+ //
+ switch ( Opcode ) {
+ default:
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "ERROR - Unable to process TFTP opcode: %d\r\n",
+ Opcode ));
+ break;
+
+ case TFTP_OP_READ_REQUEST:
+
+ //
+ // Close the context if necessary
+ //
+ if ( NULL != pContext ) {
+ ContextRemove ( pTftpServer, pContext );
+ }
+
+ //
+ // Create the connection context
+ //
+ pContext = ContextAdd ( pTftpServer );
+ if ( NULL == pContext ) {
+ break;
+ }
+
+ //
+ // Locate the mode
+ //
+ pFileName = &pBuffer[2];
+ pEnd = &pBuffer[pTftpServer->RxBytes];
+ pMode = pFileName;
+ while (( pEnd > pMode ) && ( 0 != *pMode )) {
+ pMode += 1;
+ }
+ if ( pEnd <= pMode ) {
+ //
+ // Mode not found
+ //
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,
+ "ERROR - File mode not found\r\n" ));
+ //
+ // Tell the client of the error
+ //
+ TftpSendError ( pTftpServer,
+ pContext,
+ 0,
+ (UINT8 *)"File open mode not found" );
+ break;
+ }
+ pMode += 1;
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "TFTP - FileName: %a\n",
+ pFileName ));
+
+ //
+ // Locate the options
+ //
+ pOption = pMode;
+ while (( pEnd > pOption ) && ( 0 != *pOption )) {
+ pOption += 1;
+ }
+ if ( pEnd <= pOption ) {
+ //
+ // End of mode not found
+ //
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,
+ "ERROR - File mode not valid\r\n" ));
+ //
+ // Tell the client of the error
+ //
+ TftpSendError ( pTftpServer,
+ pContext,
+ 0,
+ (UINT8 *)"File open mode not valid" );
+ break;
+ }
+ pOption += 1;
+ DEBUG (( DEBUG_TFTP_REQUEST,
+ "TFTP - Mode: %a\r\n",
+ pMode ));
+
+ //
+ // Verify the mode is supported
+ //
+ if ( 0 != stricmp ((char *)pMode, "octet" )) {
+ //
+ // File access mode not supported
+ //
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
+ "ERROR - File mode %a not supported\r\n",
+ pMode ));
+
+ //
+ // Tell the client of the error
+ //
+ TftpSendError ( pTftpServer,
+ pContext,
+ 0,
+ (UINT8 *)"File open mode not supported" );
+ break;
+ }
+
+ //
+ // Open the file, close the context on error
+ //
+// TODO: Remove the following line
+pContext->File = (EFI_HANDLE)1;
+
+ //
+ // Determine the file length
+ //
+//fstat
+
+ //
+ // Process the options
+ //
+ TftpOptions ( pContext, pOption, pEnd );
+
+ //
+ // Read in the first portion of the file
+ //
+
+ //
+ // Send the first block
+ //
+ pContext->bExpectAck = TRUE;
+ if ( 2 < pContext->TxBytes ) {
+ //
+ // Send the OACK
+ //
+ Status = TftpTxPacket ( pTftpServer, pContext );
+ }
+ else {
+ //
+ // Send the first block of data
+ //
+ Status = TftpSendNextBlock ( pTftpServer, pContext );
+ }
+ break;
+
+ case TFTP_OP_ACK:
+ //
+ // Get the block number that is being ACKed
+ //
+ BlockNumber = pTftpServer->RxBuffer[2];
+ BlockNumber <<= 8;
+ BlockNumber |= pTftpServer->RxBuffer[3];
+
+ //
+ // Determine if this is the correct ACK
+ //
+ DEBUG (( DEBUG_TFTP_ACK,
+ "ACK for block 0x%04x received\r\n",
+ BlockNumber ));
+ if (( !pContext->bExpectAck )
+ || ( BlockNumber != pContext->AckNext ))
+ {
+ DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK,
+ "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",
+ pContext->AckNext,
+ BlockNumber ));
+ }
+ else {
+ //
+ // Process the expected ACK
+ //
+ if ( pContext->bEofSent ) {
+ bCloseContext = TRUE;
+ }
+ else {
+ //
+ // Set the next expected ACK
+ //
+ pContext->AckNext += 1;
+
+ //
+ // Send the next packet of data
+ //
+ Status = TftpSendNextBlock ( pTftpServer, pContext );
+ }
+ }
+ break;
+ }
+ }
+
+ //
+ // Determine if the context should be closed
+ //
+ if ( bCloseContext ) {
+ ContextRemove ( pTftpServer, pContext );
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Build and send an error packet
+
+ @param [in] pTftpServer The TFTP server control structure address.
+ @param [in] pContext The context structure address.
+ @param [in] Error Error number for the packet
+ @param [in] pError Zero terminated error string address
+
+ @retval EFI_SUCCESS Message processed successfully
+
+**/
+EFI_STATUS
+TftpSendError (
+ IN TSDT_TFTP_SERVER * pTftpServer,
+ IN TSDT_CONNECTION_CONTEXT * pContext,
+ IN UINT16 Error,
+ IN UINT8 * pError
+ )
+{
+ UINT8 Character;
+ UINT8 * pBuffer;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Build the error packet
+ //
+ pBuffer = &pContext->TxBuffer[0];
+ pBuffer[0] = 0;
+ pBuffer[1] = TFTP_OP_ERROR;
+ pBuffer[2] = (UINT8)( Error >> 8 );
+ pBuffer[3] = (UINT8)Error;
+
+ //
+ // Copy the zero terminated string into the buffer
+ //
+ pBuffer += 4;
+ do {
+ Character = *pError++;
+ *pBuffer++ = Character;
+ } while ( 0 != Character );
+
+ //
+ // Send the error message
+ //
+ pContext->TxBytes = pBuffer - &pContext->TxBuffer[0];
+ Status = TftpTxPacket ( pTftpServer, pContext );
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Send the next block of file system data
+
+ @param [in] pTftpServer The TFTP server control structure address.
+ @param [in] pContext The context structure address.
+
+ @retval EFI_SUCCESS Message processed successfully
+
+**/
+EFI_STATUS
+TftpSendNextBlock (
+ IN TSDT_TFTP_SERVER * pTftpServer,
+ IN TSDT_CONNECTION_CONTEXT * pContext
+ )
+{
+ ssize_t LengthInBytes;
+ UINT8 * pBuffer;
+ EFI_STATUS Status;
+
+ //
+ // Determine how much data needs to be sent
+ //
+ LengthInBytes = pContext->BlockSize;
+ if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE )
+ || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) {
+ LengthInBytes = (ssize_t)pContext->LengthInBytes;
+ pContext->bEofSent = TRUE;
+ }
+
+ //
+ // Set the TFTP opcode and block number
+ //
+ pBuffer = &pContext->TxBuffer[0];
+ *pBuffer++ = 0;
+ *pBuffer++ = TFTP_OP_DATA;
+ *pBuffer++ = (UINT8)( pContext->AckNext >> 8 );
+ *pBuffer++ = (UINT8)pContext->AckNext;
+
+ //
+ // Copy the file data into the transmit buffer
+ //
+ pContext->TxBytes = 2 + 2 + LengthInBytes;
+ if ( 0 < LengthInBytes ) {
+ CopyMem ( &pBuffer,
+ pContext->pBuffer,
+ LengthInBytes );
+ }
+
+ //
+ // Send the next block
+ //
+ Status = TftpTxPacket ( pTftpServer, pContext );
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Create the port for the TFTP server
+
+ This routine polls the network layer to create the TFTP port for the
+ TFTP server. More than one attempt may be necessary since it may take
+ some time to get the IP address and initialize the upper layers of
+ the network stack.
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+**/
+VOID
+TftpServerTimer (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ UINT16 TftpPort;
+ int SocketStatus;
+ EFI_STATUS Status;
+
+ DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" ));
+
+ //
+ // Open the TFTP port on the server
+ //
+ do {
+ do {
+ //
+ // Wait for a while
+ //
+ Status = gBS->CheckEvent ( pTftpServer->TimerEvent );
+ } while ( EFI_SUCCESS != Status );
+
+ //
+ // Attempt to create the socket for the TFTP server
+ //
+ pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP;
+ pTftpServer->TftpPort.revents = 0;
+ pTftpServer->TftpPort.fd = socket ( AF_INET,
+ SOCK_DGRAM,
+ IPPROTO_UDP );
+ if ( -1 != pTftpServer->TftpPort.fd )
+ {
+ //
+ // Set the socket address
+ //
+ ZeroMem ( &pTftpServer->TftpServerAddress,
+ sizeof ( pTftpServer->TftpServerAddress ));
+ TftpPort = 69;
+ DEBUG (( DEBUG_TFTP_PORT,
+ "TFTP Port: %d\r\n",
+ TftpPort ));
+ pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress );
+ pTftpServer->TftpServerAddress.sin_family = AF_INET;
+ pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY;
+ pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort );
+
+ //
+ // Bind the socket to the TFTP port
+ //
+ SocketStatus = bind ( pTftpServer->TftpPort.fd,
+ (struct sockaddr *) &pTftpServer->TftpServerAddress,
+ pTftpServer->TftpServerAddress.sin_len );
+ if ( -1 != SocketStatus ) {
+ DEBUG (( DEBUG_TFTP_PORT,
+ "0x%08x: Socket bound to port %d\r\n",
+ pTftpServer->TftpPort.fd,
+ TftpPort ));
+ }
+
+ //
+ // Release the socket if necessary
+ //
+ if ( -1 == SocketStatus ) {
+ close ( pTftpServer->TftpPort.fd );
+ pTftpServer->TftpPort.fd = -1;
+ }
+ }
+
+ //
+ // Wait until the socket is open
+ //
+ }while ( -1 == pTftpServer->TftpPort.fd );
+
+ DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" ));
+}
+
+
+/**
+ Start the TFTP server port creation timer
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+ @retval EFI_SUCCESS The timer was successfully started.
+ @retval EFI_ALREADY_STARTED The timer is already running.
+ @retval Other The timer failed to start.
+
+**/
+EFI_STATUS
+TftpServerTimerStart (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TriggerTime;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume the timer is already running
+ //
+ Status = EFI_ALREADY_STARTED;
+ if ( !pTftpServer->bTimerRunning ) {
+ //
+ // Compute the poll interval
+ //
+ TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );
+ Status = gBS->SetTimer ( pTftpServer->TimerEvent,
+ TimerPeriodic,
+ TriggerTime );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));
+
+ //
+ // Mark the timer running
+ //
+ pTftpServer->bTimerRunning = TRUE;
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,
+ "ERROR - Failed to start TFTP port timer, Status: %r\r\n",
+ Status ));
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Stop the TFTP server port creation timer
+
+ @param [in] pTftpServer The TFTP server control structure address.
+
+ @retval EFI_SUCCESS The TFTP port timer is stopped
+ @retval Other Failed to stop the TFTP port timer
+
+**/
+EFI_STATUS
+TftpServerTimerStop (
+ IN TSDT_TFTP_SERVER * pTftpServer
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume the timer is stopped
+ //
+ Status = EFI_SUCCESS;
+ if ( pTftpServer->bTimerRunning ) {
+ //
+ // Stop the port creation polling
+ //
+ Status = gBS->SetTimer ( pTftpServer->TimerEvent,
+ TimerCancel,
+ 0 );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" ));
+
+ //
+ // Mark the timer stopped
+ //
+ pTftpServer->bTimerRunning = FALSE;
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,
+ "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n",
+ Status ));
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+/**
+ Send the next TFTP packet
+
+ @param [in] pTftpServer The TFTP server control structure address.
+ @param [in] pContext The context structure address.
+
+ @retval EFI_SUCCESS Message processed successfully
+
+**/
+EFI_STATUS
+TftpTxPacket (
+ IN TSDT_TFTP_SERVER * pTftpServer,
+ IN TSDT_CONNECTION_CONTEXT * pContext
+ )
+{
+ ssize_t LengthInBytes;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Send the TFTP packet
+ //
+ DEBUG (( DEBUG_TX,
+ "0x%08x: pContext sending 0x%08x bytes\r\n",
+ pContext,
+ pContext->TxBytes ));
+ LengthInBytes = sendto ( pTftpServer->TftpPort.fd,
+ &pContext->TxBuffer[0],
+ pContext->TxBytes,
+ 0,
+ (struct sockaddr *)&pContext->RemoteAddress,
+ pContext->RemoteAddress.sin_len );
+ if ( -1 == LengthInBytes ) {
+ DEBUG (( DEBUG_ERROR | DEBUG_TX,
+ "ERROR - Transmit failure, errno: 0x%08x\r\n",
+ errno ));
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Entry point for the TFTP server application.
+
+ @param [in] Argc The number of arguments
+ @param [in] Argv The argument value array
+
+ @retval 0 The application exited normally.
+ @retval Other An error occurred.
+**/
+int
+main (
+ IN int Argc,
+ IN char **Argv
+ )
+{
+ TSDT_TFTP_SERVER * pTftpServer;
+ EFI_STATUS Status;
+
+ //
+ // Create a timer event to start TFTP port
+ //
+ pTftpServer = &mTftpServer;
+ Status = gBS->CreateEvent ( EVT_TIMER,
+ TPL_TFTP_SERVER,
+ NULL,
+ NULL,
+ &pTftpServer->TimerEvent );
+ if ( !EFI_ERROR ( Status )) {
+ Status = TftpServerTimerStart ( pTftpServer );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Run the TFTP server forever
+ //
+ for ( ; ; ) {
+ //
+ // Poll the network layer to create the TFTP port
+ // for the tftp server. More than one attempt may
+ // be necessary since it may take some time to get
+ // the IP address and initialize the upper layers
+ // of the network stack.
+ //
+ TftpServerTimer ( pTftpServer );
+
+ //
+ // Poll the socket for activity
+ //
+ do {
+ SocketPoll ( pTftpServer );
+ } while ( -1 != pTftpServer->TftpPort.fd );
+
+//
+// TODO: Remove the following test code
+// Exit when the network connection is broken
+//
+break;
+ }
+
+ //
+ // Done with the timer event
+ //
+ TftpServerTimerStop ( pTftpServer );
+ Status = gBS->CloseEvent ( pTftpServer->TimerEvent );
+ }
+ }
+
+ //
+ // Return the final status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
diff --git a/AppPkg/Applications/Sockets/WebServer/ACPI.c b/AppPkg/Applications/Sockets/WebServer/ACPI.c index a7da233e22..bcb56d0ded 100644 --- a/AppPkg/Applications/Sockets/WebServer/ACPI.c +++ b/AppPkg/Applications/Sockets/WebServer/ACPI.c @@ -1,1918 +1,1918 @@ -/*++ - This file contains an 'Intel UEFI Application' and is - licensed for Intel CPUs and chipsets under the terms of your - license agreement with Intel or your vendor. This file may - be modified by the user, subject to additional terms of the - license agreement ---*/ -/*++ - -Copyright (c) 2011 Intel Corporation. All rights reserved -This software and associated documentation (if any) is furnished -under a license and may only be used or copied in accordance -with the terms of the license. Except as permitted by such -license, no part of this software or documentation may be -reproduced, stored in a retrieval system, or transmitted in any -form or by any means without the express written consent of -Intel Corporation. - ---*/ - -/** @file - Display the runtime services table - -**/ - -#include <WebServer.h> -#include <Guid/Acpi.h> -#include <IndustryStandard/Acpi10.h> -#include <IndustryStandard/Acpi30.h> - -#pragma warning ( disable : 4305 ) - -// -// Ensure proper structure formats -// -#pragma pack(1) - -typedef struct { - UINT8 AddressSpaceId; - UINT8 RegisterBitWidth; - UINT8 RegisterBitOffset; - UINT8 AccessSize; - UINT64 Address; -} GENERIC_ADDRESS; - - -typedef struct { - UINT32 Signature; // 0 - UINT32 Length; // 4 - UINT8 Revision; // 8 - UINT8 Checksum; // 9 - UINT8 OemId[6]; // 10 - UINT8 OemTableId[8]; // 16 - UINT32 OemRevision; // 24 - UINT32 CreatorId; // 28 - UINT32 CreatorRevision; // 32 - UINT8 DefinitionBlock[1]; // 36 -} ACPI_DSDT; - - -typedef struct { - UINT32 Signature; // 0 - UINT32 Length; // 4 - UINT8 Revision; // 8 - UINT8 Checksum; // 9 - UINT8 OemId[6]; // 10 - UINT8 OemTableId[8]; // 16 - UINT32 OemRevision; // 24 - UINT32 CreatorId; // 28 - UINT32 CreatorRevision; // 32 - UINT32 FirmwareCtrl; // 36 - UINT32 DSDT; // 40 - UINT8 Reserved; // 44 - UINT8 PreferredPmProfile; // 45 - UINT16 SciInt; // 46 - UINT32 SmiCmd; // 48 - UINT8 AcpiEnable; // 52 - UINT8 AcpiDisable; // 53 - UINT8 S4BiosReq; // 54 - UINT8 PStateCnt; // 55 - UINT32 Pm1aEvtBlk; // 56 - UINT32 Pm1bEvtBlk; // 60 - UINT32 Pm1aCntBlk; // 64 - UINT32 Pm1bCntBlk; // 68 - UINT32 Pm2CntBlk; // 72 - UINT32 PmTmrBlk; // 76 - UINT32 Gpe0Blk; // 80 - UINT32 Gpe1Blk; // 84 - UINT8 Pm1EvtLen; // 88 - UINT8 Pm1CntLen; // 89 - UINT8 PM2CntLen; // 90 - UINT8 PmTmrLen; // 91 - UINT8 Gpe0BlkLen; // 92 - UINT8 Gpe1BlkLen; // 93 - UINT8 Gpe1Base; // 94 - UINT8 CstCnt; // 95 - UINT16 PLvl2Lat; // 96 - UINT16 PLvl3Lat; // 98 - UINT16 FlushSize; // 100 - UINT16 FlushStride; // 102 - UINT8 DutyOffset; // 104 - UINT8 DutyWidth; // 105 - UINT8 DayAlrm; // 106 - UINT8 MonAlrm; // 107 - UINT8 Century; // 108 - UINT16 IapcBootArch; // 109 - UINT8 Reserved2; // 111 - UINT32 Flags; // 112 - UINT32 ResetReg [3]; // 116 - UINT8 ResetValue; // 128 - UINT8 Reserved3 [3]; // 129 - UINT64 XFirmwareCtrl; // 132 - UINT64 XDsdt; // 140 - UINT32 XPm1aEvtBlk [3]; // 148 - UINT32 XPm1bEvtBlk [3]; // 160 - UINT32 XPm1aCntBlk [3]; // 172 - UINT32 XPm1bCntBlk [3]; // 184 - UINT32 XPm2CntBlk [3]; // 196 - UINT32 XPmTmrBlk [3]; // 208 - UINT32 XGpe0Blk [3]; // 220 - UINT32 XGpe1Blk [3]; // 232 -} ACPI_FADT; - - -typedef struct { - UINT32 Signature; - UINT32 Length; - UINT8 Revision; - UINT8 Checksum; - UINT8 OemId[6]; - UINT8 OemTableId[8]; - UINT32 OemRevision; - UINT32 CreatorId; - UINT32 CreatorRevision; - UINT32 Entry[1]; -} ACPI_RSDT; - - -#pragma pack() - - -typedef struct { - UINT32 Signature; - CONST CHAR8 * pTableName; - CONST CHAR16 * pWebPage; -} TABLE_SIGNATURE; - - -CONST TABLE_SIGNATURE mTableId [] = { - { DSDT_SIGNATURE, "DSDT", PAGE_ACPI_DSDT }, - { FADT_SIGNATURE, "FADT", PAGE_ACPI_FADT } -}; - - -/** - Locate the RSDT table - - @returns Table address or NULL if not found - -**/ -CONST ACPI_RSDT * -LocateRsdt ( - VOID - ) -{ - CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b; - CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30; - CONST ACPI_RSDT * pRsdt; - EFI_STATUS Status; - - // - // Use for/break instead of goto - // - pRsdt = NULL; - for ( ; ; ) { - // - // Locate the RSDT - // - Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 ); - if ( !EFI_ERROR ( Status )) { - pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress; - } - else { - Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b ); - if ( EFI_ERROR ( Status )) { - break; - } - pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress; - } - break; - } - - // - // The entry was not found - // - return pRsdt; -} - - -/** - Locate the specified table - - @param [in] Signature Table signature - - @returns Table address or NULL if not found - -**/ -CONST VOID * -LocateTable ( - IN UINT32 Signature - ) -{ - CONST UINT32 * pEnd; - CONST UINT32 * pEntry; - CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b; - CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30; - CONST ACPI_RSDT * pRsdt; - CONST UINT32 * pSignature; - EFI_STATUS Status; - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Locate the RSDT - // - Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 ); - if ( !EFI_ERROR ( Status )) { - pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress; - } - else { - Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b ); - if ( EFI_ERROR ( Status )) { - break; - } - pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress; - } - - // - // Walk the list of entries - // - pEntry = &pRsdt->Entry [ 0 ]; - pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ]; - while ( pEnd > pEntry ) { - // - // The entry is actually a 32-bit physical table address - // The first entry in the table is the 32-bit table signature - // - pSignature = (UINT32 *)*pEntry; - if ( *pSignature == Signature ) { - return (CONST VOID *) *pEntry; - } - - // - // Set the next entry - // - pEntry++; - } - break; - } - - // - // The entry was not found - // - return NULL; -} - - -/** - Display a row containing a hex value - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [in] pName Address of a zero terminated name string - @param [in] Length Length in bytes - @param [in] pChar Address of the first character - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -RowAnsiArray ( - IN int SocketFD, - IN WSDT_PORT * pPort, - IN CONST CHAR8 * pName, - IN UINTN Length, - IN CONST CHAR8 * pChar - ) -{ - CONST CHAR8 * pData; - CONST CHAR8 * pEnd; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Start the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<tr><td>" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - pName ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</td><td><code>" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the characters - // - pData = pChar; - pEnd = &pChar [ Length ]; - while ( pEnd > pData ) { - Status = HttpSendCharacter ( SocketFD, - pPort, - *pData++, - " " ); - if ( EFI_ERROR ( Status )) { - break; - } - } - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the byte values - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<br/>0x" ); - if ( EFI_ERROR ( Status )) { - break; - } - pData = pChar; - while ( pEnd > pData ) { - Status = HttpSendHexBits ( SocketFD, - pPort, - 8, - *pData++ ); - if ( EFI_ERROR ( Status )) { - break; - } - if ( pEnd > pData ) { - Status = HttpSendAnsiString ( SocketFD, - pPort, - " 0x" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - } - - // - // Terminate the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</code></td></tr>\r\n" ); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Format a row with a list of bytes - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [in] pName Zero terminated name string - @param [in] ByteCount The number of bytes to display - @param [in] pData Address of the byte array - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -RowBytes ( - IN int SocketFD, - IN WSDT_PORT * pPort, - IN CHAR8 * pName, - IN UINTN ByteCount, - IN CONST UINT8 * pData - ) -{ - CONST UINT8 * pEnd; - EFI_STATUS Status; - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Start the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<tr><td>" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the field name - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - pName ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the field value - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</td><td><code>0x" ); - if ( EFI_ERROR ( Status )) { - break; - } - pEnd = &pData [ ByteCount ]; - while ( pEnd > pData ) { - Status = HttpSendHexBits ( SocketFD, - pPort, - 8, - *pData++ ); - if ( EFI_ERROR ( Status )) { - break; - } - if ( pEnd > pData ) { - Status = HttpSendAnsiString ( SocketFD, - pPort, - " 0x" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - } - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Terminate the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</code></td></tr>\r\n" ); - break; - } - - // - // Return the operation status - // - return Status; -} - - -/** - Format a row with a list of bytes - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [in] pName Zero terminated name string - @param [in] ByteCount The number of bytes to display - @param [in] pData Address of the byte array - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -RowDump ( - IN int SocketFD, - IN WSDT_PORT * pPort, - IN CHAR8 * pName, - IN UINTN ByteCount, - IN CONST UINT8 * pData - ) -{ - EFI_STATUS Status; - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Start the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<tr><td>" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the field name - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - pName ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Start the field value - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</td><td>" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Dump the buffer - // - Status = HttpSendDump ( SocketFD, - pPort, - ByteCount, - pData ); - - // - // Terminate the field value and row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</td></tr>\r\n" ); - break; - } - - // - // Return the operation status - // - return Status; -} - - -/** - Format a row with a general address - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [in] pName Zero terminated name string - @param [in] pAddr Address of the general address buffer - @param [in] pWebPage Zero terminated web page address - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -RowGenericAddress ( - IN int SocketFD, - IN WSDT_PORT * pPort, - IN CHAR8 * pName, - IN CONST UINT32 * pAddr, - IN CONST CHAR16 * pWebPage - ) -{ - CONST GENERIC_ADDRESS * pGenericAddress; - EFI_STATUS Status; - - // - // Use for/break instead of goto - // - for ( ; ; ) { - // - // Start the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<tr><td>" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the field name - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - pName ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the field value - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</td><td><code>" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Determine the type of address - // - pGenericAddress = (CONST GENERIC_ADDRESS *)pAddr; - if ( 0 == pGenericAddress->AddressSpaceId ) { - Status = HttpSendAnsiString ( SocketFD, pPort, "System Memory" ); - } - else if ( 1 == pGenericAddress->AddressSpaceId ) { - Status = HttpSendAnsiString ( SocketFD, pPort, "I/O Space" ); - } - else if ( 2 == pGenericAddress->AddressSpaceId ) { - Status = HttpSendAnsiString ( SocketFD, pPort, "PCI Configuration Space" ); - } - else if ( 3 == pGenericAddress->AddressSpaceId ) { - Status = HttpSendAnsiString ( SocketFD, pPort, "Embedded Controller" ); - } - else if ( 4 == pGenericAddress->AddressSpaceId ) { - Status = HttpSendAnsiString ( SocketFD, pPort, "SMBus" ); - } - else if ( 0x7f == pGenericAddress->AddressSpaceId ) { - Status = HttpSendAnsiString ( SocketFD, pPort, "Functional Fixed Hardware" ); - } - else if (( 0xc0 <= pGenericAddress->AddressSpaceId ) - && ( 0xff >= pGenericAddress->AddressSpaceId )) { - Status = HttpSendAnsiString ( SocketFD, pPort, "OEM Defined" ); - } - else { - Status = HttpSendAnsiString ( SocketFD, pPort, "Reserved" ); - } - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<br/>Register Bit Width: " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendValue ( SocketFD, - pPort, - pGenericAddress->RegisterBitWidth ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<br/>Register Bit Offset: " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendHexValue ( SocketFD, - pPort, - pGenericAddress->RegisterBitOffset ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<br/>Access Size: " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendValue ( SocketFD, - pPort, - pGenericAddress->AccessSize ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<br/>Address: " ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Add the web-page link if necessary - // - if ( NULL != pWebPage ) { - Status = HttpSendAnsiString ( SocketFD, - pPort, - "<a target=\"_blank\" href=\"" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendUnicodeString ( SocketFD, - pPort, - pWebPage ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "\">" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Display the address - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "0x" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendHexBits ( SocketFD, - pPort, - 64, - pGenericAddress->Address ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Finish the web-page link if necessary - // - if ( NULL != pWebPage ) { - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</a>" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Terminate the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "</code></td></tr>\r\n" ); - break; - } - - // - // Return the operation status - // - return Status; -} - - -/** - Translate a table address into a web page - - @param [in] pSignature Address of the table signature - @param [out] ppTableName Address to receive the table name address - - @returns Zero terminated web page address or NULL if not found - -**/ -CONST CHAR16 * -SignatureLookup ( - IN UINT32 * pSignature, - OUT CONST CHAR8 ** ppTableName - ) -{ - CONST TABLE_SIGNATURE * pTableId; - CONST TABLE_SIGNATURE * pEnd; - UINT32 Signature; - - // - // Walk the list of tables - // - Signature = *pSignature; - pTableId = &mTableId [ 0 ]; - pEnd = &pTableId [ sizeof ( mTableId ) / sizeof ( mTableId [ 0 ])]; - while ( pEnd > pTableId ) { - // - // Attempt to locate the table signature - // - if ( pTableId->Signature == Signature ) { - // - // The signature was found - // Return the web page - // - *ppTableName = pTableId->pTableName; - return pTableId->pWebPage; - } - - // - // Set the next table - // - pTableId += 1; - } - - // - // The table was not found - // - *ppTableName = (CONST CHAR8 *)pSignature; - return NULL; -} - - -/** - Respond with the ACPI DSDT table - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [out] pbDone Address to receive the request completion status - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -AcpiDsdtPage ( - IN int SocketFD, - IN WSDT_PORT * pPort, - OUT BOOLEAN * pbDone - ) -{ - CONST ACPI_DSDT * pDsdt; - CONST ACPI_FADT * pFadt; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Send the DADT page - // - for ( ; ; ) { - // - // Locate the DADT - // - pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE ); - if ( NULL == pFadt ) { - Status = EFI_NOT_FOUND; - break; - } - pDsdt = (VOID *)pFadt->XDsdt; - - // - // Send the page and table header - // - Status = TableHeader ( SocketFD, pPort, L"DSDT - Differentiated System Description Table", pDsdt ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the DSDT header - // - Status = RowAnsiArray ( SocketFD, - pPort, - "Signature", - sizeof ( pDsdt->Signature ), - (CHAR8 *)&pDsdt->Signature ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Length", - pDsdt->Length ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Revision", - pDsdt->Revision ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Checksum", - pDsdt->Checksum, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OEMID", - sizeof ( pDsdt->OemId ), - &pDsdt->OemId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OEM Table ID", - sizeof ( pDsdt->OemTableId ), - &pDsdt->OemTableId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowRevision ( SocketFD, - pPort, - "OEM Revision", - pDsdt->OemRevision ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "Creator ID", - sizeof ( pDsdt->CreatorId ), - (CHAR8 *)&pDsdt->CreatorId ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowRevision ( SocketFD, - pPort, - "Creator Revision", - pDsdt->CreatorRevision ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the data from the DSDT - // - Status = RowDump ( SocketFD, - pPort, - "Definition Block", - pDsdt->Length - sizeof ( *pDsdt ) + 1, - &pDsdt->DefinitionBlock[0]); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Build the table trailer - // - Status = TableTrailer ( SocketFD, - pPort, - pbDone ); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Respond with the ACPI FADT table - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [out] pbDone Address to receive the request completion status - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -AcpiFadtPage ( - IN int SocketFD, - IN WSDT_PORT * pPort, - OUT BOOLEAN * pbDone - ) -{ - CONST ACPI_FADT * pFadt; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Send the FADT page - // - for ( ; ; ) { - // - // Locate the FADT - // - pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE ); - if ( NULL == pFadt ) { - Status = EFI_NOT_FOUND; - break; - } - - // - // Send the page and table header - // - Status = TableHeader ( SocketFD, pPort, L"FADT - Fixed ACPI Description Table", pFadt ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the FSDT header - // - Status = RowAnsiArray ( SocketFD, - pPort, - "Signature", - sizeof ( pFadt->Signature ), - (CHAR8 *)&pFadt->Signature ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Length", - pFadt->Length ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Revision", - pFadt->Revision ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Checksum", - pFadt->Checksum, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OEMID", - sizeof ( pFadt->OemId ), - &pFadt->OemId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OEM Table ID", - sizeof ( pFadt->OemTableId ), - &pFadt->OemTableId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowRevision ( SocketFD, - pPort, - "OEM Revision", - pFadt->OemRevision ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "Creator ID", - sizeof ( pFadt->CreatorId ), - (CHAR8 *)&pFadt->CreatorId ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowRevision ( SocketFD, - pPort, - "Creator Revision", - pFadt->CreatorRevision ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the data from the FADT - // - Status = RowPointer ( SocketFD, - pPort, - "FIRMWARE_CTRL", - (CONST VOID *)pFadt->FirmwareCtrl, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowPointer ( SocketFD, - pPort, - "DSDT", - (CONST VOID *)pFadt->DSDT, - ( pFadt->DSDT == pFadt->XDsdt ) ? PAGE_ACPI_DSDT : NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Reserved", - pFadt->Reserved, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Preferred_PM_Profile", - pFadt->PreferredPmProfile, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "SCI_INT", - pFadt->SciInt, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "SMI_CMD", - pFadt->SmiCmd, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "ACPI_ENABLE", - pFadt->AcpiEnable, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "ACPI_DISABLE", - pFadt->AcpiDisable, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "S4BIOS_REQ", - pFadt->S4BiosReq, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PSTATE_CNT", - pFadt->PStateCnt, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PM1a_EVT_BLK", - pFadt->Pm1aEvtBlk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PM1b_EVT_BLK", - pFadt->Pm1bEvtBlk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PM1a_CNT_BLK", - pFadt->Pm1aCntBlk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PM1b_CNT_BLK", - pFadt->Pm1bCntBlk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PM2_CNT_BLK", - pFadt->Pm2CntBlk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "PM_TMR_BLK", - pFadt->PmTmrBlk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - - Status = RowHexValue ( SocketFD, - pPort, - "GPE0_BLK", - pFadt->Gpe0Blk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "GPE1_BLK", - pFadt->Gpe1Blk, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "PM1_EVT_LEN", - pFadt->Pm1EvtLen ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "PM1_CNT_LEN", - pFadt->Pm1CntLen ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "PM2_CNT_LEN", - pFadt->PM2CntLen ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "PM_TMR_LEN", - pFadt->PmTmrLen ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "GPE0_BLK_LEN", - pFadt->Gpe0BlkLen ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "GPE1_BLK_LEN", - pFadt->Gpe1BlkLen ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "GPE1_BASE", - pFadt->Gpe1Base, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "CST_CNT", - pFadt->CstCnt ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "P_LVL2_LAT", - pFadt->PLvl2Lat, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "P_LVL3_LAT", - pFadt->PLvl3Lat, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "FLUSH_SIZE", - pFadt->FlushSize ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "FLUSH_Stride", - pFadt->FlushStride ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "DUTY_OFFSET", - pFadt->DutyOffset, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "DUTY_WIDTH", - pFadt->DutyWidth, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "DAY_ALRM", - pFadt->DayAlrm, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "MON_ALRM", - pFadt->MonAlrm, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "CENTURY", - pFadt->Century, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "IAPC_BOOT_ARCH", - pFadt->IapcBootArch, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Reserved", - pFadt->Reserved2, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Flags", - pFadt->Flags, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "RESET_REG", - &pFadt->ResetReg[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "RESET_VALUE", - pFadt->ResetValue, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Reserved", - pFadt->Reserved3[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Reserved", - pFadt->Reserved3[1], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Reserved", - pFadt->Reserved3[2], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "X_FIRMWARE_CTRL", - pFadt->XFirmwareCtrl, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "X_DSDT", - pFadt->XDsdt, - PAGE_ACPI_DSDT ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_PM1a_EVT_BLK", - &pFadt->XPm1aEvtBlk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_PM1b_EVT_BLK", - &pFadt->XPm1bEvtBlk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_PM1a_CNT_BLK", - &pFadt->XPm1aCntBlk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_PM1b_CNT_BLK", - &pFadt->XPm1bCntBlk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_PM2_CNT_BLK", - &pFadt->XPm2CntBlk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_PM_TMR_BLK", - &pFadt->XPmTmrBlk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_GPE0_BLK", - &pFadt->XGpe0Blk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowGenericAddress ( SocketFD, - pPort, - "X_GPE1_BLK", - &pFadt->XGpe1Blk[0], - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Build the table trailer - // - Status = TableTrailer ( SocketFD, - pPort, - pbDone ); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Respond with the ACPI RSDP 1.0b table - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [out] pbDone Address to receive the request completion status - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -AcpiRsdp10Page ( - IN int SocketFD, - IN WSDT_PORT * pPort, - OUT BOOLEAN * pbDone - ) -{ - CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Send the RSDP page - // - for ( ; ; ) { - // - // Locate the RSDP - // - Status = EfiGetSystemConfigurationTable ( &gEfiAcpi10TableGuid, (VOID **) &pRsdp10b ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Send the page and table header - // - Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 1.0b Root System Description Pointer", pRsdp10b ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the RSDP - // - Status = RowAnsiArray ( SocketFD, - pPort, - "Signature", - sizeof ( pRsdp10b->Signature ), - (CHAR8 *)&pRsdp10b->Signature ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Checksum", - pRsdp10b->Checksum, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OemId", - sizeof ( pRsdp10b->OemId ), - &pRsdp10b->OemId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Reserved", - pRsdp10b->Reserved, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowPointer ( SocketFD, - pPort, - "RsdtAddress", - (VOID *)pRsdp10b->RsdtAddress, - PAGE_ACPI_RSDT ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Build the table trailer - // - Status = TableTrailer ( SocketFD, - pPort, - pbDone ); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Respond with the ACPI RSDP 3.0 table - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [out] pbDone Address to receive the request completion status - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -AcpiRsdp30Page ( - IN int SocketFD, - IN WSDT_PORT * pPort, - OUT BOOLEAN * pbDone - ) -{ - CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30; - EFI_STATUS Status; - - DBG_ENTER ( ); - - // - // Send the RSDP page - // - for ( ; ; ) { - // - // Locate the RSDP - // - Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **) &pRsdp30 ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Send the page and table header - // - Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 3.0 Root System Description Pointer", pRsdp30 ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the RSDP - // - Status = RowAnsiArray ( SocketFD, - pPort, - "Signature", - sizeof ( pRsdp30->Signature ), - (CHAR8 *)&pRsdp30->Signature ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Checksum", - pRsdp30->Checksum, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OemId", - sizeof ( pRsdp30->OemId ), - &pRsdp30->OemId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Revision", - pRsdp30->Revision, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowPointer ( SocketFD, - pPort, - "RsdtAddress", - (VOID *)pRsdp30->RsdtAddress, - PAGE_ACPI_RSDT ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Length", - pRsdp30->Length ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowPointer ( SocketFD, - pPort, - "XsdtAddress", - (VOID *)pRsdp30->XsdtAddress, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "ExtendedChecksum", - pRsdp30->ExtendedChecksum, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowBytes ( SocketFD, - pPort, - "Reserved", - sizeof ( pRsdp30->Reserved ), - &pRsdp30->Reserved [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Build the table trailer - // - Status = TableTrailer ( SocketFD, - pPort, - pbDone ); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - -/** - Respond with the ACPI RSDT table - - @param [in] SocketFD The socket's file descriptor to add to the list. - @param [in] pPort The WSDT_PORT structure address - @param [out] pbDone Address to receive the request completion status - - @retval EFI_SUCCESS The request was successfully processed - -**/ -EFI_STATUS -AcpiRsdtPage ( - IN int SocketFD, - IN WSDT_PORT * pPort, - OUT BOOLEAN * pbDone - ) -{ - CONST UINT32 * pEnd; - CONST UINT32 * pEntry; - CONST ACPI_RSDT * pRsdt; - CONST CHAR8 * pTableName; - CONST CHAR16 * pWebPage; - EFI_STATUS Status; - UINT32 TableName [ 2 ]; - - DBG_ENTER ( ); - - // - // Send the RSDT page - // - for ( ; ; ) { - // - // Locate the RSDT - // - pRsdt = LocateRsdt ( ); - if ( NULL == pRsdt ) { - Status = EFI_NOT_FOUND; - break; - } - - // - // Send the page and table header - // - Status = TableHeader ( SocketFD, pPort, L"RSDT - ACPI Root System Description Table", pRsdt ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Display the RSDT - // - Status = RowAnsiArray ( SocketFD, - pPort, - "Signature", - sizeof ( pRsdt->Signature ), - (CHAR8 *)&pRsdt->Signature ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Length", - pRsdt->Length ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowDecimalValue ( SocketFD, - pPort, - "Revision", - pRsdt->Revision ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowHexValue ( SocketFD, - pPort, - "Checksum", - pRsdt->Checksum, - NULL ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OEMID", - sizeof ( pRsdt->OemId ), - &pRsdt->OemId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "OEM Table ID", - sizeof ( pRsdt->OemTableId ), - &pRsdt->OemTableId [ 0 ]); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowRevision ( SocketFD, - pPort, - "OEM Revision", - pRsdt->OemRevision ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowAnsiArray ( SocketFD, - pPort, - "Creator ID", - sizeof ( pRsdt->CreatorId ), - (CHAR8 *)&pRsdt->CreatorId ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = RowRevision ( SocketFD, - pPort, - "Creator Revision", - pRsdt->CreatorRevision ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Walk the list of entries - // - pEntry = &pRsdt->Entry [ 0 ]; - pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ]; - TableName [ 1 ] = 0; - while ( pEnd > pEntry ) { - // - // The entry is actually a 32-bit physical table address - // The first entry in the table is the 32-bit table signature - // - TableName [ 0 ] = *(UINT32 *)*pEntry; - pWebPage = SignatureLookup ( &TableName [ 0 ], &pTableName ); - - // - // Display the table address - // - Status = RowPointer ( SocketFD, - pPort, - pTableName, - (VOID *)*pEntry, - pWebPage ); - if ( EFI_ERROR ( Status )) { - break; - } - pEntry++; - } - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Build the table trailer - // - Status = TableTrailer ( SocketFD, - pPort, - pbDone ); - break; - } - - // - // Return the operation status - // - DBG_EXIT_STATUS ( Status ); - return Status; -} - - +/*++
+ This file contains an 'Intel UEFI Application' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+--*/
+/*++
+
+Copyright (c) 2011 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+--*/
+
+/** @file
+ Display the runtime services table
+
+**/
+
+#include <WebServer.h>
+#include <Guid/Acpi.h>
+#include <IndustryStandard/Acpi10.h>
+#include <IndustryStandard/Acpi30.h>
+
+#pragma warning ( disable : 4305 )
+
+//
+// Ensure proper structure formats
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 AddressSpaceId;
+ UINT8 RegisterBitWidth;
+ UINT8 RegisterBitOffset;
+ UINT8 AccessSize;
+ UINT64 Address;
+} GENERIC_ADDRESS;
+
+
+typedef struct {
+ UINT32 Signature; // 0
+ UINT32 Length; // 4
+ UINT8 Revision; // 8
+ UINT8 Checksum; // 9
+ UINT8 OemId[6]; // 10
+ UINT8 OemTableId[8]; // 16
+ UINT32 OemRevision; // 24
+ UINT32 CreatorId; // 28
+ UINT32 CreatorRevision; // 32
+ UINT8 DefinitionBlock[1]; // 36
+} ACPI_DSDT;
+
+
+typedef struct {
+ UINT32 Signature; // 0
+ UINT32 Length; // 4
+ UINT8 Revision; // 8
+ UINT8 Checksum; // 9
+ UINT8 OemId[6]; // 10
+ UINT8 OemTableId[8]; // 16
+ UINT32 OemRevision; // 24
+ UINT32 CreatorId; // 28
+ UINT32 CreatorRevision; // 32
+ UINT32 FirmwareCtrl; // 36
+ UINT32 DSDT; // 40
+ UINT8 Reserved; // 44
+ UINT8 PreferredPmProfile; // 45
+ UINT16 SciInt; // 46
+ UINT32 SmiCmd; // 48
+ UINT8 AcpiEnable; // 52
+ UINT8 AcpiDisable; // 53
+ UINT8 S4BiosReq; // 54
+ UINT8 PStateCnt; // 55
+ UINT32 Pm1aEvtBlk; // 56
+ UINT32 Pm1bEvtBlk; // 60
+ UINT32 Pm1aCntBlk; // 64
+ UINT32 Pm1bCntBlk; // 68
+ UINT32 Pm2CntBlk; // 72
+ UINT32 PmTmrBlk; // 76
+ UINT32 Gpe0Blk; // 80
+ UINT32 Gpe1Blk; // 84
+ UINT8 Pm1EvtLen; // 88
+ UINT8 Pm1CntLen; // 89
+ UINT8 PM2CntLen; // 90
+ UINT8 PmTmrLen; // 91
+ UINT8 Gpe0BlkLen; // 92
+ UINT8 Gpe1BlkLen; // 93
+ UINT8 Gpe1Base; // 94
+ UINT8 CstCnt; // 95
+ UINT16 PLvl2Lat; // 96
+ UINT16 PLvl3Lat; // 98
+ UINT16 FlushSize; // 100
+ UINT16 FlushStride; // 102
+ UINT8 DutyOffset; // 104
+ UINT8 DutyWidth; // 105
+ UINT8 DayAlrm; // 106
+ UINT8 MonAlrm; // 107
+ UINT8 Century; // 108
+ UINT16 IapcBootArch; // 109
+ UINT8 Reserved2; // 111
+ UINT32 Flags; // 112
+ UINT32 ResetReg [3]; // 116
+ UINT8 ResetValue; // 128
+ UINT8 Reserved3 [3]; // 129
+ UINT64 XFirmwareCtrl; // 132
+ UINT64 XDsdt; // 140
+ UINT32 XPm1aEvtBlk [3]; // 148
+ UINT32 XPm1bEvtBlk [3]; // 160
+ UINT32 XPm1aCntBlk [3]; // 172
+ UINT32 XPm1bCntBlk [3]; // 184
+ UINT32 XPm2CntBlk [3]; // 196
+ UINT32 XPmTmrBlk [3]; // 208
+ UINT32 XGpe0Blk [3]; // 220
+ UINT32 XGpe1Blk [3]; // 232
+} ACPI_FADT;
+
+
+typedef struct {
+ UINT32 Signature;
+ UINT32 Length;
+ UINT8 Revision;
+ UINT8 Checksum;
+ UINT8 OemId[6];
+ UINT8 OemTableId[8];
+ UINT32 OemRevision;
+ UINT32 CreatorId;
+ UINT32 CreatorRevision;
+ UINT32 Entry[1];
+} ACPI_RSDT;
+
+
+#pragma pack()
+
+
+typedef struct {
+ UINT32 Signature;
+ CONST CHAR8 * pTableName;
+ CONST CHAR16 * pWebPage;
+} TABLE_SIGNATURE;
+
+
+CONST TABLE_SIGNATURE mTableId [] = {
+ { DSDT_SIGNATURE, "DSDT", PAGE_ACPI_DSDT },
+ { FADT_SIGNATURE, "FADT", PAGE_ACPI_FADT }
+};
+
+
+/**
+ Locate the RSDT table
+
+ @return Table address or NULL if not found
+
+**/
+CONST ACPI_RSDT *
+LocateRsdt (
+ VOID
+ )
+{
+ CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
+ CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
+ CONST ACPI_RSDT * pRsdt;
+ EFI_STATUS Status;
+
+ //
+ // Use for/break instead of goto
+ //
+ pRsdt = NULL;
+ for ( ; ; ) {
+ //
+ // Locate the RSDT
+ //
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );
+ if ( !EFI_ERROR ( Status )) {
+ pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;
+ }
+ else {
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;
+ }
+ break;
+ }
+
+ //
+ // The entry was not found
+ //
+ return pRsdt;
+}
+
+
+/**
+ Locate the specified table
+
+ @param [in] Signature Table signature
+
+ @return Table address or NULL if not found
+
+**/
+CONST VOID *
+LocateTable (
+ IN UINT32 Signature
+ )
+{
+ CONST UINT32 * pEnd;
+ CONST UINT32 * pEntry;
+ CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
+ CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
+ CONST ACPI_RSDT * pRsdt;
+ CONST UINT32 * pSignature;
+ EFI_STATUS Status;
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Locate the RSDT
+ //
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );
+ if ( !EFI_ERROR ( Status )) {
+ pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;
+ }
+ else {
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;
+ }
+
+ //
+ // Walk the list of entries
+ //
+ pEntry = &pRsdt->Entry [ 0 ];
+ pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];
+ while ( pEnd > pEntry ) {
+ //
+ // The entry is actually a 32-bit physical table address
+ // The first entry in the table is the 32-bit table signature
+ //
+ pSignature = (UINT32 *)*pEntry;
+ if ( *pSignature == Signature ) {
+ return (CONST VOID *) *pEntry;
+ }
+
+ //
+ // Set the next entry
+ //
+ pEntry++;
+ }
+ break;
+ }
+
+ //
+ // The entry was not found
+ //
+ return NULL;
+}
+
+
+/**
+ Display a row containing a hex value
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [in] pName Address of a zero terminated name string
+ @param [in] Length Length in bytes
+ @param [in] pChar Address of the first character
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+RowAnsiArray (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ IN CONST CHAR8 * pName,
+ IN UINTN Length,
+ IN CONST CHAR8 * pChar
+ )
+{
+ CONST CHAR8 * pData;
+ CONST CHAR8 * pEnd;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Start the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<tr><td>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ pName );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</td><td><code>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the characters
+ //
+ pData = pChar;
+ pEnd = &pChar [ Length ];
+ while ( pEnd > pData ) {
+ Status = HttpSendCharacter ( SocketFD,
+ pPort,
+ *pData++,
+ " " );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the byte values
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<br/>0x" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ pData = pChar;
+ while ( pEnd > pData ) {
+ Status = HttpSendHexBits ( SocketFD,
+ pPort,
+ 8,
+ *pData++ );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ if ( pEnd > pData ) {
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ " 0x" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+ }
+
+ //
+ // Terminate the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</code></td></tr>\r\n" );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Format a row with a list of bytes
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [in] pName Zero terminated name string
+ @param [in] ByteCount The number of bytes to display
+ @param [in] pData Address of the byte array
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+RowBytes (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ IN CHAR8 * pName,
+ IN UINTN ByteCount,
+ IN CONST UINT8 * pData
+ )
+{
+ CONST UINT8 * pEnd;
+ EFI_STATUS Status;
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Start the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<tr><td>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the field name
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ pName );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the field value
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</td><td><code>0x" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ pEnd = &pData [ ByteCount ];
+ while ( pEnd > pData ) {
+ Status = HttpSendHexBits ( SocketFD,
+ pPort,
+ 8,
+ *pData++ );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ if ( pEnd > pData ) {
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ " 0x" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+ }
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Terminate the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</code></td></tr>\r\n" );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Format a row with a list of bytes
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [in] pName Zero terminated name string
+ @param [in] ByteCount The number of bytes to display
+ @param [in] pData Address of the byte array
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+RowDump (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ IN CHAR8 * pName,
+ IN UINTN ByteCount,
+ IN CONST UINT8 * pData
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Start the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<tr><td>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the field name
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ pName );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Start the field value
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</td><td>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Dump the buffer
+ //
+ Status = HttpSendDump ( SocketFD,
+ pPort,
+ ByteCount,
+ pData );
+
+ //
+ // Terminate the field value and row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</td></tr>\r\n" );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Format a row with a general address
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [in] pName Zero terminated name string
+ @param [in] pAddr Address of the general address buffer
+ @param [in] pWebPage Zero terminated web page address
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+RowGenericAddress (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ IN CHAR8 * pName,
+ IN CONST UINT32 * pAddr,
+ IN CONST CHAR16 * pWebPage
+ )
+{
+ CONST GENERIC_ADDRESS * pGenericAddress;
+ EFI_STATUS Status;
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Start the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<tr><td>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the field name
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ pName );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the field value
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</td><td><code>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Determine the type of address
+ //
+ pGenericAddress = (CONST GENERIC_ADDRESS *)pAddr;
+ if ( 0 == pGenericAddress->AddressSpaceId ) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "System Memory" );
+ }
+ else if ( 1 == pGenericAddress->AddressSpaceId ) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "I/O Space" );
+ }
+ else if ( 2 == pGenericAddress->AddressSpaceId ) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "PCI Configuration Space" );
+ }
+ else if ( 3 == pGenericAddress->AddressSpaceId ) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "Embedded Controller" );
+ }
+ else if ( 4 == pGenericAddress->AddressSpaceId ) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "SMBus" );
+ }
+ else if ( 0x7f == pGenericAddress->AddressSpaceId ) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "Functional Fixed Hardware" );
+ }
+ else if (( 0xc0 <= pGenericAddress->AddressSpaceId )
+ && ( 0xff >= pGenericAddress->AddressSpaceId )) {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "OEM Defined" );
+ }
+ else {
+ Status = HttpSendAnsiString ( SocketFD, pPort, "Reserved" );
+ }
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<br/>Register Bit Width: " );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendValue ( SocketFD,
+ pPort,
+ pGenericAddress->RegisterBitWidth );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<br/>Register Bit Offset: " );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendHexValue ( SocketFD,
+ pPort,
+ pGenericAddress->RegisterBitOffset );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<br/>Access Size: " );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendValue ( SocketFD,
+ pPort,
+ pGenericAddress->AccessSize );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<br/>Address: " );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Add the web-page link if necessary
+ //
+ if ( NULL != pWebPage ) {
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "<a target=\"_blank\" href=\"" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendUnicodeString ( SocketFD,
+ pPort,
+ pWebPage );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "\">" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+
+ //
+ // Display the address
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "0x" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = HttpSendHexBits ( SocketFD,
+ pPort,
+ 64,
+ pGenericAddress->Address );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Finish the web-page link if necessary
+ //
+ if ( NULL != pWebPage ) {
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</a>" );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+
+ //
+ // Terminate the row
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "</code></td></tr>\r\n" );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Translate a table address into a web page
+
+ @param [in] pSignature Address of the table signature
+ @param [out] ppTableName Address to receive the table name address
+
+ @return Zero terminated web page address or NULL if not found
+
+**/
+CONST CHAR16 *
+SignatureLookup (
+ IN UINT32 * pSignature,
+ OUT CONST CHAR8 ** ppTableName
+ )
+{
+ CONST TABLE_SIGNATURE * pTableId;
+ CONST TABLE_SIGNATURE * pEnd;
+ UINT32 Signature;
+
+ //
+ // Walk the list of tables
+ //
+ Signature = *pSignature;
+ pTableId = &mTableId [ 0 ];
+ pEnd = &pTableId [ sizeof ( mTableId ) / sizeof ( mTableId [ 0 ])];
+ while ( pEnd > pTableId ) {
+ //
+ // Attempt to locate the table signature
+ //
+ if ( pTableId->Signature == Signature ) {
+ //
+ // The signature was found
+ // Return the web page
+ //
+ *ppTableName = pTableId->pTableName;
+ return pTableId->pWebPage;
+ }
+
+ //
+ // Set the next table
+ //
+ pTableId += 1;
+ }
+
+ //
+ // The table was not found
+ //
+ *ppTableName = (CONST CHAR8 *)pSignature;
+ return NULL;
+}
+
+
+/**
+ Respond with the ACPI DSDT table
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [out] pbDone Address to receive the request completion status
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+AcpiDsdtPage (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ OUT BOOLEAN * pbDone
+ )
+{
+ CONST ACPI_DSDT * pDsdt;
+ CONST ACPI_FADT * pFadt;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Send the DADT page
+ //
+ for ( ; ; ) {
+ //
+ // Locate the DADT
+ //
+ pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );
+ if ( NULL == pFadt ) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ pDsdt = (VOID *)pFadt->XDsdt;
+
+ //
+ // Send the page and table header
+ //
+ Status = TableHeader ( SocketFD, pPort, L"DSDT - Differentiated System Description Table", pDsdt );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the DSDT header
+ //
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Signature",
+ sizeof ( pDsdt->Signature ),
+ (CHAR8 *)&pDsdt->Signature );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Length",
+ pDsdt->Length );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Revision",
+ pDsdt->Revision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Checksum",
+ pDsdt->Checksum,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OEMID",
+ sizeof ( pDsdt->OemId ),
+ &pDsdt->OemId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OEM Table ID",
+ sizeof ( pDsdt->OemTableId ),
+ &pDsdt->OemTableId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowRevision ( SocketFD,
+ pPort,
+ "OEM Revision",
+ pDsdt->OemRevision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Creator ID",
+ sizeof ( pDsdt->CreatorId ),
+ (CHAR8 *)&pDsdt->CreatorId );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowRevision ( SocketFD,
+ pPort,
+ "Creator Revision",
+ pDsdt->CreatorRevision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the data from the DSDT
+ //
+ Status = RowDump ( SocketFD,
+ pPort,
+ "Definition Block",
+ pDsdt->Length - sizeof ( *pDsdt ) + 1,
+ &pDsdt->DefinitionBlock[0]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Build the table trailer
+ //
+ Status = TableTrailer ( SocketFD,
+ pPort,
+ pbDone );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Respond with the ACPI FADT table
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [out] pbDone Address to receive the request completion status
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+AcpiFadtPage (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ OUT BOOLEAN * pbDone
+ )
+{
+ CONST ACPI_FADT * pFadt;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Send the FADT page
+ //
+ for ( ; ; ) {
+ //
+ // Locate the FADT
+ //
+ pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );
+ if ( NULL == pFadt ) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // Send the page and table header
+ //
+ Status = TableHeader ( SocketFD, pPort, L"FADT - Fixed ACPI Description Table", pFadt );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the FSDT header
+ //
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Signature",
+ sizeof ( pFadt->Signature ),
+ (CHAR8 *)&pFadt->Signature );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Length",
+ pFadt->Length );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Revision",
+ pFadt->Revision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Checksum",
+ pFadt->Checksum,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OEMID",
+ sizeof ( pFadt->OemId ),
+ &pFadt->OemId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OEM Table ID",
+ sizeof ( pFadt->OemTableId ),
+ &pFadt->OemTableId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowRevision ( SocketFD,
+ pPort,
+ "OEM Revision",
+ pFadt->OemRevision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Creator ID",
+ sizeof ( pFadt->CreatorId ),
+ (CHAR8 *)&pFadt->CreatorId );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowRevision ( SocketFD,
+ pPort,
+ "Creator Revision",
+ pFadt->CreatorRevision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the data from the FADT
+ //
+ Status = RowPointer ( SocketFD,
+ pPort,
+ "FIRMWARE_CTRL",
+ (CONST VOID *)pFadt->FirmwareCtrl,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowPointer ( SocketFD,
+ pPort,
+ "DSDT",
+ (CONST VOID *)pFadt->DSDT,
+ ( pFadt->DSDT == pFadt->XDsdt ) ? PAGE_ACPI_DSDT : NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Reserved",
+ pFadt->Reserved,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Preferred_PM_Profile",
+ pFadt->PreferredPmProfile,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "SCI_INT",
+ pFadt->SciInt,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "SMI_CMD",
+ pFadt->SmiCmd,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "ACPI_ENABLE",
+ pFadt->AcpiEnable,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "ACPI_DISABLE",
+ pFadt->AcpiDisable,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "S4BIOS_REQ",
+ pFadt->S4BiosReq,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PSTATE_CNT",
+ pFadt->PStateCnt,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PM1a_EVT_BLK",
+ pFadt->Pm1aEvtBlk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PM1b_EVT_BLK",
+ pFadt->Pm1bEvtBlk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PM1a_CNT_BLK",
+ pFadt->Pm1aCntBlk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PM1b_CNT_BLK",
+ pFadt->Pm1bCntBlk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PM2_CNT_BLK",
+ pFadt->Pm2CntBlk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "PM_TMR_BLK",
+ pFadt->PmTmrBlk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "GPE0_BLK",
+ pFadt->Gpe0Blk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "GPE1_BLK",
+ pFadt->Gpe1Blk,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "PM1_EVT_LEN",
+ pFadt->Pm1EvtLen );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "PM1_CNT_LEN",
+ pFadt->Pm1CntLen );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "PM2_CNT_LEN",
+ pFadt->PM2CntLen );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "PM_TMR_LEN",
+ pFadt->PmTmrLen );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "GPE0_BLK_LEN",
+ pFadt->Gpe0BlkLen );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "GPE1_BLK_LEN",
+ pFadt->Gpe1BlkLen );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "GPE1_BASE",
+ pFadt->Gpe1Base,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "CST_CNT",
+ pFadt->CstCnt );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "P_LVL2_LAT",
+ pFadt->PLvl2Lat,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "P_LVL3_LAT",
+ pFadt->PLvl3Lat,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "FLUSH_SIZE",
+ pFadt->FlushSize );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "FLUSH_Stride",
+ pFadt->FlushStride );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "DUTY_OFFSET",
+ pFadt->DutyOffset,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "DUTY_WIDTH",
+ pFadt->DutyWidth,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "DAY_ALRM",
+ pFadt->DayAlrm,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "MON_ALRM",
+ pFadt->MonAlrm,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "CENTURY",
+ pFadt->Century,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "IAPC_BOOT_ARCH",
+ pFadt->IapcBootArch,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Reserved",
+ pFadt->Reserved2,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Flags",
+ pFadt->Flags,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "RESET_REG",
+ &pFadt->ResetReg[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "RESET_VALUE",
+ pFadt->ResetValue,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Reserved",
+ pFadt->Reserved3[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Reserved",
+ pFadt->Reserved3[1],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Reserved",
+ pFadt->Reserved3[2],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "X_FIRMWARE_CTRL",
+ pFadt->XFirmwareCtrl,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "X_DSDT",
+ pFadt->XDsdt,
+ PAGE_ACPI_DSDT );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_PM1a_EVT_BLK",
+ &pFadt->XPm1aEvtBlk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_PM1b_EVT_BLK",
+ &pFadt->XPm1bEvtBlk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_PM1a_CNT_BLK",
+ &pFadt->XPm1aCntBlk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_PM1b_CNT_BLK",
+ &pFadt->XPm1bCntBlk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_PM2_CNT_BLK",
+ &pFadt->XPm2CntBlk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_PM_TMR_BLK",
+ &pFadt->XPmTmrBlk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_GPE0_BLK",
+ &pFadt->XGpe0Blk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowGenericAddress ( SocketFD,
+ pPort,
+ "X_GPE1_BLK",
+ &pFadt->XGpe1Blk[0],
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Build the table trailer
+ //
+ Status = TableTrailer ( SocketFD,
+ pPort,
+ pbDone );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Respond with the ACPI RSDP 1.0b table
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [out] pbDone Address to receive the request completion status
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+AcpiRsdp10Page (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ OUT BOOLEAN * pbDone
+ )
+{
+ CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Send the RSDP page
+ //
+ for ( ; ; ) {
+ //
+ // Locate the RSDP
+ //
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpi10TableGuid, (VOID **) &pRsdp10b );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Send the page and table header
+ //
+ Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 1.0b Root System Description Pointer", pRsdp10b );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the RSDP
+ //
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Signature",
+ sizeof ( pRsdp10b->Signature ),
+ (CHAR8 *)&pRsdp10b->Signature );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Checksum",
+ pRsdp10b->Checksum,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OemId",
+ sizeof ( pRsdp10b->OemId ),
+ &pRsdp10b->OemId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Reserved",
+ pRsdp10b->Reserved,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowPointer ( SocketFD,
+ pPort,
+ "RsdtAddress",
+ (VOID *)pRsdp10b->RsdtAddress,
+ PAGE_ACPI_RSDT );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Build the table trailer
+ //
+ Status = TableTrailer ( SocketFD,
+ pPort,
+ pbDone );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Respond with the ACPI RSDP 3.0 table
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [out] pbDone Address to receive the request completion status
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+AcpiRsdp30Page (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ OUT BOOLEAN * pbDone
+ )
+{
+ CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Send the RSDP page
+ //
+ for ( ; ; ) {
+ //
+ // Locate the RSDP
+ //
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **) &pRsdp30 );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Send the page and table header
+ //
+ Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 3.0 Root System Description Pointer", pRsdp30 );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the RSDP
+ //
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Signature",
+ sizeof ( pRsdp30->Signature ),
+ (CHAR8 *)&pRsdp30->Signature );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Checksum",
+ pRsdp30->Checksum,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OemId",
+ sizeof ( pRsdp30->OemId ),
+ &pRsdp30->OemId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Revision",
+ pRsdp30->Revision,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowPointer ( SocketFD,
+ pPort,
+ "RsdtAddress",
+ (VOID *)pRsdp30->RsdtAddress,
+ PAGE_ACPI_RSDT );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Length",
+ pRsdp30->Length );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowPointer ( SocketFD,
+ pPort,
+ "XsdtAddress",
+ (VOID *)pRsdp30->XsdtAddress,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "ExtendedChecksum",
+ pRsdp30->ExtendedChecksum,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowBytes ( SocketFD,
+ pPort,
+ "Reserved",
+ sizeof ( pRsdp30->Reserved ),
+ &pRsdp30->Reserved [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Build the table trailer
+ //
+ Status = TableTrailer ( SocketFD,
+ pPort,
+ pbDone );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Respond with the ACPI RSDT table
+
+ @param [in] SocketFD The socket's file descriptor to add to the list.
+ @param [in] pPort The WSDT_PORT structure address
+ @param [out] pbDone Address to receive the request completion status
+
+ @retval EFI_SUCCESS The request was successfully processed
+
+**/
+EFI_STATUS
+AcpiRsdtPage (
+ IN int SocketFD,
+ IN WSDT_PORT * pPort,
+ OUT BOOLEAN * pbDone
+ )
+{
+ CONST UINT32 * pEnd;
+ CONST UINT32 * pEntry;
+ CONST ACPI_RSDT * pRsdt;
+ CONST CHAR8 * pTableName;
+ CONST CHAR16 * pWebPage;
+ EFI_STATUS Status;
+ UINT32 TableName [ 2 ];
+
+ DBG_ENTER ( );
+
+ //
+ // Send the RSDT page
+ //
+ for ( ; ; ) {
+ //
+ // Locate the RSDT
+ //
+ pRsdt = LocateRsdt ( );
+ if ( NULL == pRsdt ) {
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // Send the page and table header
+ //
+ Status = TableHeader ( SocketFD, pPort, L"RSDT - ACPI Root System Description Table", pRsdt );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Display the RSDT
+ //
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Signature",
+ sizeof ( pRsdt->Signature ),
+ (CHAR8 *)&pRsdt->Signature );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Length",
+ pRsdt->Length );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowDecimalValue ( SocketFD,
+ pPort,
+ "Revision",
+ pRsdt->Revision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowHexValue ( SocketFD,
+ pPort,
+ "Checksum",
+ pRsdt->Checksum,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OEMID",
+ sizeof ( pRsdt->OemId ),
+ &pRsdt->OemId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "OEM Table ID",
+ sizeof ( pRsdt->OemTableId ),
+ &pRsdt->OemTableId [ 0 ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowRevision ( SocketFD,
+ pPort,
+ "OEM Revision",
+ pRsdt->OemRevision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowAnsiArray ( SocketFD,
+ pPort,
+ "Creator ID",
+ sizeof ( pRsdt->CreatorId ),
+ (CHAR8 *)&pRsdt->CreatorId );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ Status = RowRevision ( SocketFD,
+ pPort,
+ "Creator Revision",
+ pRsdt->CreatorRevision );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Walk the list of entries
+ //
+ pEntry = &pRsdt->Entry [ 0 ];
+ pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];
+ TableName [ 1 ] = 0;
+ while ( pEnd > pEntry ) {
+ //
+ // The entry is actually a 32-bit physical table address
+ // The first entry in the table is the 32-bit table signature
+ //
+ TableName [ 0 ] = *(UINT32 *)*pEntry;
+ pWebPage = SignatureLookup ( &TableName [ 0 ], &pTableName );
+
+ //
+ // Display the table address
+ //
+ Status = RowPointer ( SocketFD,
+ pPort,
+ pTableName,
+ (VOID *)*pEntry,
+ pWebPage );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ pEntry++;
+ }
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+
+ //
+ // Build the table trailer
+ //
+ Status = TableTrailer ( SocketFD,
+ pPort,
+ pbDone );
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
diff --git a/AppPkg/Applications/Sockets/WebServer/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, - "<" ); - } - else if ( '>' == Character ) { - // - // Replace with HTML equivalent - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - ">" ); - } - else if ( '&' == Character ) { - // - // Replace with HTML equivalent - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "&" ); - } - else if ( '\"' == Character ) { - // - // Replace with HTML equivalent - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - """ ); - } - 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, - " " ); - 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, - " " ); - 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, - " " ); - 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,
+ "<" );
+ }
+ else if ( '>' == Character ) {
+ //
+ // Replace with HTML equivalent
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ ">" );
+ }
+ else if ( '&' == Character ) {
+ //
+ // Replace with HTML equivalent
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ "&" );
+ }
+ else if ( '\"' == Character ) {
+ //
+ // Replace with HTML equivalent
+ //
+ Status = HttpSendAnsiString ( SocketFD,
+ pPort,
+ """ );
+ }
+ 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,
+ " " );
+ 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,
+ " " );
+ 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,
+ " " );
+ 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;
+}
|