From: darylm503 Date: Fri, 5 Aug 2011 23:57:34 +0000 (+0000) Subject: Fix @return Doxygen commands to be singular instead of plural. X-Git-Tag: edk2-stable201903~14432 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=7dc1329100c370992cdd430359512443bd1ee9f2 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 --- 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 - -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 + +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 -#include -#include -#include - -#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, - "" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - pName ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "" ); - 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, - "
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, - "
\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, - "" ); - 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, - "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, - "\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, - "" ); - 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, - "" ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Dump the buffer - // - Status = HttpSendDump ( SocketFD, - pPort, - ByteCount, - pData ); - - // - // Terminate the field value and row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "\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, - "" ); - 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, - "" ); - 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, - "
Register Bit Width: " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendValue ( SocketFD, - pPort, - pGenericAddress->RegisterBitWidth ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "
Register Bit Offset: " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendHexValue ( SocketFD, - pPort, - pGenericAddress->RegisterBitOffset ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "
Access Size: " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendValue ( SocketFD, - pPort, - pGenericAddress->AccessSize ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, - pPort, - "
Address: " ); - if ( EFI_ERROR ( Status )) { - break; - } - - // - // Add the web-page link if necessary - // - if ( NULL != pWebPage ) { - 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, - "" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Terminate the row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "
\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 +#include +#include +#include + +#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, + "" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + pName ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + "" ); + 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, + "
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, + "
\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, + "" ); + 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, + "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, + "\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, + "" ); + 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, + "" ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Dump the buffer + // + Status = HttpSendDump ( SocketFD, + pPort, + ByteCount, + pData ); + + // + // Terminate the field value and row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "\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, + "" ); + 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, + "" ); + 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, + "
Register Bit Width: " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendValue ( SocketFD, + pPort, + pGenericAddress->RegisterBitWidth ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + "
Register Bit Offset: " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexValue ( SocketFD, + pPort, + pGenericAddress->RegisterBitOffset ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + "
Access Size: " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendValue ( SocketFD, + pPort, + pGenericAddress->AccessSize ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, + pPort, + "
Address: " ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Add the web-page link if necessary + // + if ( NULL != pWebPage ) { + 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, + "" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + + // + // Terminate the row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "
\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 - -/** - 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, - "\r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - if ( NULL != pTitle ) { - Status = HttpSendAnsiString ( SocketFD, pPort, " \r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, pPort, " " ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, pPort, " \r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - Status = HttpSendAnsiString ( SocketFD, pPort, " \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 404
" - "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, "
\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, " \r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - Status = HttpSendAnsiString ( SocketFD, pPort, " \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, - "" ); - 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, - "
\r\n" ); - if ( EFI_ERROR ( Status )) { - break; - } - } - - // - // Terminate the field value and row - // - Status = HttpSendAnsiString ( SocketFD, - pPort, - "
\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 + +/** + 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, + "\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + if ( NULL != pTitle ) { + Status = HttpSendAnsiString ( SocketFD, pPort, " \r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, pPort, " " ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, pPort, " \r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + Status = HttpSendAnsiString ( SocketFD, pPort, " \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 404
" + "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, "
\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, " \r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendAnsiString ( SocketFD, pPort, " \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, + "" ); + 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, + "
\r\n" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + + // + // Terminate the field value and row + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "
\r\n" ); + break; + } + + // + // Return the operation status + // + return Status; +} + + +/** + Display a row containing a GUID value + + @param [in] SocketFD The socket's file descriptor to add to the list. + @param [in] pPort The WSDT_PORT structure address + @param [in] pGuid Address of the GUID to display + + @retval EFI_SUCCESS The request was successfully processed + +**/ +EFI_STATUS +HttpSendGuid ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN CONST EFI_GUID * pGuid + ) +{ + UINT32 Index; + EFI_STATUS Status; + + DBG_ENTER ( ); + + // + // Use for/break instead of goto + // + for ( ; ; ) { + // + // Display the GUID in a form found in the code + // + // E.g. 0xca16005f, 0x11ec, 0x4bdc, { 0x99, 0x97, 0x27, 0x2c, 0xa9, 0xba, 0x15, 0xe5 } + // + + // + // Display the first 32 bits + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + "0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexBits ( SocketFD, + pPort, + 32, + pGuid->Data1 ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Display the second 16 bits + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + ", 0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexBits ( SocketFD, + pPort, + 16, + pGuid->Data2 ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Display the thrid 16 bits + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + ", 0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + Status = HttpSendHexBits ( SocketFD, + pPort, + 16, + pGuid->Data3 ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Place the last 64 bits in braces + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + ", { 0x" ); + if ( EFI_ERROR ( Status )) { + break; + } + for ( Index = 0; 7 >= Index; Index++ ) { + // + // Display the next 8 bits + // + Status = HttpSendHexBits ( SocketFD, + pPort, + 8, + pGuid->Data4 [ Index ]); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Separate the bytes + // + Status = HttpSendAnsiString ( SocketFD, + pPort, + ( 7 != Index ) ? ", 0x" : " }" ); + if ( EFI_ERROR ( Status )) { + break; + } + } + break; + } + + // + // Return the operation status + // + DBG_EXIT_STATUS ( Status ); + return Status; +} + + +/** + Output a hex value to the HTML page + + @param [in] SocketFD Socket file descriptor + @param [in] pPort The WSDT_PORT structure address + @param [in] Bits Number of bits to display + @param [in] Value Value to display + + @retval EFI_SUCCESS Successfully displayed the address +**/ +EFI_STATUS +HttpSendHexBits ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN INT32 Bits, + IN UINT64 Value + ) +{ + UINT32 Digit; + INT32 Shift; + EFI_STATUS Status; + + // + // Assume success + // + Status = EFI_SUCCESS; + + // + // Walk the list of divisors + // + Shift = (( Bits + 3 ) & ( ~3 )) - 4; + while ( 0 <= Shift ) { + // + // Determine the next digit + // + Digit = (UINT32)(( Value >> Shift ) & 0xf ); + if ( 10 <= Digit ) { + Digit += 'A' - '0' - 10; + } + + // + // Display the digit + // + Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit )); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Set the next shift + // + Shift -= 4; + } + + // + // Return the operation status + // + return Status; +} + + +/** + Output a hex value to the HTML page + + @param [in] SocketFD Socket file descriptor + @param [in] pPort The WSDT_PORT structure address + @param [in] Value Value to display + + @retval EFI_SUCCESS Successfully displayed the address +**/ +EFI_STATUS +HttpSendHexValue ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN UINT64 Value + ) +{ + BOOLEAN bDisplayZeros; + UINT32 Digit; + INT32 Shift; + EFI_STATUS Status; + + // + // Assume success + // + Status = EFI_SUCCESS; + + // + // Walk the list of divisors + // + bDisplayZeros = FALSE; + Shift = 60; + do { + // + // Determine the next digit + // + Digit = (UINT32)(( Value >> Shift ) & 0xf ); + if ( 10 <= Digit ) { + Digit += 'A' - '0' - 10; + } + + // + // Suppress leading zeros + // + if (( 0 != Digit ) || bDisplayZeros || ( 0 == Shift )) { + bDisplayZeros = TRUE; + + // + // Display the digit + // + Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit )); + if ( EFI_ERROR ( Status )) { + break; + } + } + + // + // Set the next shift + // + Shift -= 4; + } while ( 0 <= Shift ); + + // + // Return the operation status + // + return Status; +} + + +/** + Output an IP address to the HTML page + + @param [in] SocketFD Socket file descriptor + @param [in] pPort The WSDT_PORT structure address + @param [in] pAddress Address of the socket address + + @retval EFI_SUCCESS Successfully displayed the address +**/ +EFI_STATUS +HttpSendIpAddress ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN struct sockaddr_in * pAddress + ) +{ + EFI_STATUS Status; + + // + // Output the IPv4 address + // + Status = HttpSendValue ( SocketFD, pPort, (UINT8)pAddress->sin_addr.s_addr ); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendByte ( SocketFD, pPort, '.' ); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 8 )); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendByte ( SocketFD, pPort, '.' ); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 16 )); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendByte ( SocketFD, pPort, '.' ); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 24 )); + if ( !EFI_ERROR ( Status )) { + // + // Output the port number + // + Status = HttpSendByte ( SocketFD, pPort, ':' ); + if ( !EFI_ERROR ( Status )) { + Status = HttpSendValue ( SocketFD, pPort, htons ( pAddress->sin_port )); + } + } + } + } + } + } + } + } + + // + // Return the operation status + // + return Status; +} + + +/** + Send a Unicode string + + @param [in] SocketFD The socket's file descriptor to add to the list. + @param [in] pPort The WSDT_PORT structure address + @param [in] pString A zero terminated Unicode string + + @retval EFI_SUCCESS The request was successfully processed + +**/ +EFI_STATUS +HttpSendUnicodeString ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN CONST UINT16 * pString + ) +{ + UINT8 Data; + UINT16 Character; + EFI_STATUS Status; + + // + // Assume success + // + Status = EFI_SUCCESS; + + // + // Walk the characters in he string + // + while ( 0 != ( Character = *pString++ )) { + // + // Convert the character to UTF-8 + // + if ( 0 != ( Character & 0xf800 )) { + // + // Send the upper 4 bits + // + Data = (UINT8)(( Character >> 12 ) & 0xf ); + Data |= 0xe0; + Status = HttpSendByte ( SocketFD, + pPort, + Data ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Send the next 6 bits + // + Data = (UINT8)(( Character >> 6 ) & 0x3f ); + Data |= 0x80; + Status = HttpSendByte ( SocketFD, + pPort, + Data ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Send the last 6 bits + // + Data = (UINT8)( Character & 0x3f ); + Data |= 0x80; + } + else if ( 0 != ( Character & 0x0780 )) { + // + // Send the upper 5 bits + // + Data = (UINT8)(( Character >> 6 ) & 0x1f ); + Data |= 0xc0; + Status = HttpSendByte ( SocketFD, + pPort, + Data ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Send the last 6 bits + // + Data = (UINT8)( Character & 0x3f ); + Data |= 0x80; + } + else { + Data = (UINT8)( Character & 0x7f ); + } + + // + // Send the last data byte + // + Status = HttpSendByte ( SocketFD, + pPort, + Data ); + if ( EFI_ERROR ( Status )) { + break; + } + } + + // + // Return the operation status + // + return Status; +} + + +/** + Output a value to the HTML page + + @param [in] SocketFD Socket file descriptor + @param [in] pPort The WSDT_PORT structure address + @param [in] Value Value to display + + @retval EFI_SUCCESS Successfully displayed the address +**/ +EFI_STATUS +HttpSendValue ( + IN int SocketFD, + IN WSDT_PORT * pPort, + IN UINT64 Value + ) +{ + BOOLEAN bDisplayZeros; + UINT64 Digit; + CONST UINT64 * pEnd; + CONST UINT64 * pDivisor; + CONST UINT64 pDivisors [ ] = { + 10000000000000000000L, + 1000000000000000000L, + 100000000000000000L, + 10000000000000000L, + 1000000000000000L, + 100000000000000L, + 10000000000000L, + 1000000000000L, + 100000000000L, + 10000000000L, + 1000000000L, + 100000000L, + 10000000L, + 1000000L, + 100000L, + 10000L, + 1000L, + 100L, + 10L + }; + EFI_STATUS Status; + UINT64 Temp; + + // + // Assume success + // + Status = EFI_SUCCESS; + + // + // Walk the list of divisors + // + bDisplayZeros = FALSE; + pDivisor = &pDivisors[0]; + pEnd = &pDivisor [ sizeof ( pDivisors ) / sizeof ( pDivisors [0])]; + while ( pEnd > pDivisor ) { + // + // Determine the next digit + // + Digit = Value / *pDivisor; + + // + // Suppress leading zeros + // + if (( 0 != Digit ) || bDisplayZeros ) { + bDisplayZeros = TRUE; + + // + // Display the digit + // + Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit )); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Determine the remainder + // + Temp = *pDivisor * Digit; + Value -= Temp; + } + + // + // Set the next divisor + // + pDivisor += 1; + } + + // + // Display the final digit + // + if ( !EFI_ERROR ( Status )) { + Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Value )); + } + + // + // Return the operation status + // + return Status; +} diff --git a/StdLib/BsdSocketLib/SocketInternals.h b/StdLib/BsdSocketLib/SocketInternals.h index 4f5c584a4e..8fbd8420dc 100644 --- a/StdLib/BsdSocketLib/SocketInternals.h +++ b/StdLib/BsdSocketLib/SocketInternals.h @@ -57,7 +57,7 @@ address for the file @param [in] pErrno Address of the errno variable - @returns A pointer to the socket protocol structure or NULL if + @return A pointer to the socket protocol structure or NULL if an invalid file descriptor was passed in. **/ @@ -73,7 +73,7 @@ BslFdToSocketProtocol ( @param [in] pDescriptor Descriptor address for the file - @returns This routine returns 0 upon success and -1 upon failure. + @return This routine returns 0 upon success and -1 upon failure. In the case of failure, errno contains more information. **/ @@ -105,7 +105,7 @@ BslSocketCloseWork ( @param [in] Events Mask of events to detect - @returns Detected events for the socket + @return Detected events for the socket **/ short @@ -121,7 +121,7 @@ BslSocketPoll ( @param [in] pErrno Address of the errno variable - @returns The file descriptor for the socket or -1 if an error occurs. + @return The file descriptor for the socket or -1 if an error occurs. **/ int @@ -138,7 +138,7 @@ BslSocketProtocolToFd ( @param [in] LengthInBytes Number of bytes to read @param [in] pBuffer Address of the buffer to receive the data - @returns The number of bytes read or -1 if an error occurs. + @return The number of bytes read or -1 if an error occurs. **/ ssize_t @@ -157,7 +157,7 @@ BslSocketRead ( @param [in] LengthInBytes Number of bytes to write @param [in] pBuffer Address of the data - @returns The number of bytes written or -1 if an error occurs. + @return The number of bytes written or -1 if an error occurs. **/ ssize_t @@ -175,7 +175,7 @@ BslSocketWrite ( @param [in] pErrno Address of the errno variable - @returns A pointer to the socket protocol structure or NULL if + @return A pointer to the socket protocol structure or NULL if an invalid file descriptor was passed in. **/ diff --git a/StdLib/BsdSocketLib/accept.c b/StdLib/BsdSocketLib/accept.c index de8d91f607..25ae1b5861 100644 --- a/StdLib/BsdSocketLib/accept.c +++ b/StdLib/BsdSocketLib/accept.c @@ -27,7 +27,7 @@ of the remote network address buffer. Upon return, contains the length of the remote network address. - @returns ::accept returns zero if successful and -1 when an error occurs. + @return ::accept returns zero if successful and -1 when an error occurs. In the case of an error, errno contains more details. **/ @@ -108,7 +108,7 @@ AcceptWork ( of the remote network address buffer. Upon return, contains the length of the remote network address. - @returns ::accept returns zero if successful and -1 when an error occurs. + @return ::accept returns zero if successful and -1 when an error occurs. In the case of an error, errno contains more details. **/ @@ -139,7 +139,7 @@ accept ( of the remote network address buffer. Upon return, contains the length of the remote network address. - @returns This routine returns zero if successful and -1 when an error occurs. + @return This routine returns zero if successful and -1 when an error occurs. In the case of an error, errno contains more details. **/ diff --git a/StdLib/BsdSocketLib/bind.c b/StdLib/BsdSocketLib/bind.c index fc24ea420a..c1bf64e9e4 100644 --- a/StdLib/BsdSocketLib/bind.c +++ b/StdLib/BsdSocketLib/bind.c @@ -22,9 +22,9 @@ POSIX documentation for the bind routine is available online for reference. - @param [in] s Socket file descriptor returned from ::socket. + @param[in] s Socket file descriptor returned from ::socket. - @param [in] name Address of a sockaddr structure that contains the + @param[in] name Address of a sockaddr structure that contains the connection point on the local machine. An IPv4 address of INADDR_ANY specifies that the connection is made to all of the network stacks on the platform. Specifying a @@ -34,9 +34,9 @@ number from the dynamic range. Specifying a specific port number causes the network layer to use that port. - @param [in] namelen Specifies the length in bytes of the sockaddr structure. + @param[in] namelen Specifies the length in bytes of the sockaddr structure. - @returns The bind routine returns zero (0) if successful and -1 upon failure. + @return The bind routine returns zero (0) if successful and -1 upon failure. **/ int diff --git a/StdLib/BsdSocketLib/close.c b/StdLib/BsdSocketLib/close.c index 7d70e4f126..2a9fda4930 100644 --- a/StdLib/BsdSocketLib/close.c +++ b/StdLib/BsdSocketLib/close.c @@ -18,9 +18,9 @@ /** Worker routine to close the socket. - @param [in] pSocketProtocol Socket protocol structure address + @param[in] pSocketProtocol Socket protocol structure address - @param [in] pErrno Address of the errno variable + @param[in] pErrno Address of the errno variable @retval EFI_SUCCESS Successfully closed the socket @@ -83,9 +83,9 @@ BslSocketCloseWork ( /** Close the socket - @param [in] pDescriptor Descriptor address for the file + @param[in] pDescriptor Descriptor address for the file - @returns This routine returns 0 upon success and -1 upon failure. + @return This routine returns 0 upon success and -1 upon failure. In the case of failure, errno contains more information. **/ diff --git a/StdLib/BsdSocketLib/connect.c b/StdLib/BsdSocketLib/connect.c index e02762efa3..92fc75bdb0 100644 --- a/StdLib/BsdSocketLib/connect.c +++ b/StdLib/BsdSocketLib/connect.c @@ -42,10 +42,10 @@ @param [in] s Socket file descriptor returned from ::socket. @param [in] address Network address of the remote system - + @param [in] address_len Length of the remote network address - @returns ::connect returns zero if successful and -1 when an error occurs. + @return ::connect returns zero if successful and -1 when an error occurs. In the case of an error, errno contains more details. **/ @@ -61,7 +61,7 @@ connect ( struct __filedes * pDescriptor; EFI_SOCKET_PROTOCOL * pSocketProtocol; EFI_STATUS Status; - + // // Locate the context for this socket // @@ -85,7 +85,7 @@ connect ( &errno ); } while ( bBlocking && ( EFI_NOT_READY == Status )); } - + // // Return the new socket file descriptor // diff --git a/StdLib/BsdSocketLib/getpeername.c b/StdLib/BsdSocketLib/getpeername.c index 850308a401..37e6d1eab6 100644 --- a/StdLib/BsdSocketLib/getpeername.c +++ b/StdLib/BsdSocketLib/getpeername.c @@ -29,7 +29,7 @@ @param [in] address_len Length of the remote network address structure - @returns ::getpeername returns zero (0) if successful or -1 when an error occurs. + @return ::getpeername returns zero (0) if successful or -1 when an error occurs. In the case of an error, errno contains more details. **/ diff --git a/StdLib/BsdSocketLib/getsockname.c b/StdLib/BsdSocketLib/getsockname.c index 0b72edcf29..e8d1d55bb3 100644 --- a/StdLib/BsdSocketLib/getsockname.c +++ b/StdLib/BsdSocketLib/getsockname.c @@ -29,7 +29,7 @@ @param [in] address_len Length of the local network address structure - @returns ::getsockname returns zero (0) if successful or -1 when an error occurs. + @return ::getsockname returns zero (0) if successful or -1 when an error occurs. In the case of an error, errno contains more details. **/ diff --git a/StdLib/BsdSocketLib/listen.c b/StdLib/BsdSocketLib/listen.c index 5e14876652..193444a25c 100644 --- a/StdLib/BsdSocketLib/listen.c +++ b/StdLib/BsdSocketLib/listen.c @@ -31,7 +31,7 @@ waiting for the application to call accept. Connection attempts received while the queue is full are refused. - @returns The listen routine returns zero (0) if successful and -1 upon failure. + @return The listen routine returns zero (0) if successful and -1 upon failure. **/ int diff --git a/StdLib/BsdSocketLib/poll.c b/StdLib/BsdSocketLib/poll.c index fdf50e8b68..336924d556 100644 --- a/StdLib/BsdSocketLib/poll.c +++ b/StdLib/BsdSocketLib/poll.c @@ -22,7 +22,7 @@ @param [in] Events Mask of events to detect - @returns Detected events for the socket + @return Detected events for the socket **/ short diff --git a/StdLib/BsdSocketLib/read.c b/StdLib/BsdSocketLib/read.c index eb72f5cbf7..6f8d42974b 100644 --- a/StdLib/BsdSocketLib/read.c +++ b/StdLib/BsdSocketLib/read.c @@ -23,7 +23,7 @@ @param [in] LengthInBytes Number of bytes to read @param [in] pBuffer Address of the buffer to receive the data - @returns The number of bytes read or -1 if an error occurs. + @return The number of bytes read or -1 if an error occurs. **/ ssize_t diff --git a/StdLib/BsdSocketLib/recv.c b/StdLib/BsdSocketLib/recv.c index 735e1dbddd..91f07cb08a 100644 --- a/StdLib/BsdSocketLib/recv.c +++ b/StdLib/BsdSocketLib/recv.c @@ -26,12 +26,12 @@ @param [in] s Socket file descriptor returned from ::socket. @param [in] buffer Address of a buffer to receive the data. - + @param [in] length Length of the buffer in bytes. @param [in] flags Message control flags - @returns ::recv returns the number of valid bytes in the buffer, + @return ::recv returns the number of valid bytes in the buffer, zero if no data was received, and -1 when an error occurs. In the case of an error, errno contains more details. @@ -45,7 +45,7 @@ recv ( ) { ssize_t BytesRead; - + // // Receive the data from the remote system // diff --git a/StdLib/BsdSocketLib/recvfrom.c b/StdLib/BsdSocketLib/recvfrom.c index a8d1ab54ee..ce230231dc 100644 --- a/StdLib/BsdSocketLib/recvfrom.c +++ b/StdLib/BsdSocketLib/recvfrom.c @@ -26,7 +26,7 @@ @param [in] s Socket file descriptor returned from ::socket. @param [in] buffer Address of a buffer to receive the data. - + @param [in] length Length of the buffer in bytes. @param [in] flags Message control flags @@ -35,7 +35,7 @@ @param [in] address_len Length of the remote network address structure - @returns ::recvfrom returns the number of valid bytes in the buffer, + @return ::recvfrom returns the number of valid bytes in the buffer, zero if no data was received, and -1 when an error occurs. In the case of an error, errno contains more details. diff --git a/StdLib/BsdSocketLib/send.c b/StdLib/BsdSocketLib/send.c index f3f739cb6f..0bbed5ac33 100644 --- a/StdLib/BsdSocketLib/send.c +++ b/StdLib/BsdSocketLib/send.c @@ -26,12 +26,12 @@ @param [in] s Socket file descriptor returned from ::socket. @param [in] buffer Address of a buffer containing the data to send. - + @param [in] length Length of the buffer in bytes. @param [in] flags Message control flags - @returns ::send returns the number of data bytes that were + @return ::send returns the number of data bytes that were sent and -1 when an error occurs. In the case of an error, errno contains more details. diff --git a/StdLib/BsdSocketLib/sendto.c b/StdLib/BsdSocketLib/sendto.c index aa6ea8c14a..5311ce6022 100644 --- a/StdLib/BsdSocketLib/sendto.c +++ b/StdLib/BsdSocketLib/sendto.c @@ -26,7 +26,7 @@ @param [in] s Socket file descriptor returned from ::socket. @param [in] buffer Address of a buffer containing the data to send. - + @param [in] length Length of the buffer in bytes. @param [in] flags Message control flags @@ -35,7 +35,7 @@ @param [in] tolen Length of remote system address structure - @returns ::send returns the number of data bytes that were + @return ::send returns the number of data bytes that were sent and -1 when an error occurs. In the case of an error, errno contains more details. diff --git a/StdLib/BsdSocketLib/shutdown.c b/StdLib/BsdSocketLib/shutdown.c index 4c00feade7..c3df1ee519 100644 --- a/StdLib/BsdSocketLib/shutdown.c +++ b/StdLib/BsdSocketLib/shutdown.c @@ -26,8 +26,8 @@ @param [in] s Socket file descriptor returned from ::socket. @param [in] how Which operations to shutdown - - @returns ::shutdown returns the zero (0) if successful or -1 when an + + @return ::shutdown returns the zero (0) if successful or -1 when an error occurs. In the latter case, errno contains more details. **/ diff --git a/StdLib/BsdSocketLib/socket.c b/StdLib/BsdSocketLib/socket.c index 3754a29eb0..e78329291c 100644 --- a/StdLib/BsdSocketLib/socket.c +++ b/StdLib/BsdSocketLib/socket.c @@ -47,7 +47,7 @@ const struct fileops SocketOperations = { address for the file @param [in] pErrno Address of the errno variable - @returns A pointer to the socket protocol structure or NULL if + @return A pointer to the socket protocol structure or NULL if an invalid file descriptor was passed in. **/ @@ -101,10 +101,10 @@ BslFdToSocketProtocol ( Build a file descriptor for a socket. @param [in] pSocketProtocol Socket protocol structure address - + @param [in] pErrno Address of the errno variable - @returns The file descriptor for the socket or -1 if an error occurs. + @return The file descriptor for the socket or -1 if an error occurs. **/ int @@ -194,7 +194,7 @@ BslSocketProtocolToFd (
  • IPPROTO_UDP
  • - This value must be combined with SOCK_DGRAM. - @returns This routine returns a file descriptor for the socket. + @return This routine returns a file descriptor for the socket. **/ INT32 @@ -250,7 +250,7 @@ socket ( @param [in] pErrno Address of the errno variable - @returns A pointer to the socket protocol structure or NULL if + @return A pointer to the socket protocol structure or NULL if an invalid file descriptor was passed in. **/ diff --git a/StdLib/BsdSocketLib/write.c b/StdLib/BsdSocketLib/write.c index d04dda9c39..f6f50006af 100644 --- a/StdLib/BsdSocketLib/write.c +++ b/StdLib/BsdSocketLib/write.c @@ -23,7 +23,7 @@ @param [in] LengthInBytes Number of bytes to write @param [in] pBuffer Address of the data - @returns The number of bytes written or -1 if an error occurs. + @return The number of bytes written or -1 if an error occurs. **/ ssize_t diff --git a/StdLib/Include/Protocol/EfiSocket.h b/StdLib/Include/Protocol/EfiSocket.h index 5e044fac9e..e9e4604048 100644 --- a/StdLib/Include/Protocol/EfiSocket.h +++ b/StdLib/Include/Protocol/EfiSocket.h @@ -198,11 +198,11 @@ EFI_STATUS @param [in] pSocketProtocol Address of the socket protocol structure. @param [in] pSockAddr Network address of the remote system. - + @param [in] SockAddrLength Length in bytes of the network address. - + @param [out] pErrno Address to receive the errno value upon completion. - + @retval EFI_SUCCESS The connection was successfully established. @retval EFI_NOT_READY The connection is in progress, call this routine again. @retval Others The connection attempt failed. @@ -221,7 +221,7 @@ EFI_STATUS Get the local address. @param [in] pSocketProtocol Address of the socket protocol structure. - + @param [out] pAddress Network address to receive the local system address @param [in,out] pAddressLength Length of the local network address structure @@ -244,7 +244,7 @@ EFI_STATUS Get the peer address. @param [in] pSocketProtocol Address of the socket protocol structure. - + @param [out] pAddress Network address to receive the remote system address @param [in,out] pAddressLength Length of the remote network address structure @@ -387,13 +387,13 @@ EFI_STATUS documentation is available online. @param [in] pSocketProtocol Address of the socket protocol structure. - + @param [in] Flags Message control flags - + @param [in] BufferLength Length of the the buffer - + @param [in] pBuffer Address of a buffer to receive the data. - + @param [in] pDataLength Number of received data bytes in the buffer. @param [out] pAddress Network address to receive the remote system address @@ -425,13 +425,13 @@ EFI_STATUS remote network connection. @param [in] pSocketProtocol Address of the socket protocol structure. - + @param [in] Flags Message control flags - + @param [in] BufferLength Length of the the buffer - + @param [in] pBuffer Address of a buffer containing the data to send - + @param [in] pDataLength Address to receive the number of data bytes sent @param [in] pAddress Network address of the remote system address @@ -463,9 +463,9 @@ EFI_STATUS operations. @param [in] pSocketProtocol Address of the socket protocol structure. - + @param [in] How Which operations to stop - + @param [out] pErrno Address to receive the errno value upon completion. @retval EFI_SUCCESS - Socket operations successfully shutdown @@ -577,7 +577,7 @@ typedef struct _EFI_SOCKET_PROTOCOL { of the remote network address buffer. Upon return, contains the length of the remote network address. - @returns This routine returns zero if successful and -1 when an error occurs. + @return This routine returns zero if successful and -1 when an error occurs. In the case of an error, errno contains more details. **/ diff --git a/StdLib/Include/wchar.h b/StdLib/Include/wchar.h index c42594787d..bab02b05b9 100644 --- a/StdLib/Include/wchar.h +++ b/StdLib/Include/wchar.h @@ -510,7 +510,7 @@ wint_t btowc(int c); character set whose multibyte character representation is a single byte when in the initial shift state. - @Returns The wctob function returns EOF if c does not correspond to a multibyte + @return The wctob function returns EOF if c does not correspond to a multibyte character with length one in the initial shift state. Otherwise, it returns the single-byte representation of that character as an unsigned char converted to an int. @@ -520,7 +520,7 @@ int wctob(wint_t c); /** If ps is not a null pointer, the mbsinit function determines whether the pointed-to mbstate_t object describes an initial conversion state. - @Returns The mbsinit function returns nonzero if ps is a null pointer + @return The mbsinit function returns nonzero if ps is a null pointer or if the pointed-to object describes an initial conversion state; otherwise, it returns zero. **/ @@ -564,7 +564,7 @@ size_t mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t terminating null wide character, the resulting state described is the initial conversion state. - @Returns If conversion stops because a wide character is reached that + @return If conversion stops because a wide character is reached that does not correspond to a valid multibyte character, an encoding error occurs: the wcsrtombs function stores the value of the macro EILSEQ in errno and returns (size_t)(-1); diff --git a/StdLib/LibC/Uefi/SysCalls.c b/StdLib/LibC/Uefi/SysCalls.c index d2fb0c6af6..d52249b58b 100644 --- a/StdLib/LibC/Uefi/SysCalls.c +++ b/StdLib/LibC/Uefi/SysCalls.c @@ -651,7 +651,7 @@ open( @param [in] timeout Length of time in milliseconds to wait for the event - @returns The number of file descriptors with detected events. Zero + @return The number of file descriptors with detected events. Zero indicates that the call timed out and -1 indicates an error. **/ @@ -1100,12 +1100,12 @@ write (int fd, const void *buf, size_t nbyte) /** Gets the current working directory. - The getcwd() function shall place an absolute pathname of the current - working directory in the array pointed to by buf, and return buf. The - pathname copied to the array shall contain no components that are - symbolic links. The size argument is the size in bytes of the character - array pointed to by the buf argument. - + The getcwd() function shall place an absolute pathname of the current + working directory in the array pointed to by buf, and return buf. The + pathname copied to the array shall contain no components that are + symbolic links. The size argument is the size in bytes of the character + array pointed to by the buf argument. + @param[in,out] buf The buffer to fill. @param[in] size The number of bytes in buffer. @@ -1114,8 +1114,8 @@ write (int fd, const void *buf, size_t nbyte) @retval NULL Size was 0. @return buf The function completed successfully. See errno for info. **/ -char -*getcwd (char *buf, size_t size) +char +*getcwd (char *buf, size_t size) { CONST CHAR16 *Cwd; @@ -1133,7 +1133,7 @@ char errno = ERANGE; return (NULL); } - + return (UnicodeStrToAsciiStr(Cwd, buf)); }