@param [in] pDigit The address of the next digit\r
@param [out] pValue The address to receive the value\r
\r
- @returns Returns the address of the separator\r
+ @return Returns the address of the separator\r
\r
**/\r
CHAR8 *\r
//\r
if ( HandleCount <= Tcp4Index ) {\r
Tcp4Index = 0;\r
- \r
+\r
//\r
// Wait for the next timer tick\r
//\r
htons ( RemoteHostAddress.sin_port ));\r
bTcp4Connecting = FALSE;\r
}\r
- \r
+\r
//\r
// Open the network controller's service protocol\r
//\r
Status = pTcp4Protocol->Configure ( pTcp4Protocol,\r
&Tcp4ConfigData );\r
if ( EFI_ERROR ( Status )) {\r
- DEBUG (( DEBUG_ERROR, \r
+ DEBUG (( DEBUG_ERROR,\r
"ERROR - Failed to configure TCP port, Status: %r\r\n",\r
Status ));\r
break;\r
-/*++
- This file contains an 'Intel UEFI Application' and is
- licensed for Intel CPUs and chipsets under the terms of your
- license agreement with Intel or your vendor. This file may
- be modified by the user, subject to additional terms of the
- license agreement
---*/
-/*++
-
-Copyright (c) 2011 Intel Corporation. All rights reserved
-This software and associated documentation (if any) is furnished
-under a license and may only be used or copied in accordance
-with the terms of the license. Except as permitted by such
-license, no part of this software or documentation may be
-reproduced, stored in a retrieval system, or transmitted in any
-form or by any means without the express written consent of
-Intel Corporation.
-
---*/
-
-/** @file
- This is a simple TFTP server application
-
-**/
-
-#include <TftpServer.h>
-
-TSDT_TFTP_SERVER mTftpServer; ///< TFTP server's control structure
-
-
-/**
- Add a connection context to the list of connection contexts.
-
- @param [in] pTftpServer The TFTP server control structure address.
-
- @retval Context structure address, NULL if allocation fails
-
-**/
-TSDT_CONNECTION_CONTEXT *
-ContextAdd (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- size_t LengthInBytes;
- TSDT_CONNECTION_CONTEXT * pContext;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Allocate a new context
- //
- LengthInBytes = sizeof ( *pContext );
- Status = gBS->AllocatePool ( EfiRuntimeServicesData,
- LengthInBytes,
- (VOID **)&pContext );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DEBUG_POOL,
- "ERROR - Failed to allocate the context, Status: %r\r\n",
- Status ));
- pContext = NULL;
- break;
- }
-
- //
- // Initialize the context
- //
- ZeroMem ( pContext, LengthInBytes );
- CopyMem ( &pContext->RemoteAddress,
- &pTftpServer->RemoteAddress,
- sizeof ( pContext->RemoteAddress ));
- pContext->BlockSize = TFTP_MAX_BLOCK_SIZE;
- pContext->pBuffer = &pContext->FileData[0];
- pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )];
- pContext->MaxTransferSize = 0;
- pContext->MaxTransferSize -= 1;
-
- //
- // Display the new context
- //
- DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,
- "0x%08x: Context for %d.%d.%d.%d:%d\r\n",
- pContext,
- (UINT8)pContext->RemoteAddress.sin_addr.s_addr,
- (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ),
- (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ),
- (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ),
- htons ( pContext->RemoteAddress.sin_port )));
-
- //
- // Add the context to the context list
- //
- pContext->pNext = pTftpServer->pContextList;
- pTftpServer->pContextList = pContext;
-
- //
- // All done
- //
- break;
- }
-
- //
- // Return the connection context
- //
- DBG_EXIT_STATUS ( pContext );
- return pContext;
-}
-
-
-/**
- Locate a remote connection context.
-
- @param [in] pTftpServer The TFTP server control structure address.
-
- @param [in] pIpAddress The start of the remote IP address in network order
-
- @param [in] Port The remote port number
-
- @retval Context structure address, NULL if not found
-
-**/
-TSDT_CONNECTION_CONTEXT *
-ContextFind (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- TSDT_CONNECTION_CONTEXT * pContext;
-
- DBG_ENTER ( );
-
- //
- // Walk the list of connection contexts
- //
- pContext = pTftpServer->pContextList;
- while ( NULL != pContext ) {
- //
- // Attempt to locate the remote network connection
- //
- if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr )
- && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) {
- //
- // The connection was found
- //
- DEBUG (( DEBUG_TFTP_REQUEST,
- "0x%08x: pContext found\r\n",
- pContext ));
- break;
- }
-
- //
- // Set the next context
- //
- pContext = pContext->pNext;
- }
-
- //
- // Return the connection context structure address
- //
- DBG_EXIT_HEX ( pContext );
- return pContext;
-}
-
-
-/**
- Remove a context from the list.
-
- @param [in] pTftpServer The TFTP server control structure address.
-
- @param [in] pContext The context structure address.
-
-**/
-VOID
-ContextRemove (
- IN TSDT_TFTP_SERVER * pTftpServer,
- IN TSDT_CONNECTION_CONTEXT * pContext
- )
-{
- TSDT_CONNECTION_CONTEXT * pNextContext;
- TSDT_CONNECTION_CONTEXT * pPreviousContext;
-
- DBG_ENTER ( );
-
- //
- // Attempt to locate the context in the list
- //
- pPreviousContext = NULL;
- pNextContext = pTftpServer->pContextList;
- while ( NULL != pNextContext ) {
- //
- // Determine if the context was found
- //
- if ( pNextContext == pContext ) {
- //
- // Remove the context from the list
- //
- if ( NULL == pPreviousContext ) {
- pTftpServer->pContextList = pContext->pNext;
- }
- else {
- pPreviousContext->pNext = pContext->pNext;
- }
- break;
- }
-
- //
- // Set the next context
- //
- pPreviousContext = pNextContext;
- pNextContext = pNextContext->pNext;
- }
-
- //
- // Determine if the context was found
- //
- if ( NULL != pContext ) {
- //
- // Return the resources
- //
- gBS->FreePool ( pContext );
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Process the work for the sockets.
-
- @param [in] pTftpServer The TFTP server control structure address.
-
-**/
-VOID
-PortWork (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- TSDT_CONNECTION_CONTEXT * pContext;
- socklen_t RemoteAddressLength;
-
- DBG_ENTER ( );
-
- //
- // Handle input events
- //
- if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) {
- //
- // Receive the message from the remote system
- //
- RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );
- pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd,
- &pTftpServer->RxBuffer[0],
- sizeof ( pTftpServer->RxBuffer ),
- 0,
- (struct sockaddr *) &pTftpServer->RemoteAddress,
- &RemoteAddressLength );
- if ( -1 != pTftpServer->RxBytes ) {
- pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength;
- DEBUG (( DEBUG_TFTP_PORT,
- "Received %d bytes from %d.%d.%d.%d:%d\r\n",
- pTftpServer->RxBytes,
- pTftpServer->RemoteAddress.sin_addr.s_addr & 0xff,
- ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
- ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
- ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
- htons ( pTftpServer->RemoteAddress.sin_port )));
-
- //
- // Lookup connection context using the remote system address and port
- // to determine if an existing connection to this remote
- // system exists
- //
- pContext = ContextFind ( pTftpServer );
-
- //
- // Process the received message
- //
- TftpProcessRequest ( pTftpServer, pContext );
- }
- else {
- //
- // Receive error on the TFTP server port
- // Close the server socket
- //
- DEBUG (( DEBUG_ERROR,
- "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",
- errno ));
- pTftpServer->TftpPort.revents |= POLLHUP;
- }
- }
-
- //
- // Handle the close event
- //
- if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) {
- //
- // Close the port
- //
- close ( pTftpServer->TftpPort.fd );
- pTftpServer->TftpPort.fd = -1;
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Scan the list of sockets and process any pending work
-
- @param [in] pTftpServer The TFTP server control structure address.
-
-**/
-VOID
-SocketPoll (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- int FDCount;
-
- DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));
-
- //
- // Determine if any ports are active
- //
- FDCount = poll ( &pTftpServer->TftpPort,
- 1,
- CLIENT_POLL_DELAY );
- if ( -1 == FDCount ) {
- DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL,
- "ERROR - errno: %d\r\n",
- errno ));
- }
-
- if ( 0 < FDCount ) {
- //
- // Process this port
- //
- PortWork ( pTftpServer );
- pTftpServer->TftpPort.revents = 0;
- }
-
- DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));
-}
-
-
-/**
- Convert a character to lower case
-
- @param [in] Character The character to convert
-
- @returns The lower case equivalent of the character
-
-**/
-int
-tolower (
- int Character
- )
-{
- //
- // Determine if the character is upper case
- //
- if (( 'A' <= Character ) && ( 'Z' >= Character )) {
- //
- // Convert the character to lower caes
- //
- Character += 'a' - 'A';
- }
-
- //
- // Return the converted character
- //
- return Character;
-}
-
-
-/**
- Case independent string comparison
-
- @param [in] pString1 Zero terminated string address
- @param [in] pString2 Zero terminated string address
-
- @returns Returns the first character difference between string 1
- and string 2.
-
-**/
-int
-stricmp (
- char * pString1,
- char * pString2
- )
-{
- int Char1;
- int Char2;
- int Difference;
-
- //
- // Walk the length of the strings
- //
- do {
- //
- // Get the next characters
- //
- Char1 = (UINT8)*pString1++;
- Char2 = (UINT8)*pString2++;
-
- //
- // Convert them to lower case
- //
- Char1 = tolower ( Char1 );
- Char2 = tolower ( Char2 );
-
- //
- // Done when the characters differ
- //
- Difference = Char1 - Char2;
- if ( 0 != Difference ) {
- break;
- }
-
- //
- // Done at the end of the string
- //
- } while ( 0 != Char1 );
-
- //
- // Return the difference
- //
- return Difference;
-}
-
-
-/**
- Get the next TFTP option
-
- @param [in] pOption Address of a zero terminated option string
- @param [in] pEnd End of buffer address
- @param [in] ppNextOption Address to receive the address of the next
- zero terminated option string
-
- @retval EFI_SUCCESS Message processed successfully
-
-**/
-EFI_STATUS
-TftpOptionGet (
- IN UINT8 * pOption,
- IN UINT8 * pEnd,
- IN UINT8 ** ppNextOption
- )
-{
- UINT8 * pNextOption;
- EFI_STATUS Status;
-
- //
- // Locate the end of the option
- //
- pNextOption = pOption;
- while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {
- pNextOption += 1;
- }
- if ( pEnd <= pNextOption ) {
- //
- // Error - end of buffer reached
- //
- DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
- "ERROR - Option without zero termination received!\r\n" ));
- Status = EFI_INVALID_PARAMETER;
- }
- else {
- //
- // Zero terminated option found
- //
- pNextOption += 1;
-
- //
- // Display the zero terminated ASCII option string
- //
- DEBUG (( DEBUG_TFTP_REQUEST,
- "Option: %a\r\n",
- pOption ));
- Status = EFI_SUCCESS;
- }
-
- //
- // Return the next option address
- //
- *ppNextOption = pNextOption;
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Place an option value into the option acknowledgement
-
- @param [in] pOack Option acknowledgement address
- @param [in] Value Value to translate into ASCII decimal
-
- @returns Option acknowledgement address
-
-**/
-UINT8 *
-TftpOptionSet (
- IN UINT8 * pOack,
- IN UINT64 Value
- )
-{
- UINT64 NextValue;
-
- //
- // Determine the next value
- //
- NextValue = Value / 10;
-
- //
- // Supress leading zeros
- //
- if ( 0 != NextValue ) {
- pOack = TftpOptionSet ( pOack, NextValue );
- }
-
- //
- // Output this digit
- //
- *pOack++ = (UINT8)( Value - ( NextValue * 10 ) + '0' );
-
- //
- // Return the next option acknowledgement location
- //
- return pOack;
-}
-
-
-/**
- Process the TFTP request
-
- @param [in] pContext The context structure address.
- @param [in] pOption Address of the first zero terminated option string
- @param [in] pEnd End of buffer address
-
-**/
-VOID
-TftpOptions (
- IN TSDT_CONNECTION_CONTEXT * pContext,
- IN UINT8 * pOption,
- IN UINT8 * pEnd
- )
-{
- UINT8 * pNextOption;
- UINT8 * pOack;
- UINT8 * pTemp;
- UINT8 * pValue;
- EFI_STATUS Status;
- INT32 Value;
-
- //
- // Start the OACK packet
- // Let the OACK handle the parsing errors
- // See http://tools.ietf.org/html/rfc2347
- //
- pOack = &pContext->TxBuffer[0];
- *pOack++ = 0;
- *pOack++ = TFTP_OP_OACK;
- pContext->TxBytes = 2;
-
- //
- // Walk the list of options
- //
- do {
- //
- // Get the next option, skip junk at end of message
- //
- Status = TftpOptionGet ( pOption, pEnd, &pNextOption );
- if ( !EFI_ERROR ( Status )) {
- //
- // Process the option
- //
-
- //
- // blksize - See http://tools.ietf.org/html/rfc2348
- //
- pValue = pNextOption;
- if ( 0 == stricmp ((char *)pOption, "blksize" )) {
- //
- // Get the value
- //
- Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
- if ( !EFI_ERROR ( Status )) {
- //
- // Validate the block size, skip non-numeric block sizes
- //
- Status = TftpOptionValue ( pValue, &Value );
- if ( !EFI_ERROR ( Status )) {
- //
- // Propose a smaller block size if necessary
- //
- if ( Value > TFTP_MAX_BLOCK_SIZE ) {
- Value = TFTP_MAX_BLOCK_SIZE;
- }
-
- //
- // Set the new block size
- //
- pContext->BlockSize = Value;
- DEBUG (( DEBUG_TFTP_REQUEST,
- "Using block size of %d bytes\r\n",
- pContext->BlockSize ));
-
- //
- // Update the OACK
- //
- pTemp = pOack;
- *pOack++ = 'b';
- *pOack++ = 'l';
- *pOack++ = 'k';
- *pOack++ = 's';
- *pOack++ = 'i';
- *pOack++ = 'z';
- *pOack++ = 'e';
- *pOack++ = 0;
- pOack = TftpOptionSet ( pOack, pContext->BlockSize );
- *pOack++ = 0;
- pContext->TxBytes += pOack - pTemp;
- }
- }
- }
-
- //
- // timeout - See http://tools.ietf.org/html/rfc2349
- //
- else if ( 0 == stricmp ((char *)pOption, "timeout" )) {
- //
- // Get the value
- //
- Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
- if ( !EFI_ERROR ( Status )) {
- Status = TftpOptionValue ( pValue, &Value );
- if ( !EFI_ERROR ( Status )) {
- //
- // Set the timeout value
- //
- pContext->Timeout = Value;
- DEBUG (( DEBUG_TFTP_REQUEST,
- "Using timeout of %d seconds\r\n",
- pContext->Timeout ));
-
- //
- // Update the OACK
- //
- pTemp = pOack;
- *pOack++ = 't';
- *pOack++ = 'i';
- *pOack++ = 'm';
- *pOack++ = 'e';
- *pOack++ = 'o';
- *pOack++ = 'u';
- *pOack++ = 't';
- *pOack++ = 0;
- pOack = TftpOptionSet ( pOack, pContext->Timeout );
- *pOack++ = 0;
- pContext->TxBytes += pOack - pTemp;
- }
- }
- }
-
- //
- // tsize - See http://tools.ietf.org/html/rfc2349
- //
- else if ( 0 == stricmp ((char *)pOption, "tsize" )) {
- //
- // Get the value
- //
- Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
- if ( !EFI_ERROR ( Status )) {
- Status = TftpOptionValue ( pValue, &Value );
- if ( !EFI_ERROR ( Status )) {
- //
- // Return the file size
- //
- DEBUG (( DEBUG_TFTP_REQUEST,
- "Returning file size of %Ld bytes\r\n",
- pContext->LengthInBytes ));
-
- //
- // Update the OACK
- //
- pTemp = pOack;
- *pOack++ = 't';
- *pOack++ = 's';
- *pOack++ = 'i';
- *pOack++ = 'z';
- *pOack++ = 'e';
- *pOack++ = 0;
- pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );
- *pOack++ = 0;
- pContext->TxBytes += pOack - pTemp;
- }
- }
- }
- else {
- //
- // Unknown option - Ignore it
- //
- DEBUG (( DEBUG_WARN | DEBUG_TFTP_REQUEST,
- "WARNING - Skipping unknown option: %a\r\n",
- pOption ));
- }
- }
-
- //
- // Set the next option
- //
- pOption = pNextOption;
- } while ( pEnd > pOption );
-}
-
-
-/**
- Process the TFTP request
-
- @param [in] pOption Address of the first zero terminated option string
- @param [in] pValue Address to receive the value
-
- @retval EFI_SUCCESS Option translated into a value
-
-**/
-EFI_STATUS
-TftpOptionValue (
- IN UINT8 * pOption,
- IN INT32 * pValue
- )
-{
- UINT8 Digit;
- EFI_STATUS Status;
- INT32 Value;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Walk the characters in the option
- //
- Value = 0;
- while ( 0 != *pOption ) {
- //
- // Convert the next digit to binary
- //
- Digit = *pOption++;
- if (( '0' <= Digit ) && ( '9' >= Digit )) {
- Value *= 10;
- Value += Digit - '0';
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
- "ERROR - Invalid character '0x%02x' in the value\r\n",
- Digit ));
- Status = EFI_INVALID_PARAMETER;
- break;
- }
- }
-
- //
- // Return the value
- //
- *pValue = Value;
-
- //
- // Return the conversion status
- //
- return Status;
-}
-
-
-/**
- Process the TFTP request
-
- @param [in] pTftpServer The TFTP server control structure address.
- @param [in] pContext Connection context structure address
-
-**/
-VOID
-TftpProcessRequest (
- IN TSDT_TFTP_SERVER * pTftpServer,
- IN TSDT_CONNECTION_CONTEXT * pContext
- )
-{
- BOOLEAN bCloseContext;
- BOOLEAN bIgnorePacket;
- UINT16 BlockNumber;
- UINT16 Opcode;
- UINT8 * pBuffer;
- UINT8 * pEnd;
- UINT8 * pFileName;
- UINT8 * pMode;
- UINT8 * pOption;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Get the opcode
- //
- pBuffer = &pTftpServer->RxBuffer[0];
- Opcode = HTONS ( *(UINT16 *)&pBuffer[0]);
-Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode );
-
- //
- // Validate the parameters
- //
- bCloseContext = FALSE;
- bIgnorePacket = FALSE;
- switch ( Opcode ) {
- default:
- DEBUG (( DEBUG_TFTP_REQUEST,
- "ERROR - Unknown TFTP opcode: %d\r\n",
- Opcode ));
- bIgnorePacket = TRUE;
- break;
-
- case TFTP_OP_READ_REQUEST:
- break;
-
- case TFTP_OP_DATA:
- if ( NULL == pContext ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
- (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
- htons ( pTftpServer->RemoteAddress.sin_port )));
- bIgnorePacket = TRUE;
- break;
- }
- if ( pContext->bExpectAck ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",
- pContext ));
- bIgnorePacket = TRUE;
- break;
- }
- if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 ))
- {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Receive data length of %d > %d bytes (maximum block size) for pContext 0x%08x\r\n",
- pTftpServer->RxBytes - 2 - 2,
- pContext->BlockSize,
- pContext ));
- bIgnorePacket = TRUE;
- break;
- }
- break;
-
- case TFTP_OP_ACK:
- if ( NULL == pContext ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
- (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
- htons ( pTftpServer->RemoteAddress.sin_port )));
- bIgnorePacket = TRUE;
- }
- if ( !pContext->bExpectAck ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",
- pContext ));
- bIgnorePacket = TRUE;
- break;
- }
- break;
-
- case TFTP_OP_ERROR:
- if ( NULL == pContext ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
- (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
- (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
- htons ( pTftpServer->RemoteAddress.sin_port )));
- bIgnorePacket = TRUE;
- }
- break;
- }
- if ( !bIgnorePacket ) {
- //
- // Process the request
- //
- switch ( Opcode ) {
- default:
- DEBUG (( DEBUG_TFTP_REQUEST,
- "ERROR - Unable to process TFTP opcode: %d\r\n",
- Opcode ));
- break;
-
- case TFTP_OP_READ_REQUEST:
-
- //
- // Close the context if necessary
- //
- if ( NULL != pContext ) {
- ContextRemove ( pTftpServer, pContext );
- }
-
- //
- // Create the connection context
- //
- pContext = ContextAdd ( pTftpServer );
- if ( NULL == pContext ) {
- break;
- }
-
- //
- // Locate the mode
- //
- pFileName = &pBuffer[2];
- pEnd = &pBuffer[pTftpServer->RxBytes];
- pMode = pFileName;
- while (( pEnd > pMode ) && ( 0 != *pMode )) {
- pMode += 1;
- }
- if ( pEnd <= pMode ) {
- //
- // Mode not found
- //
- DEBUG (( DEBUG_ERROR | DEBUG_RX,
- "ERROR - File mode not found\r\n" ));
- //
- // Tell the client of the error
- //
- TftpSendError ( pTftpServer,
- pContext,
- 0,
- (UINT8 *)"File open mode not found" );
- break;
- }
- pMode += 1;
- DEBUG (( DEBUG_TFTP_REQUEST,
- "TFTP - FileName: %a\n",
- pFileName ));
-
- //
- // Locate the options
- //
- pOption = pMode;
- while (( pEnd > pOption ) && ( 0 != *pOption )) {
- pOption += 1;
- }
- if ( pEnd <= pOption ) {
- //
- // End of mode not found
- //
- DEBUG (( DEBUG_ERROR | DEBUG_RX,
- "ERROR - File mode not valid\r\n" ));
- //
- // Tell the client of the error
- //
- TftpSendError ( pTftpServer,
- pContext,
- 0,
- (UINT8 *)"File open mode not valid" );
- break;
- }
- pOption += 1;
- DEBUG (( DEBUG_TFTP_REQUEST,
- "TFTP - Mode: %a\r\n",
- pMode ));
-
- //
- // Verify the mode is supported
- //
- if ( 0 != stricmp ((char *)pMode, "octet" )) {
- //
- // File access mode not supported
- //
- DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,
- "ERROR - File mode %a not supported\r\n",
- pMode ));
-
- //
- // Tell the client of the error
- //
- TftpSendError ( pTftpServer,
- pContext,
- 0,
- (UINT8 *)"File open mode not supported" );
- break;
- }
-
- //
- // Open the file, close the context on error
- //
-// TODO: Remove the following line
-pContext->File = (EFI_HANDLE)1;
-
- //
- // Determine the file length
- //
-//fstat
-
- //
- // Process the options
- //
- TftpOptions ( pContext, pOption, pEnd );
-
- //
- // Read in the first portion of the file
- //
-
- //
- // Send the first block
- //
- pContext->bExpectAck = TRUE;
- if ( 2 < pContext->TxBytes ) {
- //
- // Send the OACK
- //
- Status = TftpTxPacket ( pTftpServer, pContext );
- }
- else {
- //
- // Send the first block of data
- //
- Status = TftpSendNextBlock ( pTftpServer, pContext );
- }
- break;
-
- case TFTP_OP_ACK:
- //
- // Get the block number that is being ACKed
- //
- BlockNumber = pTftpServer->RxBuffer[2];
- BlockNumber <<= 8;
- BlockNumber |= pTftpServer->RxBuffer[3];
-
- //
- // Determine if this is the correct ACK
- //
- DEBUG (( DEBUG_TFTP_ACK,
- "ACK for block 0x%04x received\r\n",
- BlockNumber ));
- if (( !pContext->bExpectAck )
- || ( BlockNumber != pContext->AckNext ))
- {
- DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK,
- "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",
- pContext->AckNext,
- BlockNumber ));
- }
- else {
- //
- // Process the expected ACK
- //
- if ( pContext->bEofSent ) {
- bCloseContext = TRUE;
- }
- else {
- //
- // Set the next expected ACK
- //
- pContext->AckNext += 1;
-
- //
- // Send the next packet of data
- //
- Status = TftpSendNextBlock ( pTftpServer, pContext );
- }
- }
- break;
- }
- }
-
- //
- // Determine if the context should be closed
- //
- if ( bCloseContext ) {
- ContextRemove ( pTftpServer, pContext );
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Build and send an error packet
-
- @param [in] pTftpServer The TFTP server control structure address.
- @param [in] pContext The context structure address.
- @param [in] Error Error number for the packet
- @param [in] pError Zero terminated error string address
-
- @retval EFI_SUCCESS Message processed successfully
-
-**/
-EFI_STATUS
-TftpSendError (
- IN TSDT_TFTP_SERVER * pTftpServer,
- IN TSDT_CONNECTION_CONTEXT * pContext,
- IN UINT16 Error,
- IN UINT8 * pError
- )
-{
- UINT8 Character;
- UINT8 * pBuffer;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Build the error packet
- //
- pBuffer = &pContext->TxBuffer[0];
- pBuffer[0] = 0;
- pBuffer[1] = TFTP_OP_ERROR;
- pBuffer[2] = (UINT8)( Error >> 8 );
- pBuffer[3] = (UINT8)Error;
-
- //
- // Copy the zero terminated string into the buffer
- //
- pBuffer += 4;
- do {
- Character = *pError++;
- *pBuffer++ = Character;
- } while ( 0 != Character );
-
- //
- // Send the error message
- //
- pContext->TxBytes = pBuffer - &pContext->TxBuffer[0];
- Status = TftpTxPacket ( pTftpServer, pContext );
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Send the next block of file system data
-
- @param [in] pTftpServer The TFTP server control structure address.
- @param [in] pContext The context structure address.
-
- @retval EFI_SUCCESS Message processed successfully
-
-**/
-EFI_STATUS
-TftpSendNextBlock (
- IN TSDT_TFTP_SERVER * pTftpServer,
- IN TSDT_CONNECTION_CONTEXT * pContext
- )
-{
- ssize_t LengthInBytes;
- UINT8 * pBuffer;
- EFI_STATUS Status;
-
- //
- // Determine how much data needs to be sent
- //
- LengthInBytes = pContext->BlockSize;
- if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE )
- || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) {
- LengthInBytes = (ssize_t)pContext->LengthInBytes;
- pContext->bEofSent = TRUE;
- }
-
- //
- // Set the TFTP opcode and block number
- //
- pBuffer = &pContext->TxBuffer[0];
- *pBuffer++ = 0;
- *pBuffer++ = TFTP_OP_DATA;
- *pBuffer++ = (UINT8)( pContext->AckNext >> 8 );
- *pBuffer++ = (UINT8)pContext->AckNext;
-
- //
- // Copy the file data into the transmit buffer
- //
- pContext->TxBytes = 2 + 2 + LengthInBytes;
- if ( 0 < LengthInBytes ) {
- CopyMem ( &pBuffer,
- pContext->pBuffer,
- LengthInBytes );
- }
-
- //
- // Send the next block
- //
- Status = TftpTxPacket ( pTftpServer, pContext );
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Create the port for the TFTP server
-
- This routine polls the network layer to create the TFTP port for the
- TFTP server. More than one attempt may be necessary since it may take
- some time to get the IP address and initialize the upper layers of
- the network stack.
-
- @param [in] pTftpServer The TFTP server control structure address.
-
-**/
-VOID
-TftpServerTimer (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- UINT16 TftpPort;
- int SocketStatus;
- EFI_STATUS Status;
-
- DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" ));
-
- //
- // Open the TFTP port on the server
- //
- do {
- do {
- //
- // Wait for a while
- //
- Status = gBS->CheckEvent ( pTftpServer->TimerEvent );
- } while ( EFI_SUCCESS != Status );
-
- //
- // Attempt to create the socket for the TFTP server
- //
- pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP;
- pTftpServer->TftpPort.revents = 0;
- pTftpServer->TftpPort.fd = socket ( AF_INET,
- SOCK_DGRAM,
- IPPROTO_UDP );
- if ( -1 != pTftpServer->TftpPort.fd )
- {
- //
- // Set the socket address
- //
- ZeroMem ( &pTftpServer->TftpServerAddress,
- sizeof ( pTftpServer->TftpServerAddress ));
- TftpPort = 69;
- DEBUG (( DEBUG_TFTP_PORT,
- "TFTP Port: %d\r\n",
- TftpPort ));
- pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress );
- pTftpServer->TftpServerAddress.sin_family = AF_INET;
- pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY;
- pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort );
-
- //
- // Bind the socket to the TFTP port
- //
- SocketStatus = bind ( pTftpServer->TftpPort.fd,
- (struct sockaddr *) &pTftpServer->TftpServerAddress,
- pTftpServer->TftpServerAddress.sin_len );
- if ( -1 != SocketStatus ) {
- DEBUG (( DEBUG_TFTP_PORT,
- "0x%08x: Socket bound to port %d\r\n",
- pTftpServer->TftpPort.fd,
- TftpPort ));
- }
-
- //
- // Release the socket if necessary
- //
- if ( -1 == SocketStatus ) {
- close ( pTftpServer->TftpPort.fd );
- pTftpServer->TftpPort.fd = -1;
- }
- }
-
- //
- // Wait until the socket is open
- //
- }while ( -1 == pTftpServer->TftpPort.fd );
-
- DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" ));
-}
-
-
-/**
- Start the TFTP server port creation timer
-
- @param [in] pTftpServer The TFTP server control structure address.
-
- @retval EFI_SUCCESS The timer was successfully started.
- @retval EFI_ALREADY_STARTED The timer is already running.
- @retval Other The timer failed to start.
-
-**/
-EFI_STATUS
-TftpServerTimerStart (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- EFI_STATUS Status;
- UINT64 TriggerTime;
-
- DBG_ENTER ( );
-
- //
- // Assume the timer is already running
- //
- Status = EFI_ALREADY_STARTED;
- if ( !pTftpServer->bTimerRunning ) {
- //
- // Compute the poll interval
- //
- TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );
- Status = gBS->SetTimer ( pTftpServer->TimerEvent,
- TimerPeriodic,
- TriggerTime );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));
-
- //
- // Mark the timer running
- //
- pTftpServer->bTimerRunning = TRUE;
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,
- "ERROR - Failed to start TFTP port timer, Status: %r\r\n",
- Status ));
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Stop the TFTP server port creation timer
-
- @param [in] pTftpServer The TFTP server control structure address.
-
- @retval EFI_SUCCESS The TFTP port timer is stopped
- @retval Other Failed to stop the TFTP port timer
-
-**/
-EFI_STATUS
-TftpServerTimerStop (
- IN TSDT_TFTP_SERVER * pTftpServer
- )
-{
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume the timer is stopped
- //
- Status = EFI_SUCCESS;
- if ( pTftpServer->bTimerRunning ) {
- //
- // Stop the port creation polling
- //
- Status = gBS->SetTimer ( pTftpServer->TimerEvent,
- TimerCancel,
- 0 );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" ));
-
- //
- // Mark the timer stopped
- //
- pTftpServer->bTimerRunning = FALSE;
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,
- "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n",
- Status ));
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-/**
- Send the next TFTP packet
-
- @param [in] pTftpServer The TFTP server control structure address.
- @param [in] pContext The context structure address.
-
- @retval EFI_SUCCESS Message processed successfully
-
-**/
-EFI_STATUS
-TftpTxPacket (
- IN TSDT_TFTP_SERVER * pTftpServer,
- IN TSDT_CONNECTION_CONTEXT * pContext
- )
-{
- ssize_t LengthInBytes;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Send the TFTP packet
- //
- DEBUG (( DEBUG_TX,
- "0x%08x: pContext sending 0x%08x bytes\r\n",
- pContext,
- pContext->TxBytes ));
- LengthInBytes = sendto ( pTftpServer->TftpPort.fd,
- &pContext->TxBuffer[0],
- pContext->TxBytes,
- 0,
- (struct sockaddr *)&pContext->RemoteAddress,
- pContext->RemoteAddress.sin_len );
- if ( -1 == LengthInBytes ) {
- DEBUG (( DEBUG_ERROR | DEBUG_TX,
- "ERROR - Transmit failure, errno: 0x%08x\r\n",
- errno ));
- Status = EFI_DEVICE_ERROR;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Entry point for the TFTP server application.
-
- @param [in] Argc The number of arguments
- @param [in] Argv The argument value array
-
- @retval 0 The application exited normally.
- @retval Other An error occurred.
-**/
-int
-main (
- IN int Argc,
- IN char **Argv
- )
-{
- TSDT_TFTP_SERVER * pTftpServer;
- EFI_STATUS Status;
-
- //
- // Create a timer event to start TFTP port
- //
- pTftpServer = &mTftpServer;
- Status = gBS->CreateEvent ( EVT_TIMER,
- TPL_TFTP_SERVER,
- NULL,
- NULL,
- &pTftpServer->TimerEvent );
- if ( !EFI_ERROR ( Status )) {
- Status = TftpServerTimerStart ( pTftpServer );
- if ( !EFI_ERROR ( Status )) {
- //
- // Run the TFTP server forever
- //
- for ( ; ; ) {
- //
- // Poll the network layer to create the TFTP port
- // for the tftp server. More than one attempt may
- // be necessary since it may take some time to get
- // the IP address and initialize the upper layers
- // of the network stack.
- //
- TftpServerTimer ( pTftpServer );
-
- //
- // Poll the socket for activity
- //
- do {
- SocketPoll ( pTftpServer );
- } while ( -1 != pTftpServer->TftpPort.fd );
-
-//
-// TODO: Remove the following test code
-// Exit when the network connection is broken
-//
-break;
- }
-
- //
- // Done with the timer event
- //
- TftpServerTimerStop ( pTftpServer );
- Status = gBS->CloseEvent ( pTftpServer->TimerEvent );
- }
- }
-
- //
- // Return the final status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
+/*++\r
+ This file contains an 'Intel UEFI Application' and is\r
+ licensed for Intel CPUs and chipsets under the terms of your\r
+ license agreement with Intel or your vendor. This file may\r
+ be modified by the user, subject to additional terms of the\r
+ license agreement\r
+--*/\r
+/*++\r
+\r
+Copyright (c) 2011 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+--*/\r
+\r
+/** @file\r
+ This is a simple TFTP server application\r
+\r
+**/\r
+\r
+#include <TftpServer.h>\r
+\r
+TSDT_TFTP_SERVER mTftpServer; ///< TFTP server's control structure\r
+\r
+\r
+/**\r
+ Add a connection context to the list of connection contexts.\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+ @retval Context structure address, NULL if allocation fails\r
+\r
+**/\r
+TSDT_CONNECTION_CONTEXT *\r
+ContextAdd (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ size_t LengthInBytes;\r
+ TSDT_CONNECTION_CONTEXT * pContext;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Allocate a new context\r
+ //\r
+ LengthInBytes = sizeof ( *pContext );\r
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r
+ LengthInBytes,\r
+ (VOID **)&pContext );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+ "ERROR - Failed to allocate the context, Status: %r\r\n",\r
+ Status ));\r
+ pContext = NULL;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Initialize the context\r
+ //\r
+ ZeroMem ( pContext, LengthInBytes );\r
+ CopyMem ( &pContext->RemoteAddress,\r
+ &pTftpServer->RemoteAddress,\r
+ sizeof ( pContext->RemoteAddress ));\r
+ pContext->BlockSize = TFTP_MAX_BLOCK_SIZE;\r
+ pContext->pBuffer = &pContext->FileData[0];\r
+ pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )];\r
+ pContext->MaxTransferSize = 0;\r
+ pContext->MaxTransferSize -= 1;\r
+\r
+ //\r
+ // Display the new context\r
+ //\r
+ DEBUG (( DEBUG_PORT_WORK | DEBUG_INFO,\r
+ "0x%08x: Context for %d.%d.%d.%d:%d\r\n",\r
+ pContext,\r
+ (UINT8)pContext->RemoteAddress.sin_addr.s_addr,\r
+ (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ),\r
+ (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ),\r
+ (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ),\r
+ htons ( pContext->RemoteAddress.sin_port )));\r
+\r
+ //\r
+ // Add the context to the context list\r
+ //\r
+ pContext->pNext = pTftpServer->pContextList;\r
+ pTftpServer->pContextList = pContext;\r
+\r
+ //\r
+ // All done\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the connection context\r
+ //\r
+ DBG_EXIT_STATUS ( pContext );\r
+ return pContext;\r
+}\r
+\r
+\r
+/**\r
+ Locate a remote connection context.\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+ @param [in] pIpAddress The start of the remote IP address in network order\r
+\r
+ @param [in] Port The remote port number\r
+\r
+ @retval Context structure address, NULL if not found\r
+\r
+**/\r
+TSDT_CONNECTION_CONTEXT *\r
+ContextFind (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ TSDT_CONNECTION_CONTEXT * pContext;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Walk the list of connection contexts\r
+ //\r
+ pContext = pTftpServer->pContextList;\r
+ while ( NULL != pContext ) {\r
+ //\r
+ // Attempt to locate the remote network connection\r
+ //\r
+ if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr )\r
+ && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) {\r
+ //\r
+ // The connection was found\r
+ //\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "0x%08x: pContext found\r\n",\r
+ pContext ));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Set the next context\r
+ //\r
+ pContext = pContext->pNext;\r
+ }\r
+\r
+ //\r
+ // Return the connection context structure address\r
+ //\r
+ DBG_EXIT_HEX ( pContext );\r
+ return pContext;\r
+}\r
+\r
+\r
+/**\r
+ Remove a context from the list.\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+ @param [in] pContext The context structure address.\r
+\r
+**/\r
+VOID\r
+ContextRemove (\r
+ IN TSDT_TFTP_SERVER * pTftpServer,\r
+ IN TSDT_CONNECTION_CONTEXT * pContext\r
+ )\r
+{\r
+ TSDT_CONNECTION_CONTEXT * pNextContext;\r
+ TSDT_CONNECTION_CONTEXT * pPreviousContext;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Attempt to locate the context in the list\r
+ //\r
+ pPreviousContext = NULL;\r
+ pNextContext = pTftpServer->pContextList;\r
+ while ( NULL != pNextContext ) {\r
+ //\r
+ // Determine if the context was found\r
+ //\r
+ if ( pNextContext == pContext ) {\r
+ //\r
+ // Remove the context from the list\r
+ //\r
+ if ( NULL == pPreviousContext ) {\r
+ pTftpServer->pContextList = pContext->pNext;\r
+ }\r
+ else {\r
+ pPreviousContext->pNext = pContext->pNext;\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Set the next context\r
+ //\r
+ pPreviousContext = pNextContext;\r
+ pNextContext = pNextContext->pNext;\r
+ }\r
+\r
+ //\r
+ // Determine if the context was found\r
+ //\r
+ if ( NULL != pContext ) {\r
+ //\r
+ // Return the resources\r
+ //\r
+ gBS->FreePool ( pContext );\r
+ }\r
+\r
+ DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+ Process the work for the sockets.\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+**/\r
+VOID\r
+PortWork (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ TSDT_CONNECTION_CONTEXT * pContext;\r
+ socklen_t RemoteAddressLength;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Handle input events\r
+ //\r
+ if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) {\r
+ //\r
+ // Receive the message from the remote system\r
+ //\r
+ RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );\r
+ pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd,\r
+ &pTftpServer->RxBuffer[0],\r
+ sizeof ( pTftpServer->RxBuffer ),\r
+ 0,\r
+ (struct sockaddr *) &pTftpServer->RemoteAddress,\r
+ &RemoteAddressLength );\r
+ if ( -1 != pTftpServer->RxBytes ) {\r
+ pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength;\r
+ DEBUG (( DEBUG_TFTP_PORT,\r
+ "Received %d bytes from %d.%d.%d.%d:%d\r\n",\r
+ pTftpServer->RxBytes,\r
+ pTftpServer->RemoteAddress.sin_addr.s_addr & 0xff,\r
+ ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,\r
+ ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,\r
+ ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,\r
+ htons ( pTftpServer->RemoteAddress.sin_port )));\r
+\r
+ //\r
+ // Lookup connection context using the remote system address and port\r
+ // to determine if an existing connection to this remote\r
+ // system exists\r
+ //\r
+ pContext = ContextFind ( pTftpServer );\r
+\r
+ //\r
+ // Process the received message\r
+ //\r
+ TftpProcessRequest ( pTftpServer, pContext );\r
+ }\r
+ else {\r
+ //\r
+ // Receive error on the TFTP server port\r
+ // Close the server socket\r
+ //\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",\r
+ errno ));\r
+ pTftpServer->TftpPort.revents |= POLLHUP;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Handle the close event\r
+ //\r
+ if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) {\r
+ //\r
+ // Close the port\r
+ //\r
+ close ( pTftpServer->TftpPort.fd );\r
+ pTftpServer->TftpPort.fd = -1;\r
+ }\r
+\r
+ DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+ Scan the list of sockets and process any pending work\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+**/\r
+VOID\r
+SocketPoll (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ int FDCount;\r
+\r
+ DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));\r
+\r
+ //\r
+ // Determine if any ports are active\r
+ //\r
+ FDCount = poll ( &pTftpServer->TftpPort,\r
+ 1,\r
+ CLIENT_POLL_DELAY );\r
+ if ( -1 == FDCount ) {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_SOCKET_POLL,\r
+ "ERROR - errno: %d\r\n",\r
+ errno ));\r
+ }\r
+\r
+ if ( 0 < FDCount ) {\r
+ //\r
+ // Process this port\r
+ //\r
+ PortWork ( pTftpServer );\r
+ pTftpServer->TftpPort.revents = 0;\r
+ }\r
+\r
+ DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));\r
+}\r
+\r
+\r
+/**\r
+ Convert a character to lower case\r
+\r
+ @param [in] Character The character to convert\r
+\r
+ @return The lower case equivalent of the character\r
+\r
+**/\r
+int\r
+tolower (\r
+ int Character\r
+ )\r
+{\r
+ //\r
+ // Determine if the character is upper case\r
+ //\r
+ if (( 'A' <= Character ) && ( 'Z' >= Character )) {\r
+ //\r
+ // Convert the character to lower caes\r
+ //\r
+ Character += 'a' - 'A';\r
+ }\r
+\r
+ //\r
+ // Return the converted character\r
+ //\r
+ return Character;\r
+}\r
+\r
+\r
+/**\r
+ Case independent string comparison\r
+\r
+ @param [in] pString1 Zero terminated string address\r
+ @param [in] pString2 Zero terminated string address\r
+\r
+ @return Returns the first character difference between string 1\r
+ and string 2.\r
+\r
+**/\r
+int\r
+stricmp (\r
+ char * pString1,\r
+ char * pString2\r
+ )\r
+{\r
+ int Char1;\r
+ int Char2;\r
+ int Difference;\r
+\r
+ //\r
+ // Walk the length of the strings\r
+ //\r
+ do {\r
+ //\r
+ // Get the next characters\r
+ //\r
+ Char1 = (UINT8)*pString1++;\r
+ Char2 = (UINT8)*pString2++;\r
+\r
+ //\r
+ // Convert them to lower case\r
+ //\r
+ Char1 = tolower ( Char1 );\r
+ Char2 = tolower ( Char2 );\r
+\r
+ //\r
+ // Done when the characters differ\r
+ //\r
+ Difference = Char1 - Char2;\r
+ if ( 0 != Difference ) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Done at the end of the string\r
+ //\r
+ } while ( 0 != Char1 );\r
+\r
+ //\r
+ // Return the difference\r
+ //\r
+ return Difference;\r
+}\r
+\r
+\r
+/**\r
+ Get the next TFTP option\r
+\r
+ @param [in] pOption Address of a zero terminated option string\r
+ @param [in] pEnd End of buffer address\r
+ @param [in] ppNextOption Address to receive the address of the next\r
+ zero terminated option string\r
+\r
+ @retval EFI_SUCCESS Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+TftpOptionGet (\r
+ IN UINT8 * pOption,\r
+ IN UINT8 * pEnd,\r
+ IN UINT8 ** ppNextOption\r
+ )\r
+{\r
+ UINT8 * pNextOption;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Locate the end of the option\r
+ //\r
+ pNextOption = pOption;\r
+ while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {\r
+ pNextOption += 1;\r
+ }\r
+ if ( pEnd <= pNextOption ) {\r
+ //\r
+ // Error - end of buffer reached\r
+ //\r
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
+ "ERROR - Option without zero termination received!\r\n" ));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ else {\r
+ //\r
+ // Zero terminated option found\r
+ //\r
+ pNextOption += 1;\r
+\r
+ //\r
+ // Display the zero terminated ASCII option string\r
+ //\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "Option: %a\r\n",\r
+ pOption ));\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Return the next option address\r
+ //\r
+ *ppNextOption = pNextOption;\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Place an option value into the option acknowledgement\r
+\r
+ @param [in] pOack Option acknowledgement address\r
+ @param [in] Value Value to translate into ASCII decimal\r
+\r
+ @return Option acknowledgement address\r
+\r
+**/\r
+UINT8 *\r
+TftpOptionSet (\r
+ IN UINT8 * pOack,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ UINT64 NextValue;\r
+\r
+ //\r
+ // Determine the next value\r
+ //\r
+ NextValue = Value / 10;\r
+\r
+ //\r
+ // Supress leading zeros\r
+ //\r
+ if ( 0 != NextValue ) {\r
+ pOack = TftpOptionSet ( pOack, NextValue );\r
+ }\r
+\r
+ //\r
+ // Output this digit\r
+ //\r
+ *pOack++ = (UINT8)( Value - ( NextValue * 10 ) + '0' );\r
+\r
+ //\r
+ // Return the next option acknowledgement location\r
+ //\r
+ return pOack;\r
+}\r
+\r
+\r
+/**\r
+ Process the TFTP request\r
+\r
+ @param [in] pContext The context structure address.\r
+ @param [in] pOption Address of the first zero terminated option string\r
+ @param [in] pEnd End of buffer address\r
+\r
+**/\r
+VOID\r
+TftpOptions (\r
+ IN TSDT_CONNECTION_CONTEXT * pContext,\r
+ IN UINT8 * pOption,\r
+ IN UINT8 * pEnd\r
+ )\r
+{\r
+ UINT8 * pNextOption;\r
+ UINT8 * pOack;\r
+ UINT8 * pTemp;\r
+ UINT8 * pValue;\r
+ EFI_STATUS Status;\r
+ INT32 Value;\r
+\r
+ //\r
+ // Start the OACK packet\r
+ // Let the OACK handle the parsing errors\r
+ // See http://tools.ietf.org/html/rfc2347\r
+ //\r
+ pOack = &pContext->TxBuffer[0];\r
+ *pOack++ = 0;\r
+ *pOack++ = TFTP_OP_OACK;\r
+ pContext->TxBytes = 2;\r
+\r
+ //\r
+ // Walk the list of options\r
+ //\r
+ do {\r
+ //\r
+ // Get the next option, skip junk at end of message\r
+ //\r
+ Status = TftpOptionGet ( pOption, pEnd, &pNextOption );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Process the option\r
+ //\r
+\r
+ //\r
+ // blksize - See http://tools.ietf.org/html/rfc2348\r
+ //\r
+ pValue = pNextOption;\r
+ if ( 0 == stricmp ((char *)pOption, "blksize" )) {\r
+ //\r
+ // Get the value\r
+ //\r
+ Status = TftpOptionGet ( pValue, pEnd, &pNextOption );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Validate the block size, skip non-numeric block sizes\r
+ //\r
+ Status = TftpOptionValue ( pValue, &Value );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Propose a smaller block size if necessary\r
+ //\r
+ if ( Value > TFTP_MAX_BLOCK_SIZE ) {\r
+ Value = TFTP_MAX_BLOCK_SIZE;\r
+ }\r
+\r
+ //\r
+ // Set the new block size\r
+ //\r
+ pContext->BlockSize = Value;\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "Using block size of %d bytes\r\n",\r
+ pContext->BlockSize ));\r
+\r
+ //\r
+ // Update the OACK\r
+ //\r
+ pTemp = pOack;\r
+ *pOack++ = 'b';\r
+ *pOack++ = 'l';\r
+ *pOack++ = 'k';\r
+ *pOack++ = 's';\r
+ *pOack++ = 'i';\r
+ *pOack++ = 'z';\r
+ *pOack++ = 'e';\r
+ *pOack++ = 0;\r
+ pOack = TftpOptionSet ( pOack, pContext->BlockSize );\r
+ *pOack++ = 0;\r
+ pContext->TxBytes += pOack - pTemp;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // timeout - See http://tools.ietf.org/html/rfc2349\r
+ //\r
+ else if ( 0 == stricmp ((char *)pOption, "timeout" )) {\r
+ //\r
+ // Get the value\r
+ //\r
+ Status = TftpOptionGet ( pValue, pEnd, &pNextOption );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = TftpOptionValue ( pValue, &Value );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Set the timeout value\r
+ //\r
+ pContext->Timeout = Value;\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "Using timeout of %d seconds\r\n",\r
+ pContext->Timeout ));\r
+\r
+ //\r
+ // Update the OACK\r
+ //\r
+ pTemp = pOack;\r
+ *pOack++ = 't';\r
+ *pOack++ = 'i';\r
+ *pOack++ = 'm';\r
+ *pOack++ = 'e';\r
+ *pOack++ = 'o';\r
+ *pOack++ = 'u';\r
+ *pOack++ = 't';\r
+ *pOack++ = 0;\r
+ pOack = TftpOptionSet ( pOack, pContext->Timeout );\r
+ *pOack++ = 0;\r
+ pContext->TxBytes += pOack - pTemp;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // tsize - See http://tools.ietf.org/html/rfc2349\r
+ //\r
+ else if ( 0 == stricmp ((char *)pOption, "tsize" )) {\r
+ //\r
+ // Get the value\r
+ //\r
+ Status = TftpOptionGet ( pValue, pEnd, &pNextOption );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = TftpOptionValue ( pValue, &Value );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Return the file size\r
+ //\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "Returning file size of %Ld bytes\r\n",\r
+ pContext->LengthInBytes ));\r
+\r
+ //\r
+ // Update the OACK\r
+ //\r
+ pTemp = pOack;\r
+ *pOack++ = 't';\r
+ *pOack++ = 's';\r
+ *pOack++ = 'i';\r
+ *pOack++ = 'z';\r
+ *pOack++ = 'e';\r
+ *pOack++ = 0;\r
+ pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );\r
+ *pOack++ = 0;\r
+ pContext->TxBytes += pOack - pTemp;\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ //\r
+ // Unknown option - Ignore it\r
+ //\r
+ DEBUG (( DEBUG_WARN | DEBUG_TFTP_REQUEST,\r
+ "WARNING - Skipping unknown option: %a\r\n",\r
+ pOption ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set the next option\r
+ //\r
+ pOption = pNextOption;\r
+ } while ( pEnd > pOption );\r
+}\r
+\r
+\r
+/**\r
+ Process the TFTP request\r
+\r
+ @param [in] pOption Address of the first zero terminated option string\r
+ @param [in] pValue Address to receive the value\r
+\r
+ @retval EFI_SUCCESS Option translated into a value\r
+\r
+**/\r
+EFI_STATUS\r
+TftpOptionValue (\r
+ IN UINT8 * pOption,\r
+ IN INT32 * pValue\r
+ )\r
+{\r
+ UINT8 Digit;\r
+ EFI_STATUS Status;\r
+ INT32 Value;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Walk the characters in the option\r
+ //\r
+ Value = 0;\r
+ while ( 0 != *pOption ) {\r
+ //\r
+ // Convert the next digit to binary\r
+ //\r
+ Digit = *pOption++;\r
+ if (( '0' <= Digit ) && ( '9' >= Digit )) {\r
+ Value *= 10;\r
+ Value += Digit - '0';\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
+ "ERROR - Invalid character '0x%02x' in the value\r\n",\r
+ Digit ));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the value\r
+ //\r
+ *pValue = Value;\r
+\r
+ //\r
+ // Return the conversion status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Process the TFTP request\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+ @param [in] pContext Connection context structure address\r
+\r
+**/\r
+VOID\r
+TftpProcessRequest (\r
+ IN TSDT_TFTP_SERVER * pTftpServer,\r
+ IN TSDT_CONNECTION_CONTEXT * pContext\r
+ )\r
+{\r
+ BOOLEAN bCloseContext;\r
+ BOOLEAN bIgnorePacket;\r
+ UINT16 BlockNumber;\r
+ UINT16 Opcode;\r
+ UINT8 * pBuffer;\r
+ UINT8 * pEnd;\r
+ UINT8 * pFileName;\r
+ UINT8 * pMode;\r
+ UINT8 * pOption;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Get the opcode\r
+ //\r
+ pBuffer = &pTftpServer->RxBuffer[0];\r
+ Opcode = HTONS ( *(UINT16 *)&pBuffer[0]);\r
+Print ( L"TFTP Opcode: 0x%08x\r\n", Opcode );\r
+\r
+ //\r
+ // Validate the parameters\r
+ //\r
+ bCloseContext = FALSE;\r
+ bIgnorePacket = FALSE;\r
+ switch ( Opcode ) {\r
+ default:\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "ERROR - Unknown TFTP opcode: %d\r\n",\r
+ Opcode ));\r
+ bIgnorePacket = TRUE;\r
+ break;\r
+\r
+ case TFTP_OP_READ_REQUEST:\r
+ break;\r
+\r
+ case TFTP_OP_DATA:\r
+ if ( NULL == pContext ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
+ (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),\r
+ htons ( pTftpServer->RemoteAddress.sin_port )));\r
+ bIgnorePacket = TRUE;\r
+ break;\r
+ }\r
+ if ( pContext->bExpectAck ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",\r
+ pContext ));\r
+ bIgnorePacket = TRUE;\r
+ break;\r
+ }\r
+ if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 ))\r
+ {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Receive data length of %d > %d bytes (maximum block size) for pContext 0x%08x\r\n",\r
+ pTftpServer->RxBytes - 2 - 2,\r
+ pContext->BlockSize,\r
+ pContext ));\r
+ bIgnorePacket = TRUE;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case TFTP_OP_ACK:\r
+ if ( NULL == pContext ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
+ (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),\r
+ htons ( pTftpServer->RemoteAddress.sin_port )));\r
+ bIgnorePacket = TRUE;\r
+ }\r
+ if ( !pContext->bExpectAck ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",\r
+ pContext ));\r
+ bIgnorePacket = TRUE;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case TFTP_OP_ERROR:\r
+ if ( NULL == pContext ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - File not open for %d.%d.%d.%d:%d\r\n",\r
+ (UINT8)pTftpServer->RemoteAddress.sin_addr.s_addr,\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),\r
+ (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),\r
+ htons ( pTftpServer->RemoteAddress.sin_port )));\r
+ bIgnorePacket = TRUE;\r
+ }\r
+ break;\r
+ }\r
+ if ( !bIgnorePacket ) {\r
+ //\r
+ // Process the request\r
+ //\r
+ switch ( Opcode ) {\r
+ default:\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "ERROR - Unable to process TFTP opcode: %d\r\n",\r
+ Opcode ));\r
+ break;\r
+\r
+ case TFTP_OP_READ_REQUEST:\r
+\r
+ //\r
+ // Close the context if necessary\r
+ //\r
+ if ( NULL != pContext ) {\r
+ ContextRemove ( pTftpServer, pContext );\r
+ }\r
+\r
+ //\r
+ // Create the connection context\r
+ //\r
+ pContext = ContextAdd ( pTftpServer );\r
+ if ( NULL == pContext ) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Locate the mode\r
+ //\r
+ pFileName = &pBuffer[2];\r
+ pEnd = &pBuffer[pTftpServer->RxBytes];\r
+ pMode = pFileName;\r
+ while (( pEnd > pMode ) && ( 0 != *pMode )) {\r
+ pMode += 1;\r
+ }\r
+ if ( pEnd <= pMode ) {\r
+ //\r
+ // Mode not found\r
+ //\r
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
+ "ERROR - File mode not found\r\n" ));\r
+ //\r
+ // Tell the client of the error\r
+ //\r
+ TftpSendError ( pTftpServer,\r
+ pContext,\r
+ 0,\r
+ (UINT8 *)"File open mode not found" );\r
+ break;\r
+ }\r
+ pMode += 1;\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "TFTP - FileName: %a\n",\r
+ pFileName ));\r
+\r
+ //\r
+ // Locate the options\r
+ //\r
+ pOption = pMode;\r
+ while (( pEnd > pOption ) && ( 0 != *pOption )) {\r
+ pOption += 1;\r
+ }\r
+ if ( pEnd <= pOption ) {\r
+ //\r
+ // End of mode not found\r
+ //\r
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,\r
+ "ERROR - File mode not valid\r\n" ));\r
+ //\r
+ // Tell the client of the error\r
+ //\r
+ TftpSendError ( pTftpServer,\r
+ pContext,\r
+ 0,\r
+ (UINT8 *)"File open mode not valid" );\r
+ break;\r
+ }\r
+ pOption += 1;\r
+ DEBUG (( DEBUG_TFTP_REQUEST,\r
+ "TFTP - Mode: %a\r\n",\r
+ pMode ));\r
+\r
+ //\r
+ // Verify the mode is supported\r
+ //\r
+ if ( 0 != stricmp ((char *)pMode, "octet" )) {\r
+ //\r
+ // File access mode not supported\r
+ //\r
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_REQUEST,\r
+ "ERROR - File mode %a not supported\r\n",\r
+ pMode ));\r
+\r
+ //\r
+ // Tell the client of the error\r
+ //\r
+ TftpSendError ( pTftpServer,\r
+ pContext,\r
+ 0,\r
+ (UINT8 *)"File open mode not supported" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Open the file, close the context on error\r
+ //\r
+// TODO: Remove the following line\r
+pContext->File = (EFI_HANDLE)1;\r
+\r
+ //\r
+ // Determine the file length\r
+ //\r
+//fstat\r
+\r
+ //\r
+ // Process the options\r
+ //\r
+ TftpOptions ( pContext, pOption, pEnd );\r
+\r
+ //\r
+ // Read in the first portion of the file\r
+ //\r
+\r
+ //\r
+ // Send the first block\r
+ //\r
+ pContext->bExpectAck = TRUE;\r
+ if ( 2 < pContext->TxBytes ) {\r
+ //\r
+ // Send the OACK\r
+ //\r
+ Status = TftpTxPacket ( pTftpServer, pContext );\r
+ }\r
+ else {\r
+ //\r
+ // Send the first block of data\r
+ //\r
+ Status = TftpSendNextBlock ( pTftpServer, pContext );\r
+ }\r
+ break;\r
+\r
+ case TFTP_OP_ACK:\r
+ //\r
+ // Get the block number that is being ACKed\r
+ //\r
+ BlockNumber = pTftpServer->RxBuffer[2];\r
+ BlockNumber <<= 8;\r
+ BlockNumber |= pTftpServer->RxBuffer[3];\r
+\r
+ //\r
+ // Determine if this is the correct ACK\r
+ //\r
+ DEBUG (( DEBUG_TFTP_ACK,\r
+ "ACK for block 0x%04x received\r\n",\r
+ BlockNumber ));\r
+ if (( !pContext->bExpectAck )\r
+ || ( BlockNumber != pContext->AckNext ))\r
+ {\r
+ DEBUG (( DEBUG_WARN | DEBUG_TFTP_ACK,\r
+ "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",\r
+ pContext->AckNext,\r
+ BlockNumber ));\r
+ }\r
+ else {\r
+ //\r
+ // Process the expected ACK\r
+ //\r
+ if ( pContext->bEofSent ) {\r
+ bCloseContext = TRUE;\r
+ }\r
+ else {\r
+ //\r
+ // Set the next expected ACK\r
+ //\r
+ pContext->AckNext += 1;\r
+\r
+ //\r
+ // Send the next packet of data\r
+ //\r
+ Status = TftpSendNextBlock ( pTftpServer, pContext );\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Determine if the context should be closed\r
+ //\r
+ if ( bCloseContext ) {\r
+ ContextRemove ( pTftpServer, pContext );\r
+ }\r
+\r
+ DBG_EXIT ( );\r
+}\r
+\r
+\r
+/**\r
+ Build and send an error packet\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+ @param [in] pContext The context structure address.\r
+ @param [in] Error Error number for the packet\r
+ @param [in] pError Zero terminated error string address\r
+\r
+ @retval EFI_SUCCESS Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+TftpSendError (\r
+ IN TSDT_TFTP_SERVER * pTftpServer,\r
+ IN TSDT_CONNECTION_CONTEXT * pContext,\r
+ IN UINT16 Error,\r
+ IN UINT8 * pError\r
+ )\r
+{\r
+ UINT8 Character;\r
+ UINT8 * pBuffer;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Build the error packet\r
+ //\r
+ pBuffer = &pContext->TxBuffer[0];\r
+ pBuffer[0] = 0;\r
+ pBuffer[1] = TFTP_OP_ERROR;\r
+ pBuffer[2] = (UINT8)( Error >> 8 );\r
+ pBuffer[3] = (UINT8)Error;\r
+\r
+ //\r
+ // Copy the zero terminated string into the buffer\r
+ //\r
+ pBuffer += 4;\r
+ do {\r
+ Character = *pError++;\r
+ *pBuffer++ = Character;\r
+ } while ( 0 != Character );\r
+\r
+ //\r
+ // Send the error message\r
+ //\r
+ pContext->TxBytes = pBuffer - &pContext->TxBuffer[0];\r
+ Status = TftpTxPacket ( pTftpServer, pContext );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send the next block of file system data\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+ @param [in] pContext The context structure address.\r
+\r
+ @retval EFI_SUCCESS Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+TftpSendNextBlock (\r
+ IN TSDT_TFTP_SERVER * pTftpServer,\r
+ IN TSDT_CONNECTION_CONTEXT * pContext\r
+ )\r
+{\r
+ ssize_t LengthInBytes;\r
+ UINT8 * pBuffer;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Determine how much data needs to be sent\r
+ //\r
+ LengthInBytes = pContext->BlockSize;\r
+ if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE )\r
+ || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) {\r
+ LengthInBytes = (ssize_t)pContext->LengthInBytes;\r
+ pContext->bEofSent = TRUE;\r
+ }\r
+\r
+ //\r
+ // Set the TFTP opcode and block number\r
+ //\r
+ pBuffer = &pContext->TxBuffer[0];\r
+ *pBuffer++ = 0;\r
+ *pBuffer++ = TFTP_OP_DATA;\r
+ *pBuffer++ = (UINT8)( pContext->AckNext >> 8 );\r
+ *pBuffer++ = (UINT8)pContext->AckNext;\r
+\r
+ //\r
+ // Copy the file data into the transmit buffer\r
+ //\r
+ pContext->TxBytes = 2 + 2 + LengthInBytes;\r
+ if ( 0 < LengthInBytes ) {\r
+ CopyMem ( &pBuffer,\r
+ pContext->pBuffer,\r
+ LengthInBytes );\r
+ }\r
+\r
+ //\r
+ // Send the next block\r
+ //\r
+ Status = TftpTxPacket ( pTftpServer, pContext );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Create the port for the TFTP server\r
+\r
+ This routine polls the network layer to create the TFTP port for the\r
+ TFTP server. More than one attempt may be necessary since it may take\r
+ some time to get the IP address and initialize the upper layers of\r
+ the network stack.\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+**/\r
+VOID\r
+TftpServerTimer (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ UINT16 TftpPort;\r
+ int SocketStatus;\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" ));\r
+\r
+ //\r
+ // Open the TFTP port on the server\r
+ //\r
+ do {\r
+ do {\r
+ //\r
+ // Wait for a while\r
+ //\r
+ Status = gBS->CheckEvent ( pTftpServer->TimerEvent );\r
+ } while ( EFI_SUCCESS != Status );\r
+\r
+ //\r
+ // Attempt to create the socket for the TFTP server\r
+ //\r
+ pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP;\r
+ pTftpServer->TftpPort.revents = 0;\r
+ pTftpServer->TftpPort.fd = socket ( AF_INET,\r
+ SOCK_DGRAM,\r
+ IPPROTO_UDP );\r
+ if ( -1 != pTftpServer->TftpPort.fd )\r
+ {\r
+ //\r
+ // Set the socket address\r
+ //\r
+ ZeroMem ( &pTftpServer->TftpServerAddress,\r
+ sizeof ( pTftpServer->TftpServerAddress ));\r
+ TftpPort = 69;\r
+ DEBUG (( DEBUG_TFTP_PORT,\r
+ "TFTP Port: %d\r\n",\r
+ TftpPort ));\r
+ pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress );\r
+ pTftpServer->TftpServerAddress.sin_family = AF_INET;\r
+ pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY;\r
+ pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort );\r
+\r
+ //\r
+ // Bind the socket to the TFTP port\r
+ //\r
+ SocketStatus = bind ( pTftpServer->TftpPort.fd,\r
+ (struct sockaddr *) &pTftpServer->TftpServerAddress,\r
+ pTftpServer->TftpServerAddress.sin_len );\r
+ if ( -1 != SocketStatus ) {\r
+ DEBUG (( DEBUG_TFTP_PORT,\r
+ "0x%08x: Socket bound to port %d\r\n",\r
+ pTftpServer->TftpPort.fd,\r
+ TftpPort ));\r
+ }\r
+\r
+ //\r
+ // Release the socket if necessary\r
+ //\r
+ if ( -1 == SocketStatus ) {\r
+ close ( pTftpServer->TftpPort.fd );\r
+ pTftpServer->TftpPort.fd = -1;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Wait until the socket is open\r
+ //\r
+ }while ( -1 == pTftpServer->TftpPort.fd );\r
+\r
+ DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" ));\r
+}\r
+\r
+\r
+/**\r
+ Start the TFTP server port creation timer\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+ @retval EFI_SUCCESS The timer was successfully started.\r
+ @retval EFI_ALREADY_STARTED The timer is already running.\r
+ @retval Other The timer failed to start.\r
+\r
+**/\r
+EFI_STATUS\r
+TftpServerTimerStart (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 TriggerTime;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Assume the timer is already running\r
+ //\r
+ Status = EFI_ALREADY_STARTED;\r
+ if ( !pTftpServer->bTimerRunning ) {\r
+ //\r
+ // Compute the poll interval\r
+ //\r
+ TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );\r
+ Status = gBS->SetTimer ( pTftpServer->TimerEvent,\r
+ TimerPeriodic,\r
+ TriggerTime );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));\r
+\r
+ //\r
+ // Mark the timer running\r
+ //\r
+ pTftpServer->bTimerRunning = TRUE;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,\r
+ "ERROR - Failed to start TFTP port timer, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop the TFTP server port creation timer\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+\r
+ @retval EFI_SUCCESS The TFTP port timer is stopped\r
+ @retval Other Failed to stop the TFTP port timer\r
+\r
+**/\r
+EFI_STATUS\r
+TftpServerTimerStop (\r
+ IN TSDT_TFTP_SERVER * pTftpServer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Assume the timer is stopped\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ if ( pTftpServer->bTimerRunning ) {\r
+ //\r
+ // Stop the port creation polling\r
+ //\r
+ Status = gBS->SetTimer ( pTftpServer->TimerEvent,\r
+ TimerCancel,\r
+ 0 );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" ));\r
+\r
+ //\r
+ // Mark the timer stopped\r
+ //\r
+ pTftpServer->bTimerRunning = FALSE;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_TFTP_PORT,\r
+ "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n",\r
+ Status ));\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Send the next TFTP packet\r
+\r
+ @param [in] pTftpServer The TFTP server control structure address.\r
+ @param [in] pContext The context structure address.\r
+\r
+ @retval EFI_SUCCESS Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+TftpTxPacket (\r
+ IN TSDT_TFTP_SERVER * pTftpServer,\r
+ IN TSDT_CONNECTION_CONTEXT * pContext\r
+ )\r
+{\r
+ ssize_t LengthInBytes;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Send the TFTP packet\r
+ //\r
+ DEBUG (( DEBUG_TX,\r
+ "0x%08x: pContext sending 0x%08x bytes\r\n",\r
+ pContext,\r
+ pContext->TxBytes ));\r
+ LengthInBytes = sendto ( pTftpServer->TftpPort.fd,\r
+ &pContext->TxBuffer[0],\r
+ pContext->TxBytes,\r
+ 0,\r
+ (struct sockaddr *)&pContext->RemoteAddress,\r
+ pContext->RemoteAddress.sin_len );\r
+ if ( -1 == LengthInBytes ) {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_TX,\r
+ "ERROR - Transmit failure, errno: 0x%08x\r\n",\r
+ errno ));\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Entry point for the TFTP server application.\r
+\r
+ @param [in] Argc The number of arguments\r
+ @param [in] Argv The argument value array\r
+\r
+ @retval 0 The application exited normally.\r
+ @retval Other An error occurred.\r
+**/\r
+int\r
+main (\r
+ IN int Argc,\r
+ IN char **Argv\r
+ )\r
+{\r
+ TSDT_TFTP_SERVER * pTftpServer;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Create a timer event to start TFTP port\r
+ //\r
+ pTftpServer = &mTftpServer;\r
+ Status = gBS->CreateEvent ( EVT_TIMER,\r
+ TPL_TFTP_SERVER,\r
+ NULL,\r
+ NULL,\r
+ &pTftpServer->TimerEvent );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = TftpServerTimerStart ( pTftpServer );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Run the TFTP server forever\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Poll the network layer to create the TFTP port\r
+ // for the tftp server. More than one attempt may\r
+ // be necessary since it may take some time to get\r
+ // the IP address and initialize the upper layers\r
+ // of the network stack.\r
+ //\r
+ TftpServerTimer ( pTftpServer );\r
+\r
+ //\r
+ // Poll the socket for activity\r
+ //\r
+ do {\r
+ SocketPoll ( pTftpServer );\r
+ } while ( -1 != pTftpServer->TftpPort.fd );\r
+\r
+//\r
+// TODO: Remove the following test code\r
+// Exit when the network connection is broken\r
+//\r
+break;\r
+ }\r
+\r
+ //\r
+ // Done with the timer event\r
+ //\r
+ TftpServerTimerStop ( pTftpServer );\r
+ Status = gBS->CloseEvent ( pTftpServer->TimerEvent );\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the final status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
-/*++
- This file contains an 'Intel UEFI Application' and is
- licensed for Intel CPUs and chipsets under the terms of your
- license agreement with Intel or your vendor. This file may
- be modified by the user, subject to additional terms of the
- license agreement
---*/
-/*++
-
-Copyright (c) 2011 Intel Corporation. All rights reserved
-This software and associated documentation (if any) is furnished
-under a license and may only be used or copied in accordance
-with the terms of the license. Except as permitted by such
-license, no part of this software or documentation may be
-reproduced, stored in a retrieval system, or transmitted in any
-form or by any means without the express written consent of
-Intel Corporation.
-
---*/
-
-/** @file
- Display the runtime services table
-
-**/
-
-#include <WebServer.h>
-#include <Guid/Acpi.h>
-#include <IndustryStandard/Acpi10.h>
-#include <IndustryStandard/Acpi30.h>
-
-#pragma warning ( disable : 4305 )
-
-//
-// Ensure proper structure formats
-//
-#pragma pack(1)
-
-typedef struct {
- UINT8 AddressSpaceId;
- UINT8 RegisterBitWidth;
- UINT8 RegisterBitOffset;
- UINT8 AccessSize;
- UINT64 Address;
-} GENERIC_ADDRESS;
-
-
-typedef struct {
- UINT32 Signature; // 0
- UINT32 Length; // 4
- UINT8 Revision; // 8
- UINT8 Checksum; // 9
- UINT8 OemId[6]; // 10
- UINT8 OemTableId[8]; // 16
- UINT32 OemRevision; // 24
- UINT32 CreatorId; // 28
- UINT32 CreatorRevision; // 32
- UINT8 DefinitionBlock[1]; // 36
-} ACPI_DSDT;
-
-
-typedef struct {
- UINT32 Signature; // 0
- UINT32 Length; // 4
- UINT8 Revision; // 8
- UINT8 Checksum; // 9
- UINT8 OemId[6]; // 10
- UINT8 OemTableId[8]; // 16
- UINT32 OemRevision; // 24
- UINT32 CreatorId; // 28
- UINT32 CreatorRevision; // 32
- UINT32 FirmwareCtrl; // 36
- UINT32 DSDT; // 40
- UINT8 Reserved; // 44
- UINT8 PreferredPmProfile; // 45
- UINT16 SciInt; // 46
- UINT32 SmiCmd; // 48
- UINT8 AcpiEnable; // 52
- UINT8 AcpiDisable; // 53
- UINT8 S4BiosReq; // 54
- UINT8 PStateCnt; // 55
- UINT32 Pm1aEvtBlk; // 56
- UINT32 Pm1bEvtBlk; // 60
- UINT32 Pm1aCntBlk; // 64
- UINT32 Pm1bCntBlk; // 68
- UINT32 Pm2CntBlk; // 72
- UINT32 PmTmrBlk; // 76
- UINT32 Gpe0Blk; // 80
- UINT32 Gpe1Blk; // 84
- UINT8 Pm1EvtLen; // 88
- UINT8 Pm1CntLen; // 89
- UINT8 PM2CntLen; // 90
- UINT8 PmTmrLen; // 91
- UINT8 Gpe0BlkLen; // 92
- UINT8 Gpe1BlkLen; // 93
- UINT8 Gpe1Base; // 94
- UINT8 CstCnt; // 95
- UINT16 PLvl2Lat; // 96
- UINT16 PLvl3Lat; // 98
- UINT16 FlushSize; // 100
- UINT16 FlushStride; // 102
- UINT8 DutyOffset; // 104
- UINT8 DutyWidth; // 105
- UINT8 DayAlrm; // 106
- UINT8 MonAlrm; // 107
- UINT8 Century; // 108
- UINT16 IapcBootArch; // 109
- UINT8 Reserved2; // 111
- UINT32 Flags; // 112
- UINT32 ResetReg [3]; // 116
- UINT8 ResetValue; // 128
- UINT8 Reserved3 [3]; // 129
- UINT64 XFirmwareCtrl; // 132
- UINT64 XDsdt; // 140
- UINT32 XPm1aEvtBlk [3]; // 148
- UINT32 XPm1bEvtBlk [3]; // 160
- UINT32 XPm1aCntBlk [3]; // 172
- UINT32 XPm1bCntBlk [3]; // 184
- UINT32 XPm2CntBlk [3]; // 196
- UINT32 XPmTmrBlk [3]; // 208
- UINT32 XGpe0Blk [3]; // 220
- UINT32 XGpe1Blk [3]; // 232
-} ACPI_FADT;
-
-
-typedef struct {
- UINT32 Signature;
- UINT32 Length;
- UINT8 Revision;
- UINT8 Checksum;
- UINT8 OemId[6];
- UINT8 OemTableId[8];
- UINT32 OemRevision;
- UINT32 CreatorId;
- UINT32 CreatorRevision;
- UINT32 Entry[1];
-} ACPI_RSDT;
-
-
-#pragma pack()
-
-
-typedef struct {
- UINT32 Signature;
- CONST CHAR8 * pTableName;
- CONST CHAR16 * pWebPage;
-} TABLE_SIGNATURE;
-
-
-CONST TABLE_SIGNATURE mTableId [] = {
- { DSDT_SIGNATURE, "DSDT", PAGE_ACPI_DSDT },
- { FADT_SIGNATURE, "FADT", PAGE_ACPI_FADT }
-};
-
-
-/**
- Locate the RSDT table
-
- @returns Table address or NULL if not found
-
-**/
-CONST ACPI_RSDT *
-LocateRsdt (
- VOID
- )
-{
- CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
- CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
- CONST ACPI_RSDT * pRsdt;
- EFI_STATUS Status;
-
- //
- // Use for/break instead of goto
- //
- pRsdt = NULL;
- for ( ; ; ) {
- //
- // Locate the RSDT
- //
- Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );
- if ( !EFI_ERROR ( Status )) {
- pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;
- }
- else {
- Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;
- }
- break;
- }
-
- //
- // The entry was not found
- //
- return pRsdt;
-}
-
-
-/**
- Locate the specified table
-
- @param [in] Signature Table signature
-
- @returns Table address or NULL if not found
-
-**/
-CONST VOID *
-LocateTable (
- IN UINT32 Signature
- )
-{
- CONST UINT32 * pEnd;
- CONST UINT32 * pEntry;
- CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
- CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
- CONST ACPI_RSDT * pRsdt;
- CONST UINT32 * pSignature;
- EFI_STATUS Status;
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Locate the RSDT
- //
- Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );
- if ( !EFI_ERROR ( Status )) {
- pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;
- }
- else {
- Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;
- }
-
- //
- // Walk the list of entries
- //
- pEntry = &pRsdt->Entry [ 0 ];
- pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];
- while ( pEnd > pEntry ) {
- //
- // The entry is actually a 32-bit physical table address
- // The first entry in the table is the 32-bit table signature
- //
- pSignature = (UINT32 *)*pEntry;
- if ( *pSignature == Signature ) {
- return (CONST VOID *) *pEntry;
- }
-
- //
- // Set the next entry
- //
- pEntry++;
- }
- break;
- }
-
- //
- // The entry was not found
- //
- return NULL;
-}
-
-
-/**
- Display a row containing a hex value
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pName Address of a zero terminated name string
- @param [in] Length Length in bytes
- @param [in] pChar Address of the first character
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-RowAnsiArray (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CONST CHAR8 * pName,
- IN UINTN Length,
- IN CONST CHAR8 * pChar
- )
-{
- CONST CHAR8 * pData;
- CONST CHAR8 * pEnd;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Start the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<tr><td>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- pName );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</td><td><code>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the characters
- //
- pData = pChar;
- pEnd = &pChar [ Length ];
- while ( pEnd > pData ) {
- Status = HttpSendCharacter ( SocketFD,
- pPort,
- *pData++,
- " " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the byte values
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<br/>0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- pData = pChar;
- while ( pEnd > pData ) {
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 8,
- *pData++ );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- if ( pEnd > pData ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- " 0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- }
-
- //
- // Terminate the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</code></td></tr>\r\n" );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Format a row with a list of bytes
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pName Zero terminated name string
- @param [in] ByteCount The number of bytes to display
- @param [in] pData Address of the byte array
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-RowBytes (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CHAR8 * pName,
- IN UINTN ByteCount,
- IN CONST UINT8 * pData
- )
-{
- CONST UINT8 * pEnd;
- EFI_STATUS Status;
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Start the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<tr><td>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the field name
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- pName );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the field value
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</td><td><code>0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- pEnd = &pData [ ByteCount ];
- while ( pEnd > pData ) {
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 8,
- *pData++ );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- if ( pEnd > pData ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- " 0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Terminate the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</code></td></tr>\r\n" );
- break;
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Format a row with a list of bytes
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pName Zero terminated name string
- @param [in] ByteCount The number of bytes to display
- @param [in] pData Address of the byte array
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-RowDump (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CHAR8 * pName,
- IN UINTN ByteCount,
- IN CONST UINT8 * pData
- )
-{
- EFI_STATUS Status;
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Start the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<tr><td>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the field name
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- pName );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Start the field value
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</td><td>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Dump the buffer
- //
- Status = HttpSendDump ( SocketFD,
- pPort,
- ByteCount,
- pData );
-
- //
- // Terminate the field value and row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</td></tr>\r\n" );
- break;
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Format a row with a general address
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pName Zero terminated name string
- @param [in] pAddr Address of the general address buffer
- @param [in] pWebPage Zero terminated web page address
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-RowGenericAddress (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CHAR8 * pName,
- IN CONST UINT32 * pAddr,
- IN CONST CHAR16 * pWebPage
- )
-{
- CONST GENERIC_ADDRESS * pGenericAddress;
- EFI_STATUS Status;
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Start the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<tr><td>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the field name
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- pName );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the field value
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</td><td><code>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Determine the type of address
- //
- pGenericAddress = (CONST GENERIC_ADDRESS *)pAddr;
- if ( 0 == pGenericAddress->AddressSpaceId ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "System Memory" );
- }
- else if ( 1 == pGenericAddress->AddressSpaceId ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "I/O Space" );
- }
- else if ( 2 == pGenericAddress->AddressSpaceId ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "PCI Configuration Space" );
- }
- else if ( 3 == pGenericAddress->AddressSpaceId ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "Embedded Controller" );
- }
- else if ( 4 == pGenericAddress->AddressSpaceId ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "SMBus" );
- }
- else if ( 0x7f == pGenericAddress->AddressSpaceId ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "Functional Fixed Hardware" );
- }
- else if (( 0xc0 <= pGenericAddress->AddressSpaceId )
- && ( 0xff >= pGenericAddress->AddressSpaceId )) {
- Status = HttpSendAnsiString ( SocketFD, pPort, "OEM Defined" );
- }
- else {
- Status = HttpSendAnsiString ( SocketFD, pPort, "Reserved" );
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<br/>Register Bit Width: " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendValue ( SocketFD,
- pPort,
- pGenericAddress->RegisterBitWidth );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<br/>Register Bit Offset: " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendHexValue ( SocketFD,
- pPort,
- pGenericAddress->RegisterBitOffset );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<br/>Access Size: " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendValue ( SocketFD,
- pPort,
- pGenericAddress->AccessSize );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<br/>Address: " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Add the web-page link if necessary
- //
- if ( NULL != pWebPage ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<a target=\"_blank\" href=\"" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendUnicodeString ( SocketFD,
- pPort,
- pWebPage );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "\">" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
-
- //
- // Display the address
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 64,
- pGenericAddress->Address );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Finish the web-page link if necessary
- //
- if ( NULL != pWebPage ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</a>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
-
- //
- // Terminate the row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</code></td></tr>\r\n" );
- break;
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Translate a table address into a web page
-
- @param [in] pSignature Address of the table signature
- @param [out] ppTableName Address to receive the table name address
-
- @returns Zero terminated web page address or NULL if not found
-
-**/
-CONST CHAR16 *
-SignatureLookup (
- IN UINT32 * pSignature,
- OUT CONST CHAR8 ** ppTableName
- )
-{
- CONST TABLE_SIGNATURE * pTableId;
- CONST TABLE_SIGNATURE * pEnd;
- UINT32 Signature;
-
- //
- // Walk the list of tables
- //
- Signature = *pSignature;
- pTableId = &mTableId [ 0 ];
- pEnd = &pTableId [ sizeof ( mTableId ) / sizeof ( mTableId [ 0 ])];
- while ( pEnd > pTableId ) {
- //
- // Attempt to locate the table signature
- //
- if ( pTableId->Signature == Signature ) {
- //
- // The signature was found
- // Return the web page
- //
- *ppTableName = pTableId->pTableName;
- return pTableId->pWebPage;
- }
-
- //
- // Set the next table
- //
- pTableId += 1;
- }
-
- //
- // The table was not found
- //
- *ppTableName = (CONST CHAR8 *)pSignature;
- return NULL;
-}
-
-
-/**
- Respond with the ACPI DSDT table
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-AcpiDsdtPage (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- OUT BOOLEAN * pbDone
- )
-{
- CONST ACPI_DSDT * pDsdt;
- CONST ACPI_FADT * pFadt;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Send the DADT page
- //
- for ( ; ; ) {
- //
- // Locate the DADT
- //
- pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );
- if ( NULL == pFadt ) {
- Status = EFI_NOT_FOUND;
- break;
- }
- pDsdt = (VOID *)pFadt->XDsdt;
-
- //
- // Send the page and table header
- //
- Status = TableHeader ( SocketFD, pPort, L"DSDT - Differentiated System Description Table", pDsdt );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the DSDT header
- //
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Signature",
- sizeof ( pDsdt->Signature ),
- (CHAR8 *)&pDsdt->Signature );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Length",
- pDsdt->Length );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Revision",
- pDsdt->Revision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Checksum",
- pDsdt->Checksum,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OEMID",
- sizeof ( pDsdt->OemId ),
- &pDsdt->OemId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OEM Table ID",
- sizeof ( pDsdt->OemTableId ),
- &pDsdt->OemTableId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowRevision ( SocketFD,
- pPort,
- "OEM Revision",
- pDsdt->OemRevision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Creator ID",
- sizeof ( pDsdt->CreatorId ),
- (CHAR8 *)&pDsdt->CreatorId );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowRevision ( SocketFD,
- pPort,
- "Creator Revision",
- pDsdt->CreatorRevision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the data from the DSDT
- //
- Status = RowDump ( SocketFD,
- pPort,
- "Definition Block",
- pDsdt->Length - sizeof ( *pDsdt ) + 1,
- &pDsdt->DefinitionBlock[0]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Build the table trailer
- //
- Status = TableTrailer ( SocketFD,
- pPort,
- pbDone );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Respond with the ACPI FADT table
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-AcpiFadtPage (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- OUT BOOLEAN * pbDone
- )
-{
- CONST ACPI_FADT * pFadt;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Send the FADT page
- //
- for ( ; ; ) {
- //
- // Locate the FADT
- //
- pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );
- if ( NULL == pFadt ) {
- Status = EFI_NOT_FOUND;
- break;
- }
-
- //
- // Send the page and table header
- //
- Status = TableHeader ( SocketFD, pPort, L"FADT - Fixed ACPI Description Table", pFadt );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the FSDT header
- //
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Signature",
- sizeof ( pFadt->Signature ),
- (CHAR8 *)&pFadt->Signature );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Length",
- pFadt->Length );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Revision",
- pFadt->Revision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Checksum",
- pFadt->Checksum,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OEMID",
- sizeof ( pFadt->OemId ),
- &pFadt->OemId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OEM Table ID",
- sizeof ( pFadt->OemTableId ),
- &pFadt->OemTableId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowRevision ( SocketFD,
- pPort,
- "OEM Revision",
- pFadt->OemRevision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Creator ID",
- sizeof ( pFadt->CreatorId ),
- (CHAR8 *)&pFadt->CreatorId );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowRevision ( SocketFD,
- pPort,
- "Creator Revision",
- pFadt->CreatorRevision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the data from the FADT
- //
- Status = RowPointer ( SocketFD,
- pPort,
- "FIRMWARE_CTRL",
- (CONST VOID *)pFadt->FirmwareCtrl,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowPointer ( SocketFD,
- pPort,
- "DSDT",
- (CONST VOID *)pFadt->DSDT,
- ( pFadt->DSDT == pFadt->XDsdt ) ? PAGE_ACPI_DSDT : NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Reserved",
- pFadt->Reserved,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Preferred_PM_Profile",
- pFadt->PreferredPmProfile,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "SCI_INT",
- pFadt->SciInt,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "SMI_CMD",
- pFadt->SmiCmd,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "ACPI_ENABLE",
- pFadt->AcpiEnable,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "ACPI_DISABLE",
- pFadt->AcpiDisable,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "S4BIOS_REQ",
- pFadt->S4BiosReq,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PSTATE_CNT",
- pFadt->PStateCnt,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PM1a_EVT_BLK",
- pFadt->Pm1aEvtBlk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PM1b_EVT_BLK",
- pFadt->Pm1bEvtBlk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PM1a_CNT_BLK",
- pFadt->Pm1aCntBlk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PM1b_CNT_BLK",
- pFadt->Pm1bCntBlk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PM2_CNT_BLK",
- pFadt->Pm2CntBlk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "PM_TMR_BLK",
- pFadt->PmTmrBlk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- Status = RowHexValue ( SocketFD,
- pPort,
- "GPE0_BLK",
- pFadt->Gpe0Blk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "GPE1_BLK",
- pFadt->Gpe1Blk,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "PM1_EVT_LEN",
- pFadt->Pm1EvtLen );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "PM1_CNT_LEN",
- pFadt->Pm1CntLen );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "PM2_CNT_LEN",
- pFadt->PM2CntLen );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "PM_TMR_LEN",
- pFadt->PmTmrLen );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "GPE0_BLK_LEN",
- pFadt->Gpe0BlkLen );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "GPE1_BLK_LEN",
- pFadt->Gpe1BlkLen );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "GPE1_BASE",
- pFadt->Gpe1Base,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "CST_CNT",
- pFadt->CstCnt );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "P_LVL2_LAT",
- pFadt->PLvl2Lat,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "P_LVL3_LAT",
- pFadt->PLvl3Lat,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "FLUSH_SIZE",
- pFadt->FlushSize );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "FLUSH_Stride",
- pFadt->FlushStride );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "DUTY_OFFSET",
- pFadt->DutyOffset,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "DUTY_WIDTH",
- pFadt->DutyWidth,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "DAY_ALRM",
- pFadt->DayAlrm,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "MON_ALRM",
- pFadt->MonAlrm,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "CENTURY",
- pFadt->Century,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "IAPC_BOOT_ARCH",
- pFadt->IapcBootArch,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Reserved",
- pFadt->Reserved2,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Flags",
- pFadt->Flags,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "RESET_REG",
- &pFadt->ResetReg[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "RESET_VALUE",
- pFadt->ResetValue,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Reserved",
- pFadt->Reserved3[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Reserved",
- pFadt->Reserved3[1],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Reserved",
- pFadt->Reserved3[2],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "X_FIRMWARE_CTRL",
- pFadt->XFirmwareCtrl,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "X_DSDT",
- pFadt->XDsdt,
- PAGE_ACPI_DSDT );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_PM1a_EVT_BLK",
- &pFadt->XPm1aEvtBlk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_PM1b_EVT_BLK",
- &pFadt->XPm1bEvtBlk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_PM1a_CNT_BLK",
- &pFadt->XPm1aCntBlk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_PM1b_CNT_BLK",
- &pFadt->XPm1bCntBlk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_PM2_CNT_BLK",
- &pFadt->XPm2CntBlk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_PM_TMR_BLK",
- &pFadt->XPmTmrBlk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_GPE0_BLK",
- &pFadt->XGpe0Blk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowGenericAddress ( SocketFD,
- pPort,
- "X_GPE1_BLK",
- &pFadt->XGpe1Blk[0],
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Build the table trailer
- //
- Status = TableTrailer ( SocketFD,
- pPort,
- pbDone );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Respond with the ACPI RSDP 1.0b table
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-AcpiRsdp10Page (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- OUT BOOLEAN * pbDone
- )
-{
- CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Send the RSDP page
- //
- for ( ; ; ) {
- //
- // Locate the RSDP
- //
- Status = EfiGetSystemConfigurationTable ( &gEfiAcpi10TableGuid, (VOID **) &pRsdp10b );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the page and table header
- //
- Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 1.0b Root System Description Pointer", pRsdp10b );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the RSDP
- //
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Signature",
- sizeof ( pRsdp10b->Signature ),
- (CHAR8 *)&pRsdp10b->Signature );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Checksum",
- pRsdp10b->Checksum,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OemId",
- sizeof ( pRsdp10b->OemId ),
- &pRsdp10b->OemId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Reserved",
- pRsdp10b->Reserved,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowPointer ( SocketFD,
- pPort,
- "RsdtAddress",
- (VOID *)pRsdp10b->RsdtAddress,
- PAGE_ACPI_RSDT );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Build the table trailer
- //
- Status = TableTrailer ( SocketFD,
- pPort,
- pbDone );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Respond with the ACPI RSDP 3.0 table
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-AcpiRsdp30Page (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- OUT BOOLEAN * pbDone
- )
-{
- CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Send the RSDP page
- //
- for ( ; ; ) {
- //
- // Locate the RSDP
- //
- Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **) &pRsdp30 );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the page and table header
- //
- Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 3.0 Root System Description Pointer", pRsdp30 );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the RSDP
- //
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Signature",
- sizeof ( pRsdp30->Signature ),
- (CHAR8 *)&pRsdp30->Signature );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Checksum",
- pRsdp30->Checksum,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OemId",
- sizeof ( pRsdp30->OemId ),
- &pRsdp30->OemId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Revision",
- pRsdp30->Revision,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowPointer ( SocketFD,
- pPort,
- "RsdtAddress",
- (VOID *)pRsdp30->RsdtAddress,
- PAGE_ACPI_RSDT );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Length",
- pRsdp30->Length );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowPointer ( SocketFD,
- pPort,
- "XsdtAddress",
- (VOID *)pRsdp30->XsdtAddress,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "ExtendedChecksum",
- pRsdp30->ExtendedChecksum,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowBytes ( SocketFD,
- pPort,
- "Reserved",
- sizeof ( pRsdp30->Reserved ),
- &pRsdp30->Reserved [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Build the table trailer
- //
- Status = TableTrailer ( SocketFD,
- pPort,
- pbDone );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Respond with the ACPI RSDT table
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-AcpiRsdtPage (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- OUT BOOLEAN * pbDone
- )
-{
- CONST UINT32 * pEnd;
- CONST UINT32 * pEntry;
- CONST ACPI_RSDT * pRsdt;
- CONST CHAR8 * pTableName;
- CONST CHAR16 * pWebPage;
- EFI_STATUS Status;
- UINT32 TableName [ 2 ];
-
- DBG_ENTER ( );
-
- //
- // Send the RSDT page
- //
- for ( ; ; ) {
- //
- // Locate the RSDT
- //
- pRsdt = LocateRsdt ( );
- if ( NULL == pRsdt ) {
- Status = EFI_NOT_FOUND;
- break;
- }
-
- //
- // Send the page and table header
- //
- Status = TableHeader ( SocketFD, pPort, L"RSDT - ACPI Root System Description Table", pRsdt );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the RSDT
- //
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Signature",
- sizeof ( pRsdt->Signature ),
- (CHAR8 *)&pRsdt->Signature );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Length",
- pRsdt->Length );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowDecimalValue ( SocketFD,
- pPort,
- "Revision",
- pRsdt->Revision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowHexValue ( SocketFD,
- pPort,
- "Checksum",
- pRsdt->Checksum,
- NULL );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OEMID",
- sizeof ( pRsdt->OemId ),
- &pRsdt->OemId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "OEM Table ID",
- sizeof ( pRsdt->OemTableId ),
- &pRsdt->OemTableId [ 0 ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowRevision ( SocketFD,
- pPort,
- "OEM Revision",
- pRsdt->OemRevision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowAnsiArray ( SocketFD,
- pPort,
- "Creator ID",
- sizeof ( pRsdt->CreatorId ),
- (CHAR8 *)&pRsdt->CreatorId );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = RowRevision ( SocketFD,
- pPort,
- "Creator Revision",
- pRsdt->CreatorRevision );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Walk the list of entries
- //
- pEntry = &pRsdt->Entry [ 0 ];
- pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];
- TableName [ 1 ] = 0;
- while ( pEnd > pEntry ) {
- //
- // The entry is actually a 32-bit physical table address
- // The first entry in the table is the 32-bit table signature
- //
- TableName [ 0 ] = *(UINT32 *)*pEntry;
- pWebPage = SignatureLookup ( &TableName [ 0 ], &pTableName );
-
- //
- // Display the table address
- //
- Status = RowPointer ( SocketFD,
- pPort,
- pTableName,
- (VOID *)*pEntry,
- pWebPage );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- pEntry++;
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Build the table trailer
- //
- Status = TableTrailer ( SocketFD,
- pPort,
- pbDone );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
+/*++\r
+ This file contains an 'Intel UEFI Application' and is\r
+ licensed for Intel CPUs and chipsets under the terms of your\r
+ license agreement with Intel or your vendor. This file may\r
+ be modified by the user, subject to additional terms of the\r
+ license agreement\r
+--*/\r
+/*++\r
+\r
+Copyright (c) 2011 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+--*/\r
+\r
+/** @file\r
+ Display the runtime services table\r
+\r
+**/\r
+\r
+#include <WebServer.h>\r
+#include <Guid/Acpi.h>\r
+#include <IndustryStandard/Acpi10.h>\r
+#include <IndustryStandard/Acpi30.h>\r
+\r
+#pragma warning ( disable : 4305 )\r
+\r
+//\r
+// Ensure proper structure formats\r
+//\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+ UINT8 AddressSpaceId;\r
+ UINT8 RegisterBitWidth;\r
+ UINT8 RegisterBitOffset;\r
+ UINT8 AccessSize;\r
+ UINT64 Address;\r
+} GENERIC_ADDRESS;\r
+\r
+\r
+typedef struct {\r
+ UINT32 Signature; // 0\r
+ UINT32 Length; // 4\r
+ UINT8 Revision; // 8\r
+ UINT8 Checksum; // 9\r
+ UINT8 OemId[6]; // 10\r
+ UINT8 OemTableId[8]; // 16\r
+ UINT32 OemRevision; // 24\r
+ UINT32 CreatorId; // 28\r
+ UINT32 CreatorRevision; // 32\r
+ UINT8 DefinitionBlock[1]; // 36\r
+} ACPI_DSDT;\r
+\r
+\r
+typedef struct {\r
+ UINT32 Signature; // 0\r
+ UINT32 Length; // 4\r
+ UINT8 Revision; // 8\r
+ UINT8 Checksum; // 9\r
+ UINT8 OemId[6]; // 10\r
+ UINT8 OemTableId[8]; // 16\r
+ UINT32 OemRevision; // 24\r
+ UINT32 CreatorId; // 28\r
+ UINT32 CreatorRevision; // 32\r
+ UINT32 FirmwareCtrl; // 36\r
+ UINT32 DSDT; // 40\r
+ UINT8 Reserved; // 44\r
+ UINT8 PreferredPmProfile; // 45\r
+ UINT16 SciInt; // 46\r
+ UINT32 SmiCmd; // 48\r
+ UINT8 AcpiEnable; // 52\r
+ UINT8 AcpiDisable; // 53\r
+ UINT8 S4BiosReq; // 54\r
+ UINT8 PStateCnt; // 55\r
+ UINT32 Pm1aEvtBlk; // 56\r
+ UINT32 Pm1bEvtBlk; // 60\r
+ UINT32 Pm1aCntBlk; // 64\r
+ UINT32 Pm1bCntBlk; // 68\r
+ UINT32 Pm2CntBlk; // 72\r
+ UINT32 PmTmrBlk; // 76\r
+ UINT32 Gpe0Blk; // 80\r
+ UINT32 Gpe1Blk; // 84\r
+ UINT8 Pm1EvtLen; // 88\r
+ UINT8 Pm1CntLen; // 89\r
+ UINT8 PM2CntLen; // 90\r
+ UINT8 PmTmrLen; // 91\r
+ UINT8 Gpe0BlkLen; // 92\r
+ UINT8 Gpe1BlkLen; // 93\r
+ UINT8 Gpe1Base; // 94\r
+ UINT8 CstCnt; // 95\r
+ UINT16 PLvl2Lat; // 96\r
+ UINT16 PLvl3Lat; // 98\r
+ UINT16 FlushSize; // 100\r
+ UINT16 FlushStride; // 102\r
+ UINT8 DutyOffset; // 104\r
+ UINT8 DutyWidth; // 105\r
+ UINT8 DayAlrm; // 106\r
+ UINT8 MonAlrm; // 107\r
+ UINT8 Century; // 108\r
+ UINT16 IapcBootArch; // 109\r
+ UINT8 Reserved2; // 111\r
+ UINT32 Flags; // 112\r
+ UINT32 ResetReg [3]; // 116\r
+ UINT8 ResetValue; // 128\r
+ UINT8 Reserved3 [3]; // 129\r
+ UINT64 XFirmwareCtrl; // 132\r
+ UINT64 XDsdt; // 140\r
+ UINT32 XPm1aEvtBlk [3]; // 148\r
+ UINT32 XPm1bEvtBlk [3]; // 160\r
+ UINT32 XPm1aCntBlk [3]; // 172\r
+ UINT32 XPm1bCntBlk [3]; // 184\r
+ UINT32 XPm2CntBlk [3]; // 196\r
+ UINT32 XPmTmrBlk [3]; // 208\r
+ UINT32 XGpe0Blk [3]; // 220\r
+ UINT32 XGpe1Blk [3]; // 232\r
+} ACPI_FADT;\r
+\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ UINT32 Length;\r
+ UINT8 Revision;\r
+ UINT8 Checksum;\r
+ UINT8 OemId[6];\r
+ UINT8 OemTableId[8];\r
+ UINT32 OemRevision;\r
+ UINT32 CreatorId;\r
+ UINT32 CreatorRevision;\r
+ UINT32 Entry[1];\r
+} ACPI_RSDT;\r
+\r
+\r
+#pragma pack()\r
+\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ CONST CHAR8 * pTableName;\r
+ CONST CHAR16 * pWebPage;\r
+} TABLE_SIGNATURE;\r
+\r
+\r
+CONST TABLE_SIGNATURE mTableId [] = {\r
+ { DSDT_SIGNATURE, "DSDT", PAGE_ACPI_DSDT },\r
+ { FADT_SIGNATURE, "FADT", PAGE_ACPI_FADT }\r
+};\r
+\r
+\r
+/**\r
+ Locate the RSDT table\r
+\r
+ @return Table address or NULL if not found\r
+\r
+**/\r
+CONST ACPI_RSDT *\r
+LocateRsdt (\r
+ VOID\r
+ )\r
+{\r
+ CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;\r
+ CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;\r
+ CONST ACPI_RSDT * pRsdt;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ pRsdt = NULL;\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the RSDT\r
+ //\r
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;\r
+ }\r
+ else {\r
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The entry was not found\r
+ //\r
+ return pRsdt;\r
+}\r
+\r
+\r
+/**\r
+ Locate the specified table\r
+\r
+ @param [in] Signature Table signature\r
+\r
+ @return Table address or NULL if not found\r
+\r
+**/\r
+CONST VOID *\r
+LocateTable (\r
+ IN UINT32 Signature\r
+ )\r
+{\r
+ CONST UINT32 * pEnd;\r
+ CONST UINT32 * pEntry;\r
+ CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;\r
+ CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;\r
+ CONST ACPI_RSDT * pRsdt;\r
+ CONST UINT32 * pSignature;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the RSDT\r
+ //\r
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **)&pRsdp30 );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ pRsdt = (ACPI_RSDT *)pRsdp30->RsdtAddress;\r
+ }\r
+ else {\r
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&pRsdp10b );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ pRsdt = (ACPI_RSDT *)pRsdp10b->RsdtAddress;\r
+ }\r
+\r
+ //\r
+ // Walk the list of entries\r
+ //\r
+ pEntry = &pRsdt->Entry [ 0 ];\r
+ pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];\r
+ while ( pEnd > pEntry ) {\r
+ //\r
+ // The entry is actually a 32-bit physical table address\r
+ // The first entry in the table is the 32-bit table signature\r
+ //\r
+ pSignature = (UINT32 *)*pEntry;\r
+ if ( *pSignature == Signature ) {\r
+ return (CONST VOID *) *pEntry;\r
+ }\r
+\r
+ //\r
+ // Set the next entry\r
+ //\r
+ pEntry++;\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The entry was not found\r
+ //\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Display a row containing a hex value\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pName Address of a zero terminated name string\r
+ @param [in] Length Length in bytes\r
+ @param [in] pChar Address of the first character\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowAnsiArray (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CONST CHAR8 * pName,\r
+ IN UINTN Length,\r
+ IN CONST CHAR8 * pChar\r
+ )\r
+{\r
+ CONST CHAR8 * pData;\r
+ CONST CHAR8 * pEnd;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Start the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<tr><td>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ pName );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</td><td><code>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the characters\r
+ //\r
+ pData = pChar;\r
+ pEnd = &pChar [ Length ];\r
+ while ( pEnd > pData ) {\r
+ Status = HttpSendCharacter ( SocketFD,\r
+ pPort,\r
+ *pData++,\r
+ " " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the byte values\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<br/>0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ pData = pChar;\r
+ while ( pEnd > pData ) {\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 8,\r
+ *pData++ );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ if ( pEnd > pData ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ " 0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Terminate the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</code></td></tr>\r\n" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Format a row with a list of bytes\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pName Zero terminated name string\r
+ @param [in] ByteCount The number of bytes to display\r
+ @param [in] pData Address of the byte array\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowBytes (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CHAR8 * pName,\r
+ IN UINTN ByteCount,\r
+ IN CONST UINT8 * pData\r
+ )\r
+{\r
+ CONST UINT8 * pEnd;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Start the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<tr><td>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the field name\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ pName );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the field value\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</td><td><code>0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ pEnd = &pData [ ByteCount ];\r
+ while ( pEnd > pData ) {\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 8,\r
+ *pData++ );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ if ( pEnd > pData ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ " 0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Terminate the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</code></td></tr>\r\n" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Format a row with a list of bytes\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pName Zero terminated name string\r
+ @param [in] ByteCount The number of bytes to display\r
+ @param [in] pData Address of the byte array\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowDump (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CHAR8 * pName,\r
+ IN UINTN ByteCount,\r
+ IN CONST UINT8 * pData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Start the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<tr><td>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the field name\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ pName );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Start the field value\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</td><td>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Dump the buffer\r
+ //\r
+ Status = HttpSendDump ( SocketFD,\r
+ pPort,\r
+ ByteCount,\r
+ pData );\r
+\r
+ //\r
+ // Terminate the field value and row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</td></tr>\r\n" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Format a row with a general address\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pName Zero terminated name string\r
+ @param [in] pAddr Address of the general address buffer\r
+ @param [in] pWebPage Zero terminated web page address\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+RowGenericAddress (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CHAR8 * pName,\r
+ IN CONST UINT32 * pAddr,\r
+ IN CONST CHAR16 * pWebPage\r
+ )\r
+{\r
+ CONST GENERIC_ADDRESS * pGenericAddress;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Start the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<tr><td>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the field name\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ pName );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the field value\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</td><td><code>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Determine the type of address\r
+ //\r
+ pGenericAddress = (CONST GENERIC_ADDRESS *)pAddr;\r
+ if ( 0 == pGenericAddress->AddressSpaceId ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "System Memory" );\r
+ }\r
+ else if ( 1 == pGenericAddress->AddressSpaceId ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "I/O Space" );\r
+ }\r
+ else if ( 2 == pGenericAddress->AddressSpaceId ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "PCI Configuration Space" );\r
+ }\r
+ else if ( 3 == pGenericAddress->AddressSpaceId ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "Embedded Controller" );\r
+ }\r
+ else if ( 4 == pGenericAddress->AddressSpaceId ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "SMBus" );\r
+ }\r
+ else if ( 0x7f == pGenericAddress->AddressSpaceId ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "Functional Fixed Hardware" );\r
+ }\r
+ else if (( 0xc0 <= pGenericAddress->AddressSpaceId )\r
+ && ( 0xff >= pGenericAddress->AddressSpaceId )) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "OEM Defined" );\r
+ }\r
+ else {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "Reserved" );\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<br/>Register Bit Width: " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendValue ( SocketFD,\r
+ pPort,\r
+ pGenericAddress->RegisterBitWidth );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<br/>Register Bit Offset: " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendHexValue ( SocketFD,\r
+ pPort,\r
+ pGenericAddress->RegisterBitOffset );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<br/>Access Size: " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendValue ( SocketFD,\r
+ pPort,\r
+ pGenericAddress->AccessSize );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<br/>Address: " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Add the web-page link if necessary\r
+ //\r
+ if ( NULL != pWebPage ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<a target=\"_blank\" href=\"" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendUnicodeString ( SocketFD,\r
+ pPort,\r
+ pWebPage );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "\">" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Display the address\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 64,\r
+ pGenericAddress->Address );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Finish the web-page link if necessary\r
+ //\r
+ if ( NULL != pWebPage ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</a>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Terminate the row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</code></td></tr>\r\n" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Translate a table address into a web page\r
+\r
+ @param [in] pSignature Address of the table signature\r
+ @param [out] ppTableName Address to receive the table name address\r
+\r
+ @return Zero terminated web page address or NULL if not found\r
+\r
+**/\r
+CONST CHAR16 *\r
+SignatureLookup (\r
+ IN UINT32 * pSignature,\r
+ OUT CONST CHAR8 ** ppTableName\r
+ )\r
+{\r
+ CONST TABLE_SIGNATURE * pTableId;\r
+ CONST TABLE_SIGNATURE * pEnd;\r
+ UINT32 Signature;\r
+\r
+ //\r
+ // Walk the list of tables\r
+ //\r
+ Signature = *pSignature;\r
+ pTableId = &mTableId [ 0 ];\r
+ pEnd = &pTableId [ sizeof ( mTableId ) / sizeof ( mTableId [ 0 ])];\r
+ while ( pEnd > pTableId ) {\r
+ //\r
+ // Attempt to locate the table signature\r
+ //\r
+ if ( pTableId->Signature == Signature ) {\r
+ //\r
+ // The signature was found\r
+ // Return the web page\r
+ //\r
+ *ppTableName = pTableId->pTableName;\r
+ return pTableId->pWebPage;\r
+ }\r
+\r
+ //\r
+ // Set the next table\r
+ //\r
+ pTableId += 1;\r
+ }\r
+\r
+ //\r
+ // The table was not found\r
+ //\r
+ *ppTableName = (CONST CHAR8 *)pSignature;\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Respond with the ACPI DSDT table\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+AcpiDsdtPage (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ OUT BOOLEAN * pbDone\r
+ )\r
+{\r
+ CONST ACPI_DSDT * pDsdt;\r
+ CONST ACPI_FADT * pFadt;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Send the DADT page\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the DADT\r
+ //\r
+ pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );\r
+ if ( NULL == pFadt ) {\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+ pDsdt = (VOID *)pFadt->XDsdt;\r
+\r
+ //\r
+ // Send the page and table header\r
+ //\r
+ Status = TableHeader ( SocketFD, pPort, L"DSDT - Differentiated System Description Table", pDsdt );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the DSDT header\r
+ //\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Signature",\r
+ sizeof ( pDsdt->Signature ),\r
+ (CHAR8 *)&pDsdt->Signature );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Length",\r
+ pDsdt->Length );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Revision",\r
+ pDsdt->Revision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Checksum",\r
+ pDsdt->Checksum,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OEMID",\r
+ sizeof ( pDsdt->OemId ),\r
+ &pDsdt->OemId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OEM Table ID",\r
+ sizeof ( pDsdt->OemTableId ),\r
+ &pDsdt->OemTableId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowRevision ( SocketFD,\r
+ pPort,\r
+ "OEM Revision",\r
+ pDsdt->OemRevision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Creator ID",\r
+ sizeof ( pDsdt->CreatorId ),\r
+ (CHAR8 *)&pDsdt->CreatorId );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowRevision ( SocketFD,\r
+ pPort,\r
+ "Creator Revision",\r
+ pDsdt->CreatorRevision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the data from the DSDT\r
+ //\r
+ Status = RowDump ( SocketFD,\r
+ pPort,\r
+ "Definition Block",\r
+ pDsdt->Length - sizeof ( *pDsdt ) + 1,\r
+ &pDsdt->DefinitionBlock[0]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Build the table trailer\r
+ //\r
+ Status = TableTrailer ( SocketFD,\r
+ pPort,\r
+ pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Respond with the ACPI FADT table\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+AcpiFadtPage (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ OUT BOOLEAN * pbDone\r
+ )\r
+{\r
+ CONST ACPI_FADT * pFadt;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Send the FADT page\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the FADT\r
+ //\r
+ pFadt = (ACPI_FADT *)LocateTable ( FADT_SIGNATURE );\r
+ if ( NULL == pFadt ) {\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page and table header\r
+ //\r
+ Status = TableHeader ( SocketFD, pPort, L"FADT - Fixed ACPI Description Table", pFadt );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the FSDT header\r
+ //\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Signature",\r
+ sizeof ( pFadt->Signature ),\r
+ (CHAR8 *)&pFadt->Signature );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Length",\r
+ pFadt->Length );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Revision",\r
+ pFadt->Revision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Checksum",\r
+ pFadt->Checksum,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OEMID",\r
+ sizeof ( pFadt->OemId ),\r
+ &pFadt->OemId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OEM Table ID",\r
+ sizeof ( pFadt->OemTableId ),\r
+ &pFadt->OemTableId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowRevision ( SocketFD,\r
+ pPort,\r
+ "OEM Revision",\r
+ pFadt->OemRevision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Creator ID",\r
+ sizeof ( pFadt->CreatorId ),\r
+ (CHAR8 *)&pFadt->CreatorId );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowRevision ( SocketFD,\r
+ pPort,\r
+ "Creator Revision",\r
+ pFadt->CreatorRevision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the data from the FADT\r
+ //\r
+ Status = RowPointer ( SocketFD,\r
+ pPort,\r
+ "FIRMWARE_CTRL",\r
+ (CONST VOID *)pFadt->FirmwareCtrl,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowPointer ( SocketFD,\r
+ pPort,\r
+ "DSDT",\r
+ (CONST VOID *)pFadt->DSDT,\r
+ ( pFadt->DSDT == pFadt->XDsdt ) ? PAGE_ACPI_DSDT : NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ pFadt->Reserved,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Preferred_PM_Profile",\r
+ pFadt->PreferredPmProfile,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "SCI_INT",\r
+ pFadt->SciInt,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "SMI_CMD",\r
+ pFadt->SmiCmd,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "ACPI_ENABLE",\r
+ pFadt->AcpiEnable,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "ACPI_DISABLE",\r
+ pFadt->AcpiDisable,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "S4BIOS_REQ",\r
+ pFadt->S4BiosReq,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PSTATE_CNT",\r
+ pFadt->PStateCnt,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PM1a_EVT_BLK",\r
+ pFadt->Pm1aEvtBlk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PM1b_EVT_BLK",\r
+ pFadt->Pm1bEvtBlk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PM1a_CNT_BLK",\r
+ pFadt->Pm1aCntBlk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PM1b_CNT_BLK",\r
+ pFadt->Pm1bCntBlk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PM2_CNT_BLK",\r
+ pFadt->Pm2CntBlk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "PM_TMR_BLK",\r
+ pFadt->PmTmrBlk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "GPE0_BLK",\r
+ pFadt->Gpe0Blk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "GPE1_BLK",\r
+ pFadt->Gpe1Blk,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "PM1_EVT_LEN",\r
+ pFadt->Pm1EvtLen );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "PM1_CNT_LEN",\r
+ pFadt->Pm1CntLen );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "PM2_CNT_LEN",\r
+ pFadt->PM2CntLen );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "PM_TMR_LEN",\r
+ pFadt->PmTmrLen );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "GPE0_BLK_LEN",\r
+ pFadt->Gpe0BlkLen );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "GPE1_BLK_LEN",\r
+ pFadt->Gpe1BlkLen );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "GPE1_BASE",\r
+ pFadt->Gpe1Base,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "CST_CNT",\r
+ pFadt->CstCnt );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "P_LVL2_LAT",\r
+ pFadt->PLvl2Lat,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "P_LVL3_LAT",\r
+ pFadt->PLvl3Lat,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "FLUSH_SIZE",\r
+ pFadt->FlushSize );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "FLUSH_Stride",\r
+ pFadt->FlushStride );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "DUTY_OFFSET",\r
+ pFadt->DutyOffset,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "DUTY_WIDTH",\r
+ pFadt->DutyWidth,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "DAY_ALRM",\r
+ pFadt->DayAlrm,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "MON_ALRM",\r
+ pFadt->MonAlrm,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "CENTURY",\r
+ pFadt->Century,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "IAPC_BOOT_ARCH",\r
+ pFadt->IapcBootArch,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ pFadt->Reserved2,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Flags",\r
+ pFadt->Flags,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "RESET_REG",\r
+ &pFadt->ResetReg[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "RESET_VALUE",\r
+ pFadt->ResetValue,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ pFadt->Reserved3[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ pFadt->Reserved3[1],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ pFadt->Reserved3[2],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "X_FIRMWARE_CTRL",\r
+ pFadt->XFirmwareCtrl,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "X_DSDT",\r
+ pFadt->XDsdt,\r
+ PAGE_ACPI_DSDT );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_PM1a_EVT_BLK",\r
+ &pFadt->XPm1aEvtBlk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_PM1b_EVT_BLK",\r
+ &pFadt->XPm1bEvtBlk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_PM1a_CNT_BLK",\r
+ &pFadt->XPm1aCntBlk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_PM1b_CNT_BLK",\r
+ &pFadt->XPm1bCntBlk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_PM2_CNT_BLK",\r
+ &pFadt->XPm2CntBlk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_PM_TMR_BLK",\r
+ &pFadt->XPmTmrBlk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_GPE0_BLK",\r
+ &pFadt->XGpe0Blk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowGenericAddress ( SocketFD,\r
+ pPort,\r
+ "X_GPE1_BLK",\r
+ &pFadt->XGpe1Blk[0],\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Build the table trailer\r
+ //\r
+ Status = TableTrailer ( SocketFD,\r
+ pPort,\r
+ pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Respond with the ACPI RSDP 1.0b table\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+AcpiRsdp10Page (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ OUT BOOLEAN * pbDone\r
+ )\r
+{\r
+ CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp10b;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Send the RSDP page\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the RSDP\r
+ //\r
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpi10TableGuid, (VOID **) &pRsdp10b );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page and table header\r
+ //\r
+ Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 1.0b Root System Description Pointer", pRsdp10b );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the RSDP\r
+ //\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Signature",\r
+ sizeof ( pRsdp10b->Signature ),\r
+ (CHAR8 *)&pRsdp10b->Signature );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Checksum",\r
+ pRsdp10b->Checksum,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OemId",\r
+ sizeof ( pRsdp10b->OemId ),\r
+ &pRsdp10b->OemId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ pRsdp10b->Reserved,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowPointer ( SocketFD,\r
+ pPort,\r
+ "RsdtAddress",\r
+ (VOID *)pRsdp10b->RsdtAddress,\r
+ PAGE_ACPI_RSDT );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Build the table trailer\r
+ //\r
+ Status = TableTrailer ( SocketFD,\r
+ pPort,\r
+ pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Respond with the ACPI RSDP 3.0 table\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+AcpiRsdp30Page (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ OUT BOOLEAN * pbDone\r
+ )\r
+{\r
+ CONST EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER * pRsdp30;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Send the RSDP page\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the RSDP\r
+ //\r
+ Status = EfiGetSystemConfigurationTable ( &gEfiAcpiTableGuid, (VOID **) &pRsdp30 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page and table header\r
+ //\r
+ Status = TableHeader ( SocketFD, pPort, L"RSDP - ACPI 3.0 Root System Description Pointer", pRsdp30 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the RSDP\r
+ //\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Signature",\r
+ sizeof ( pRsdp30->Signature ),\r
+ (CHAR8 *)&pRsdp30->Signature );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Checksum",\r
+ pRsdp30->Checksum,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OemId",\r
+ sizeof ( pRsdp30->OemId ),\r
+ &pRsdp30->OemId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Revision",\r
+ pRsdp30->Revision,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowPointer ( SocketFD,\r
+ pPort,\r
+ "RsdtAddress",\r
+ (VOID *)pRsdp30->RsdtAddress,\r
+ PAGE_ACPI_RSDT );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Length",\r
+ pRsdp30->Length );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowPointer ( SocketFD,\r
+ pPort,\r
+ "XsdtAddress",\r
+ (VOID *)pRsdp30->XsdtAddress,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "ExtendedChecksum",\r
+ pRsdp30->ExtendedChecksum,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowBytes ( SocketFD,\r
+ pPort,\r
+ "Reserved",\r
+ sizeof ( pRsdp30->Reserved ),\r
+ &pRsdp30->Reserved [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Build the table trailer\r
+ //\r
+ Status = TableTrailer ( SocketFD,\r
+ pPort,\r
+ pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Respond with the ACPI RSDT table\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+AcpiRsdtPage (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ OUT BOOLEAN * pbDone\r
+ )\r
+{\r
+ CONST UINT32 * pEnd;\r
+ CONST UINT32 * pEntry;\r
+ CONST ACPI_RSDT * pRsdt;\r
+ CONST CHAR8 * pTableName;\r
+ CONST CHAR16 * pWebPage;\r
+ EFI_STATUS Status;\r
+ UINT32 TableName [ 2 ];\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Send the RSDT page\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Locate the RSDT\r
+ //\r
+ pRsdt = LocateRsdt ( );\r
+ if ( NULL == pRsdt ) {\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page and table header\r
+ //\r
+ Status = TableHeader ( SocketFD, pPort, L"RSDT - ACPI Root System Description Table", pRsdt );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the RSDT\r
+ //\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Signature",\r
+ sizeof ( pRsdt->Signature ),\r
+ (CHAR8 *)&pRsdt->Signature );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Length",\r
+ pRsdt->Length );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowDecimalValue ( SocketFD,\r
+ pPort,\r
+ "Revision",\r
+ pRsdt->Revision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowHexValue ( SocketFD,\r
+ pPort,\r
+ "Checksum",\r
+ pRsdt->Checksum,\r
+ NULL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OEMID",\r
+ sizeof ( pRsdt->OemId ),\r
+ &pRsdt->OemId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "OEM Table ID",\r
+ sizeof ( pRsdt->OemTableId ),\r
+ &pRsdt->OemTableId [ 0 ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowRevision ( SocketFD,\r
+ pPort,\r
+ "OEM Revision",\r
+ pRsdt->OemRevision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowAnsiArray ( SocketFD,\r
+ pPort,\r
+ "Creator ID",\r
+ sizeof ( pRsdt->CreatorId ),\r
+ (CHAR8 *)&pRsdt->CreatorId );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = RowRevision ( SocketFD,\r
+ pPort,\r
+ "Creator Revision",\r
+ pRsdt->CreatorRevision );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Walk the list of entries\r
+ //\r
+ pEntry = &pRsdt->Entry [ 0 ];\r
+ pEnd = &pEntry [(( pRsdt->Length - sizeof ( *pRsdt )) >> 2 ) + 1 ];\r
+ TableName [ 1 ] = 0;\r
+ while ( pEnd > pEntry ) {\r
+ //\r
+ // The entry is actually a 32-bit physical table address\r
+ // The first entry in the table is the 32-bit table signature\r
+ //\r
+ TableName [ 0 ] = *(UINT32 *)*pEntry;\r
+ pWebPage = SignatureLookup ( &TableName [ 0 ], &pTableName );\r
+\r
+ //\r
+ // Display the table address\r
+ //\r
+ Status = RowPointer ( SocketFD,\r
+ pPort,\r
+ pTableName,\r
+ (VOID *)*pEntry,\r
+ pWebPage );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ pEntry++;\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Build the table trailer\r
+ //\r
+ Status = TableTrailer ( SocketFD,\r
+ pPort,\r
+ pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
-/*++
- This file contains an 'Intel UEFI Application' and is
- licensed for Intel CPUs and chipsets under the terms of your
- license agreement with Intel or your vendor. This file may
- be modified by the user, subject to additional terms of the
- license agreement
---*/
-/*++
-
-Copyright (c) 2011 Intel Corporation. All rights reserved
-This software and associated documentation (if any) is furnished
-under a license and may only be used or copied in accordance
-with the terms of the license. Except as permitted by such
-license, no part of this software or documentation may be
-reproduced, stored in a retrieval system, or transmitted in any
-form or by any means without the express written consent of
-Intel Corporation.
-
---*/
-
-/** @file
- HTTP processing for the web server.
-
-**/
-
-#include <WebServer.h>
-
-/**
- Get a UTF-8 character from the buffer
-
- @param [in] pData The address of the buffer containing the character
- @param [out] ppData The address to receive the next character address
-
- @returns The character value
-
-**/
-INTN
-HttpCharGet (
- IN UINT8 * pData,
- IN UINT8 ** ppData
- )
-{
- INTN Data;
- INTN Character;
- INTN Control;
- INTN Mask;
-
- //
- // Verify that there is some data left
- //
- if ( NULL == pData ) {
- //
- // No data to return
- //
- pData = NULL;
- Character = 0;
- }
- else {
- //
- // Get the first portion of the character
- //
- Character = *pData++;
- Control = Character;
- Mask = 0xc0;
-
- //
- // Append the rest of the character
- //
- if ( 0 != ( Control & 0x80 )) {
- while ( 0 != ( Control & 0x40 )) {
- Character &= Mask;
- Mask <<= 5;
- Control <<= 1;
- Character <<= 6;
- Data = *pData++ & 0x3f;
- if ( 0x80 != ( Data & 0xc0 )) {
- //
- // Invalid character
- //
- pData = NULL;
- Character = 0;
- break;
- }
- Character |= Data & 0x3f;
- }
- }
- }
-
- //
- // Return the next character location and the character
- //
- *ppData = pData;
- return Character;
-}
-
-
-/**
- Transmit a portion of the HTTP response
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpFlush (
- IN int SocketFD,
- IN WSDT_PORT * pPort
- )
-{
- INTN LengthInBytes;
- UINT8 * pBuffer;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
- pBuffer = &pPort->TxBuffer[0];
- do {
- //
- // Attempt to send the data
- //
- LengthInBytes = send ( SocketFD,
- pBuffer,
- pPort->TxBytes,
- 0 );
- if ( -1 != LengthInBytes ) {
- //
- // Account for the data sent
- //
- pBuffer += LengthInBytes;
- pPort->TxBytes -= LengthInBytes;
- }
- else {
- //
- // Transmit error
- //
- Status = EFI_DEVICE_ERROR;
- break;
- }
- } while ( 0 < pPort->TxBytes );
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Convert the ANSI character to lower case
-
- @param [in] Character The character to convert to lower case.
-
- @returns The lower case character
-
-**/
-INTN
-HttpLowerCase (
- IN INTN Character
- )
-{
- //
- // Determine if the character is upper case
- //
- if (( 'A' <= Character ) && ( 'Z' >= Character )) {
- Character += 'a' - 'A';
- }
-
- //
- // Return the lower case value of the character
- //
- return Character;
-}
-
-
-/**
- Match a Unicode string against a UTF-8 string
-
- @param [in] pString A zero terminated Unicode string
- @param [in] pData A zero terminated UTF-8 string
- @param [in] bIgnoreCase TRUE if case is to be ignored
-
- @returns The difference between the last two characters tested.
- Returns -1 for error.
-
-**/
-INTN
-HttpMatch (
- IN UINT16 * pString,
- IN UINT8 * pData,
- IN BOOLEAN bIgnoreCase
- )
-{
- INTN Character1;
- INTN Character2;
- INTN Difference;
-
- do {
- //
- // Get the character from the comparison string
- //
- Character1 = *pString++;
-
- //
- // Convert the character to lower case
- //
- if ( bIgnoreCase ) {
- Character1 = HttpLowerCase ( Character1 );
- }
-
- //
- // Get the character from the request
- //
- Character2 = HttpCharGet ( pData, &pData );
- if ( NULL == pData ) {
- //
- // Error getting character
- //
- Difference = -1;
- break;
- }
-
- //
- // Convert the character to lower case
- //
- if ( bIgnoreCase ) {
- Character2 = HttpLowerCase ( Character2 );
- }
-
- //
- // Compare the characters
- //
- Difference = Character1 - Character2;
- if ( 0 != Difference ) {
- return Difference;
- }
- } while ( 0 != Character1 );
-
- //
- // Return the difference
- //
- return Difference;
-}
-
-
-/**
- Buffer the HTTP page header
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pTitle A zero terminated Unicode title string
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpPageHeader (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CONST CHAR16 * pTitle
- )
-{
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Build the page header
- //
- for ( ; ; ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<!DOCTYPE "
- "HTML "
- "PUBLIC "
- "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "
- "\"http://www.w3.org/TR/html4/loose.dtd\">\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, "<html lang=\"en-US\">\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- if ( NULL != pTitle ) {
- Status = HttpSendAnsiString ( SocketFD, pPort, " <head>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, " <title>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, "</title>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, " </head>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, " <body>\r\n" );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Respond with an error indicating that the page was not found
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpPageNotFound (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN BOOLEAN * pbDone
- )
-{
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Send the page not found
- //
- for ( ; ; ) {
- //
- // Send the page header
- //
- Status = HttpPageHeader ( SocketFD, pPort, L"404 Not found" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the page body
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "ERROR <b>404</b><br />"
- "Requested page is not available\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the page trailer
- //
- Status = HttpPageTrailer ( SocketFD, pPort, pbDone );
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Buffer and send the HTTP page trailer
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpPageTrailer (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN BOOLEAN * pbDone
- )
-{
- int RetVal;
- EFI_STATUS Status;
- socklen_t LengthInBytes;
- struct sockaddr_in LocalAddress;
- struct sockaddr_in RemoteAddress;
-
- DBG_ENTER ( );
-
- //
- // Build the page header
- //
- for ( ; ; ) {
- LengthInBytes = sizeof ( LocalAddress );
- RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );
- if ( 0 == RetVal ) {
- RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );
- if ( 0 == RetVal ) {
- //
- // Seperate the body from the trailer
- //
- Status = HttpSendAnsiString ( SocketFD, pPort, " <hr>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the system addresses and the page transfer direction
- //
- Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, " --> " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendIpAddress ( SocketFD, pPort, &RemoteAddress );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- }
-
- //
- // Terminate the page
- //
- Status = HttpSendAnsiString ( SocketFD, pPort, " </body>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendAnsiString ( SocketFD, pPort, " </html>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the page trailer
- //
- Status = HttpFlush ( SocketFD, pPort );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Mark the page as complete
- //
- *pbDone = TRUE;
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Replace a space with a zero
-
- @param [in] pData The request buffer address
- @param [in] pEnd End of buffer address
-
- @returns The next character location
-
-**/
-UINT8 *
-HttpReplaceSpace (
- IN UINT8 * pData,
- IN UINT8 * pEnd
- )
-{
- INTN Character;
- UINT8 * pSpace;
-
- pSpace = pData;
- while ( pEnd > pData ) {
- //
- // Get the character from the request
- //
- Character = HttpCharGet ( pData, &pData );
- if ( ' ' == Character ) {
- break;
- }
- pSpace = pData;
- }
-
- //
- // Replace the space character with zero
- //
- ZeroMem ( pSpace, pData - pSpace );
-
- //
- // Return the next character location
- //
- return pData;
-}
-
-
-/**
- Process an HTTP request
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [out] pbDone Address to receive the request completion status
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpRequest (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- OUT BOOLEAN * pbDone
- )
-{
- UINT8 * pData;
- UINT8 * pEnd;
- CONST DT_PAGE * pPage;
- CONST DT_PAGE * pPageEnd;
- UINT8 * pVerb;
- UINT8 * pVersion;
- UINT8 * pWebPage;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume the request is not finished
- //
- *pbDone = FALSE;
- Status = EFI_SUCCESS;
- for ( ; ; ) {
-
- //
- // Attempt to parse the command
- //
- pData = &pPort->Request[0];
- pEnd = &pData [ pPort->RequestLength ];
- pVerb = pData;
- pWebPage = HttpReplaceSpace ( pVerb, pEnd );
- if ( pEnd <= pWebPage ) {
- break;
- }
- pVersion = HttpReplaceSpace ( pWebPage, pEnd );
- if ( pEnd <= pVersion ) {
- break;
- }
-
- //
- // Validate the request
- //
- if ( 0 != HttpMatch ( L"GET", pVerb, TRUE )) {
- //
- // Invalid request type
- //
- DEBUG (( DEBUG_REQUEST,
- "HTTP: Invalid verb\r\n" ));
- Status = EFI_NOT_FOUND;
- break;
- }
-
- //
- // Walk the page table
- //
- pPage = &mPageList[0];
- pPageEnd = &pPage [ mPageCount ];
- while ( pPageEnd > pPage ) {
- //
- // Determine if the page was located
- //
- if ( 0 == HttpMatch ( pPage->pPageName, pWebPage, FALSE )) {
- break;
- }
-
- //
- // Set the next page
- //
- pPage += 1;
- }
- if ( pPageEnd <= pPage ) {
- //
- // The page was not found
- //
- DEBUG (( DEBUG_REQUEST,
- "HTTP: Page not found in page table\r\n" ));
- Status = EFI_NOT_FOUND;
- break;
- }
-
- //
- // Respond with the page contents
- //
- Status = pPage->pfnResponse ( SocketFD, pPort, pbDone );
- break;
- }
-
- //
- // Return page not found if necessary
- //
- if ( EFI_NOT_FOUND == Status ) {
- Status = HttpPageNotFound ( SocketFD, pPort, pbDone );
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Buffer data for sending
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] LengthInBytes Length of valid data in the buffer
- @param [in] pBuffer Buffer of data to send
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSend (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN size_t LengthInBytes,
- IN CONST UINT8 * pBuffer
- )
-{
- size_t DataBytes;
- size_t MaxBytes;
- EFI_STATUS Status;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
- do {
- //
- // Determine how much data fits into the buffer
- //
- MaxBytes = sizeof ( pPort->TxBuffer );
- DataBytes = MaxBytes - pPort->TxBytes;
- if ( DataBytes > LengthInBytes )
- {
- DataBytes = LengthInBytes;
- }
-
- //
- // Copy the data into the buffer
- //
- CopyMem ( &pPort->TxBuffer [ pPort->TxBytes ],
- pBuffer,
- DataBytes );
-
- //
- // Account for the data copied
- //
- pPort->TxBytes += DataBytes;
- LengthInBytes -= DataBytes;
-
- //
- // Transmit the buffer if it is full
- //
- if ( MaxBytes <= pPort->TxBytes ) {
- Status = HttpFlush ( SocketFD, pPort );
- }
- } while (( EFI_SUCCESS == Status ) && ( 0 < LengthInBytes ));
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Send an ANSI string
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pString A zero terminated Unicode string
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSendAnsiString (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CONST char * pString
- )
-{
- CONST char * pData;
- EFI_STATUS Status;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Walk the characters in he string
- //
- pData = pString;
- while ( 0 != *pData ) {
- pData += 1;
- }
-
- //
- // Send the string
- //
- Status = HttpSend ( SocketFD,
- pPort,
- pData - pString,
- (CONST UINT8 *)pString );
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Buffer a single byte
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] Data The data byte to send
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSendByte (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN UINT8 Data
- )
-{
- EFI_STATUS Status;
-
- //
- // Send the data byte
- //
- Status = HttpSend ( SocketFD,
- pPort,
- 1,
- &Data );
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Display a character
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] Character Character to display
- @param [in] pReplacement Replacement character string
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSendCharacter (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CHAR8 Character,
- IN CHAR8 * pReplacement
- )
-{
- EFI_STATUS Status;
-
- //
- // Determine if this is a printable character
- //
- if (( 0x20 <= Character ) && ( 0x7f > Character )) {
- if ( '<' == Character ) {
- //
- // Replace with HTML equivalent
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<" );
- }
- else if ( '>' == Character ) {
- //
- // Replace with HTML equivalent
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- ">" );
- }
- else if ( '&' == Character ) {
- //
- // Replace with HTML equivalent
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "&" );
- }
- else if ( '\"' == Character ) {
- //
- // Replace with HTML equivalent
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- """ );
- }
- else {
- //
- // Display the character
- //
- Status = HttpSendByte ( SocketFD,
- pPort,
- Character );
- }
- }
- else {
- //
- // Not a displayable character
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- pReplacement );
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Send a buffer dump
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] ByteCount The number of bytes to display
- @param [in] pData Address of the byte array
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSendDump (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN UINTN ByteCount,
- IN CONST UINT8 * pData
- )
-{
- INTN BytesToDisplay;
- UINT8 Character;
- INTN Index;
- INTN InitialSpaces;
- CONST UINT8 * pDataEnd;
- CONST UINT8 * pEnd;
- CONST UINT8 * pTemp;
- EFI_STATUS Status;
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Start the field value
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<code>" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Walk the bytes to be displayed
- //
- pEnd = &pData [ ByteCount ];
- while ( pEnd > pData ) {
- //
- // Display the address
- //
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- sizeof ( pData ) * 8,
- (UINT64)pData );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Separate the address and data
- //
- Status = HttpSendByte ( SocketFD, pPort, ':' );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Position the starting data correctly
- //
- InitialSpaces = (UINTN)pData;
- InitialSpaces &= BYTES_ON_A_LINE - 1;
- for ( Index = SPACES_ADDRESS_TO_DATA
- + (( 2 + SPACES_BETWEEN_BYTES )
- * InitialSpaces );
- 0 < Index; Index-- ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- " " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the data
- //
- BytesToDisplay = pEnd - pData;
- if (( BYTES_ON_A_LINE - InitialSpaces ) < BytesToDisplay ) {
- BytesToDisplay = BYTES_ON_A_LINE - InitialSpaces;
- }
- pDataEnd = &pData [ BytesToDisplay ];
- pTemp = pData;
- while ( pDataEnd > pTemp ) {
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 8,
- *pTemp++ );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Separate the data bytes
- //
- for ( Index = SPACES_BETWEEN_BYTES; 0 < Index; Index-- ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- " " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Separate the data from the ASCII display
- //
- for ( Index = (( 2 + SPACES_BETWEEN_BYTES )
- * ( BYTES_ON_A_LINE - BytesToDisplay - InitialSpaces ))
- - SPACES_BETWEEN_BYTES
- + SPACES_DATA_TO_ASCII
- + InitialSpaces;
- 0 < Index; Index-- ) {
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- " " );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the ASCII data
- //
- while ( pDataEnd > pData ) {
- Character = *pData++;
- Status = HttpSendCharacter ( SocketFD,
- pPort,
- Character,
- "." );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Terminate the line
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "<br/>\r\n" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
-
- //
- // Terminate the field value and row
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "</code>\r\n" );
- break;
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Display a row containing a GUID value
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pGuid Address of the GUID to display
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSendGuid (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CONST EFI_GUID * pGuid
- )
-{
- UINT32 Index;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Display the GUID in a form found in the code
- //
- // E.g. 0xca16005f, 0x11ec, 0x4bdc, { 0x99, 0x97, 0x27, 0x2c, 0xa9, 0xba, 0x15, 0xe5 }
- //
-
- //
- // Display the first 32 bits
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- "0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 32,
- pGuid->Data1 );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the second 16 bits
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- ", 0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 16,
- pGuid->Data2 );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Display the thrid 16 bits
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- ", 0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 16,
- pGuid->Data3 );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Place the last 64 bits in braces
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- ", { 0x" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- for ( Index = 0; 7 >= Index; Index++ ) {
- //
- // Display the next 8 bits
- //
- Status = HttpSendHexBits ( SocketFD,
- pPort,
- 8,
- pGuid->Data4 [ Index ]);
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Separate the bytes
- //
- Status = HttpSendAnsiString ( SocketFD,
- pPort,
- ( 7 != Index ) ? ", 0x" : " }" );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Output a hex value to the HTML page
-
- @param [in] SocketFD Socket file descriptor
- @param [in] pPort The WSDT_PORT structure address
- @param [in] Bits Number of bits to display
- @param [in] Value Value to display
-
- @retval EFI_SUCCESS Successfully displayed the address
-**/
-EFI_STATUS
-HttpSendHexBits (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN INT32 Bits,
- IN UINT64 Value
- )
-{
- UINT32 Digit;
- INT32 Shift;
- EFI_STATUS Status;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Walk the list of divisors
- //
- Shift = (( Bits + 3 ) & ( ~3 )) - 4;
- while ( 0 <= Shift ) {
- //
- // Determine the next digit
- //
- Digit = (UINT32)(( Value >> Shift ) & 0xf );
- if ( 10 <= Digit ) {
- Digit += 'A' - '0' - 10;
- }
-
- //
- // Display the digit
- //
- Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Set the next shift
- //
- Shift -= 4;
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Output a hex value to the HTML page
-
- @param [in] SocketFD Socket file descriptor
- @param [in] pPort The WSDT_PORT structure address
- @param [in] Value Value to display
-
- @retval EFI_SUCCESS Successfully displayed the address
-**/
-EFI_STATUS
-HttpSendHexValue (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN UINT64 Value
- )
-{
- BOOLEAN bDisplayZeros;
- UINT32 Digit;
- INT32 Shift;
- EFI_STATUS Status;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Walk the list of divisors
- //
- bDisplayZeros = FALSE;
- Shift = 60;
- do {
- //
- // Determine the next digit
- //
- Digit = (UINT32)(( Value >> Shift ) & 0xf );
- if ( 10 <= Digit ) {
- Digit += 'A' - '0' - 10;
- }
-
- //
- // Suppress leading zeros
- //
- if (( 0 != Digit ) || bDisplayZeros || ( 0 == Shift )) {
- bDisplayZeros = TRUE;
-
- //
- // Display the digit
- //
- Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
-
- //
- // Set the next shift
- //
- Shift -= 4;
- } while ( 0 <= Shift );
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Output an IP address to the HTML page
-
- @param [in] SocketFD Socket file descriptor
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pAddress Address of the socket address
-
- @retval EFI_SUCCESS Successfully displayed the address
-**/
-EFI_STATUS
-HttpSendIpAddress (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN struct sockaddr_in * pAddress
- )
-{
- EFI_STATUS Status;
-
- //
- // Output the IPv4 address
- //
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)pAddress->sin_addr.s_addr );
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendByte ( SocketFD, pPort, '.' );
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 8 ));
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendByte ( SocketFD, pPort, '.' );
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 16 ));
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendByte ( SocketFD, pPort, '.' );
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 24 ));
- if ( !EFI_ERROR ( Status )) {
- //
- // Output the port number
- //
- Status = HttpSendByte ( SocketFD, pPort, ':' );
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendValue ( SocketFD, pPort, htons ( pAddress->sin_port ));
- }
- }
- }
- }
- }
- }
- }
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Send a Unicode string
-
- @param [in] SocketFD The socket's file descriptor to add to the list.
- @param [in] pPort The WSDT_PORT structure address
- @param [in] pString A zero terminated Unicode string
-
- @retval EFI_SUCCESS The request was successfully processed
-
-**/
-EFI_STATUS
-HttpSendUnicodeString (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN CONST UINT16 * pString
- )
-{
- UINT8 Data;
- UINT16 Character;
- EFI_STATUS Status;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Walk the characters in he string
- //
- while ( 0 != ( Character = *pString++ )) {
- //
- // Convert the character to UTF-8
- //
- if ( 0 != ( Character & 0xf800 )) {
- //
- // Send the upper 4 bits
- //
- Data = (UINT8)(( Character >> 12 ) & 0xf );
- Data |= 0xe0;
- Status = HttpSendByte ( SocketFD,
- pPort,
- Data );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the next 6 bits
- //
- Data = (UINT8)(( Character >> 6 ) & 0x3f );
- Data |= 0x80;
- Status = HttpSendByte ( SocketFD,
- pPort,
- Data );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the last 6 bits
- //
- Data = (UINT8)( Character & 0x3f );
- Data |= 0x80;
- }
- else if ( 0 != ( Character & 0x0780 )) {
- //
- // Send the upper 5 bits
- //
- Data = (UINT8)(( Character >> 6 ) & 0x1f );
- Data |= 0xc0;
- Status = HttpSendByte ( SocketFD,
- pPort,
- Data );
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Send the last 6 bits
- //
- Data = (UINT8)( Character & 0x3f );
- Data |= 0x80;
- }
- else {
- Data = (UINT8)( Character & 0x7f );
- }
-
- //
- // Send the last data byte
- //
- Status = HttpSendByte ( SocketFD,
- pPort,
- Data );
- if ( EFI_ERROR ( Status )) {
- break;
- }
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
-
-
-/**
- Output a value to the HTML page
-
- @param [in] SocketFD Socket file descriptor
- @param [in] pPort The WSDT_PORT structure address
- @param [in] Value Value to display
-
- @retval EFI_SUCCESS Successfully displayed the address
-**/
-EFI_STATUS
-HttpSendValue (
- IN int SocketFD,
- IN WSDT_PORT * pPort,
- IN UINT64 Value
- )
-{
- BOOLEAN bDisplayZeros;
- UINT64 Digit;
- CONST UINT64 * pEnd;
- CONST UINT64 * pDivisor;
- CONST UINT64 pDivisors [ ] = {
- 10000000000000000000L,
- 1000000000000000000L,
- 100000000000000000L,
- 10000000000000000L,
- 1000000000000000L,
- 100000000000000L,
- 10000000000000L,
- 1000000000000L,
- 100000000000L,
- 10000000000L,
- 1000000000L,
- 100000000L,
- 10000000L,
- 1000000L,
- 100000L,
- 10000L,
- 1000L,
- 100L,
- 10L
- };
- EFI_STATUS Status;
- UINT64 Temp;
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Walk the list of divisors
- //
- bDisplayZeros = FALSE;
- pDivisor = &pDivisors[0];
- pEnd = &pDivisor [ sizeof ( pDivisors ) / sizeof ( pDivisors [0])];
- while ( pEnd > pDivisor ) {
- //
- // Determine the next digit
- //
- Digit = Value / *pDivisor;
-
- //
- // Suppress leading zeros
- //
- if (( 0 != Digit ) || bDisplayZeros ) {
- bDisplayZeros = TRUE;
-
- //
- // Display the digit
- //
- Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));
- if ( EFI_ERROR ( Status )) {
- break;
- }
-
- //
- // Determine the remainder
- //
- Temp = *pDivisor * Digit;
- Value -= Temp;
- }
-
- //
- // Set the next divisor
- //
- pDivisor += 1;
- }
-
- //
- // Display the final digit
- //
- if ( !EFI_ERROR ( Status )) {
- Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Value ));
- }
-
- //
- // Return the operation status
- //
- return Status;
-}
+/*++\r
+ This file contains an 'Intel UEFI Application' and is\r
+ licensed for Intel CPUs and chipsets under the terms of your\r
+ license agreement with Intel or your vendor. This file may\r
+ be modified by the user, subject to additional terms of the\r
+ license agreement\r
+--*/\r
+/*++\r
+\r
+Copyright (c) 2011 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+--*/\r
+\r
+/** @file\r
+ HTTP processing for the web server.\r
+\r
+**/\r
+\r
+#include <WebServer.h>\r
+\r
+/**\r
+ Get a UTF-8 character from the buffer\r
+\r
+ @param [in] pData The address of the buffer containing the character\r
+ @param [out] ppData The address to receive the next character address\r
+\r
+ @return The character value\r
+\r
+**/\r
+INTN\r
+HttpCharGet (\r
+ IN UINT8 * pData,\r
+ IN UINT8 ** ppData\r
+ )\r
+{\r
+ INTN Data;\r
+ INTN Character;\r
+ INTN Control;\r
+ INTN Mask;\r
+\r
+ //\r
+ // Verify that there is some data left\r
+ //\r
+ if ( NULL == pData ) {\r
+ //\r
+ // No data to return\r
+ //\r
+ pData = NULL;\r
+ Character = 0;\r
+ }\r
+ else {\r
+ //\r
+ // Get the first portion of the character\r
+ //\r
+ Character = *pData++;\r
+ Control = Character;\r
+ Mask = 0xc0;\r
+\r
+ //\r
+ // Append the rest of the character\r
+ //\r
+ if ( 0 != ( Control & 0x80 )) {\r
+ while ( 0 != ( Control & 0x40 )) {\r
+ Character &= Mask;\r
+ Mask <<= 5;\r
+ Control <<= 1;\r
+ Character <<= 6;\r
+ Data = *pData++ & 0x3f;\r
+ if ( 0x80 != ( Data & 0xc0 )) {\r
+ //\r
+ // Invalid character\r
+ //\r
+ pData = NULL;\r
+ Character = 0;\r
+ break;\r
+ }\r
+ Character |= Data & 0x3f;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the next character location and the character\r
+ //\r
+ *ppData = pData;\r
+ return Character;\r
+}\r
+\r
+\r
+/**\r
+ Transmit a portion of the HTTP response\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpFlush (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort\r
+ )\r
+{\r
+ INTN LengthInBytes;\r
+ UINT8 * pBuffer;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ pBuffer = &pPort->TxBuffer[0];\r
+ do {\r
+ //\r
+ // Attempt to send the data\r
+ //\r
+ LengthInBytes = send ( SocketFD,\r
+ pBuffer,\r
+ pPort->TxBytes,\r
+ 0 );\r
+ if ( -1 != LengthInBytes ) {\r
+ //\r
+ // Account for the data sent\r
+ //\r
+ pBuffer += LengthInBytes;\r
+ pPort->TxBytes -= LengthInBytes;\r
+ }\r
+ else {\r
+ //\r
+ // Transmit error\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+ } while ( 0 < pPort->TxBytes );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Convert the ANSI character to lower case\r
+\r
+ @param [in] Character The character to convert to lower case.\r
+\r
+ @return The lower case character\r
+\r
+**/\r
+INTN\r
+HttpLowerCase (\r
+ IN INTN Character\r
+ )\r
+{\r
+ //\r
+ // Determine if the character is upper case\r
+ //\r
+ if (( 'A' <= Character ) && ( 'Z' >= Character )) {\r
+ Character += 'a' - 'A';\r
+ }\r
+\r
+ //\r
+ // Return the lower case value of the character\r
+ //\r
+ return Character;\r
+}\r
+\r
+\r
+/**\r
+ Match a Unicode string against a UTF-8 string\r
+\r
+ @param [in] pString A zero terminated Unicode string\r
+ @param [in] pData A zero terminated UTF-8 string\r
+ @param [in] bIgnoreCase TRUE if case is to be ignored\r
+\r
+ @return The difference between the last two characters tested.\r
+ Returns -1 for error.\r
+\r
+**/\r
+INTN\r
+HttpMatch (\r
+ IN UINT16 * pString,\r
+ IN UINT8 * pData,\r
+ IN BOOLEAN bIgnoreCase\r
+ )\r
+{\r
+ INTN Character1;\r
+ INTN Character2;\r
+ INTN Difference;\r
+\r
+ do {\r
+ //\r
+ // Get the character from the comparison string\r
+ //\r
+ Character1 = *pString++;\r
+\r
+ //\r
+ // Convert the character to lower case\r
+ //\r
+ if ( bIgnoreCase ) {\r
+ Character1 = HttpLowerCase ( Character1 );\r
+ }\r
+\r
+ //\r
+ // Get the character from the request\r
+ //\r
+ Character2 = HttpCharGet ( pData, &pData );\r
+ if ( NULL == pData ) {\r
+ //\r
+ // Error getting character\r
+ //\r
+ Difference = -1;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Convert the character to lower case\r
+ //\r
+ if ( bIgnoreCase ) {\r
+ Character2 = HttpLowerCase ( Character2 );\r
+ }\r
+\r
+ //\r
+ // Compare the characters\r
+ //\r
+ Difference = Character1 - Character2;\r
+ if ( 0 != Difference ) {\r
+ return Difference;\r
+ }\r
+ } while ( 0 != Character1 );\r
+\r
+ //\r
+ // Return the difference\r
+ //\r
+ return Difference;\r
+}\r
+\r
+\r
+/**\r
+ Buffer the HTTP page header\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pTitle A zero terminated Unicode title string\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpPageHeader (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CONST CHAR16 * pTitle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Build the page header\r
+ //\r
+ for ( ; ; ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<!DOCTYPE "\r
+ "HTML "\r
+ "PUBLIC "\r
+ "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "\r
+ "\"http://www.w3.org/TR/html4/loose.dtd\">\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "<html lang=\"en-US\">\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ if ( NULL != pTitle ) {\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " <head>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " <title>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendUnicodeString ( SocketFD, pPort, pTitle );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "</title>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " </head>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " <body>\r\n" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Respond with an error indicating that the page was not found\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpPageNotFound (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN BOOLEAN * pbDone\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Send the page not found\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Send the page header\r
+ //\r
+ Status = HttpPageHeader ( SocketFD, pPort, L"404 Not found" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page body\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "ERROR <b>404</b><br />"\r
+ "Requested page is not available\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page trailer\r
+ //\r
+ Status = HttpPageTrailer ( SocketFD, pPort, pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Buffer and send the HTTP page trailer\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpPageTrailer (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN BOOLEAN * pbDone\r
+ )\r
+{\r
+ int RetVal;\r
+ EFI_STATUS Status;\r
+ socklen_t LengthInBytes;\r
+ struct sockaddr_in LocalAddress;\r
+ struct sockaddr_in RemoteAddress;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Build the page header\r
+ //\r
+ for ( ; ; ) {\r
+ LengthInBytes = sizeof ( LocalAddress );\r
+ RetVal = getsockname ( SocketFD, (struct sockaddr *)&LocalAddress, &LengthInBytes );\r
+ if ( 0 == RetVal ) {\r
+ RetVal = getpeername ( SocketFD, (struct sockaddr *)&RemoteAddress, &LengthInBytes );\r
+ if ( 0 == RetVal ) {\r
+ //\r
+ // Seperate the body from the trailer\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " <hr>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the system addresses and the page transfer direction\r
+ //\r
+ Status = HttpSendIpAddress ( SocketFD, pPort, &LocalAddress );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " --> " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendIpAddress ( SocketFD, pPort, &RemoteAddress );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, "\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Terminate the page\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " </body>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendAnsiString ( SocketFD, pPort, " </html>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the page trailer\r
+ //\r
+ Status = HttpFlush ( SocketFD, pPort );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Mark the page as complete\r
+ //\r
+ *pbDone = TRUE;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Replace a space with a zero\r
+\r
+ @param [in] pData The request buffer address\r
+ @param [in] pEnd End of buffer address\r
+\r
+ @return The next character location\r
+\r
+**/\r
+UINT8 *\r
+HttpReplaceSpace (\r
+ IN UINT8 * pData,\r
+ IN UINT8 * pEnd\r
+ )\r
+{\r
+ INTN Character;\r
+ UINT8 * pSpace;\r
+\r
+ pSpace = pData;\r
+ while ( pEnd > pData ) {\r
+ //\r
+ // Get the character from the request\r
+ //\r
+ Character = HttpCharGet ( pData, &pData );\r
+ if ( ' ' == Character ) {\r
+ break;\r
+ }\r
+ pSpace = pData;\r
+ }\r
+\r
+ //\r
+ // Replace the space character with zero\r
+ //\r
+ ZeroMem ( pSpace, pData - pSpace );\r
+\r
+ //\r
+ // Return the next character location\r
+ //\r
+ return pData;\r
+}\r
+\r
+\r
+/**\r
+ Process an HTTP request\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [out] pbDone Address to receive the request completion status\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpRequest (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ OUT BOOLEAN * pbDone\r
+ )\r
+{\r
+ UINT8 * pData;\r
+ UINT8 * pEnd;\r
+ CONST DT_PAGE * pPage;\r
+ CONST DT_PAGE * pPageEnd;\r
+ UINT8 * pVerb;\r
+ UINT8 * pVersion;\r
+ UINT8 * pWebPage;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Assume the request is not finished\r
+ //\r
+ *pbDone = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ for ( ; ; ) {\r
+\r
+ //\r
+ // Attempt to parse the command\r
+ //\r
+ pData = &pPort->Request[0];\r
+ pEnd = &pData [ pPort->RequestLength ];\r
+ pVerb = pData;\r
+ pWebPage = HttpReplaceSpace ( pVerb, pEnd );\r
+ if ( pEnd <= pWebPage ) {\r
+ break;\r
+ }\r
+ pVersion = HttpReplaceSpace ( pWebPage, pEnd );\r
+ if ( pEnd <= pVersion ) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Validate the request\r
+ //\r
+ if ( 0 != HttpMatch ( L"GET", pVerb, TRUE )) {\r
+ //\r
+ // Invalid request type\r
+ //\r
+ DEBUG (( DEBUG_REQUEST,\r
+ "HTTP: Invalid verb\r\n" ));\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Walk the page table\r
+ //\r
+ pPage = &mPageList[0];\r
+ pPageEnd = &pPage [ mPageCount ];\r
+ while ( pPageEnd > pPage ) {\r
+ //\r
+ // Determine if the page was located\r
+ //\r
+ if ( 0 == HttpMatch ( pPage->pPageName, pWebPage, FALSE )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Set the next page\r
+ //\r
+ pPage += 1;\r
+ }\r
+ if ( pPageEnd <= pPage ) {\r
+ //\r
+ // The page was not found\r
+ //\r
+ DEBUG (( DEBUG_REQUEST,\r
+ "HTTP: Page not found in page table\r\n" ));\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Respond with the page contents\r
+ //\r
+ Status = pPage->pfnResponse ( SocketFD, pPort, pbDone );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return page not found if necessary\r
+ //\r
+ if ( EFI_NOT_FOUND == Status ) {\r
+ Status = HttpPageNotFound ( SocketFD, pPort, pbDone );\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Buffer data for sending\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] LengthInBytes Length of valid data in the buffer\r
+ @param [in] pBuffer Buffer of data to send\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSend (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN size_t LengthInBytes,\r
+ IN CONST UINT8 * pBuffer\r
+ )\r
+{\r
+ size_t DataBytes;\r
+ size_t MaxBytes;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ do {\r
+ //\r
+ // Determine how much data fits into the buffer\r
+ //\r
+ MaxBytes = sizeof ( pPort->TxBuffer );\r
+ DataBytes = MaxBytes - pPort->TxBytes;\r
+ if ( DataBytes > LengthInBytes )\r
+ {\r
+ DataBytes = LengthInBytes;\r
+ }\r
+\r
+ //\r
+ // Copy the data into the buffer\r
+ //\r
+ CopyMem ( &pPort->TxBuffer [ pPort->TxBytes ],\r
+ pBuffer,\r
+ DataBytes );\r
+\r
+ //\r
+ // Account for the data copied\r
+ //\r
+ pPort->TxBytes += DataBytes;\r
+ LengthInBytes -= DataBytes;\r
+\r
+ //\r
+ // Transmit the buffer if it is full\r
+ //\r
+ if ( MaxBytes <= pPort->TxBytes ) {\r
+ Status = HttpFlush ( SocketFD, pPort );\r
+ }\r
+ } while (( EFI_SUCCESS == Status ) && ( 0 < LengthInBytes ));\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send an ANSI string\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pString A zero terminated Unicode string\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendAnsiString (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CONST char * pString\r
+ )\r
+{\r
+ CONST char * pData;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Walk the characters in he string\r
+ //\r
+ pData = pString;\r
+ while ( 0 != *pData ) {\r
+ pData += 1;\r
+ }\r
+\r
+ //\r
+ // Send the string\r
+ //\r
+ Status = HttpSend ( SocketFD,\r
+ pPort,\r
+ pData - pString,\r
+ (CONST UINT8 *)pString );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Buffer a single byte\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] Data The data byte to send\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendByte (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN UINT8 Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Send the data byte\r
+ //\r
+ Status = HttpSend ( SocketFD,\r
+ pPort,\r
+ 1,\r
+ &Data );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Display a character\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] Character Character to display\r
+ @param [in] pReplacement Replacement character string\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendCharacter (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CHAR8 Character,\r
+ IN CHAR8 * pReplacement\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Determine if this is a printable character\r
+ //\r
+ if (( 0x20 <= Character ) && ( 0x7f > Character )) {\r
+ if ( '<' == Character ) {\r
+ //\r
+ // Replace with HTML equivalent\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<" );\r
+ }\r
+ else if ( '>' == Character ) {\r
+ //\r
+ // Replace with HTML equivalent\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ ">" );\r
+ }\r
+ else if ( '&' == Character ) {\r
+ //\r
+ // Replace with HTML equivalent\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "&" );\r
+ }\r
+ else if ( '\"' == Character ) {\r
+ //\r
+ // Replace with HTML equivalent\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ """ );\r
+ }\r
+ else {\r
+ //\r
+ // Display the character\r
+ //\r
+ Status = HttpSendByte ( SocketFD,\r
+ pPort,\r
+ Character );\r
+ }\r
+ }\r
+ else {\r
+ //\r
+ // Not a displayable character\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ pReplacement );\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send a buffer dump\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] ByteCount The number of bytes to display\r
+ @param [in] pData Address of the byte array\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendDump (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN UINTN ByteCount,\r
+ IN CONST UINT8 * pData\r
+ )\r
+{\r
+ INTN BytesToDisplay;\r
+ UINT8 Character;\r
+ INTN Index;\r
+ INTN InitialSpaces;\r
+ CONST UINT8 * pDataEnd;\r
+ CONST UINT8 * pEnd;\r
+ CONST UINT8 * pTemp;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Start the field value\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<code>" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Walk the bytes to be displayed\r
+ //\r
+ pEnd = &pData [ ByteCount ];\r
+ while ( pEnd > pData ) {\r
+ //\r
+ // Display the address\r
+ //\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ sizeof ( pData ) * 8,\r
+ (UINT64)pData );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Separate the address and data\r
+ //\r
+ Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Position the starting data correctly\r
+ //\r
+ InitialSpaces = (UINTN)pData;\r
+ InitialSpaces &= BYTES_ON_A_LINE - 1;\r
+ for ( Index = SPACES_ADDRESS_TO_DATA\r
+ + (( 2 + SPACES_BETWEEN_BYTES )\r
+ * InitialSpaces );\r
+ 0 < Index; Index-- ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ " " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the data\r
+ //\r
+ BytesToDisplay = pEnd - pData;\r
+ if (( BYTES_ON_A_LINE - InitialSpaces ) < BytesToDisplay ) {\r
+ BytesToDisplay = BYTES_ON_A_LINE - InitialSpaces;\r
+ }\r
+ pDataEnd = &pData [ BytesToDisplay ];\r
+ pTemp = pData;\r
+ while ( pDataEnd > pTemp ) {\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 8,\r
+ *pTemp++ );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Separate the data bytes\r
+ //\r
+ for ( Index = SPACES_BETWEEN_BYTES; 0 < Index; Index-- ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ " " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Separate the data from the ASCII display\r
+ //\r
+ for ( Index = (( 2 + SPACES_BETWEEN_BYTES )\r
+ * ( BYTES_ON_A_LINE - BytesToDisplay - InitialSpaces ))\r
+ - SPACES_BETWEEN_BYTES\r
+ + SPACES_DATA_TO_ASCII\r
+ + InitialSpaces;\r
+ 0 < Index; Index-- ) {\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ " " );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the ASCII data\r
+ //\r
+ while ( pDataEnd > pData ) {\r
+ Character = *pData++;\r
+ Status = HttpSendCharacter ( SocketFD,\r
+ pPort,\r
+ Character,\r
+ "." );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Terminate the line\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "<br/>\r\n" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Terminate the field value and row\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "</code>\r\n" );\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Display a row containing a GUID value\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pGuid Address of the GUID to display\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendGuid (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CONST EFI_GUID * pGuid\r
+ )\r
+{\r
+ UINT32 Index;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Use for/break instead of goto\r
+ //\r
+ for ( ; ; ) {\r
+ //\r
+ // Display the GUID in a form found in the code\r
+ //\r
+ // E.g. 0xca16005f, 0x11ec, 0x4bdc, { 0x99, 0x97, 0x27, 0x2c, 0xa9, 0xba, 0x15, 0xe5 }\r
+ //\r
+\r
+ //\r
+ // Display the first 32 bits\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ "0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 32,\r
+ pGuid->Data1 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the second 16 bits\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ ", 0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 16,\r
+ pGuid->Data2 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the thrid 16 bits\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ ", 0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 16,\r
+ pGuid->Data3 );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Place the last 64 bits in braces\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ ", { 0x" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ for ( Index = 0; 7 >= Index; Index++ ) {\r
+ //\r
+ // Display the next 8 bits\r
+ //\r
+ Status = HttpSendHexBits ( SocketFD,\r
+ pPort,\r
+ 8,\r
+ pGuid->Data4 [ Index ]);\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Separate the bytes\r
+ //\r
+ Status = HttpSendAnsiString ( SocketFD,\r
+ pPort,\r
+ ( 7 != Index ) ? ", 0x" : " }" );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Output a hex value to the HTML page\r
+\r
+ @param [in] SocketFD Socket file descriptor\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] Bits Number of bits to display\r
+ @param [in] Value Value to display\r
+\r
+ @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendHexBits (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN INT32 Bits,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ UINT32 Digit;\r
+ INT32 Shift;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Walk the list of divisors\r
+ //\r
+ Shift = (( Bits + 3 ) & ( ~3 )) - 4;\r
+ while ( 0 <= Shift ) {\r
+ //\r
+ // Determine the next digit\r
+ //\r
+ Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
+ if ( 10 <= Digit ) {\r
+ Digit += 'A' - '0' - 10;\r
+ }\r
+\r
+ //\r
+ // Display the digit\r
+ //\r
+ Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Set the next shift\r
+ //\r
+ Shift -= 4;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Output a hex value to the HTML page\r
+\r
+ @param [in] SocketFD Socket file descriptor\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] Value Value to display\r
+\r
+ @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendHexValue (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ BOOLEAN bDisplayZeros;\r
+ UINT32 Digit;\r
+ INT32 Shift;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Walk the list of divisors\r
+ //\r
+ bDisplayZeros = FALSE;\r
+ Shift = 60;\r
+ do {\r
+ //\r
+ // Determine the next digit\r
+ //\r
+ Digit = (UINT32)(( Value >> Shift ) & 0xf );\r
+ if ( 10 <= Digit ) {\r
+ Digit += 'A' - '0' - 10;\r
+ }\r
+\r
+ //\r
+ // Suppress leading zeros\r
+ //\r
+ if (( 0 != Digit ) || bDisplayZeros || ( 0 == Shift )) {\r
+ bDisplayZeros = TRUE;\r
+\r
+ //\r
+ // Display the digit\r
+ //\r
+ Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set the next shift\r
+ //\r
+ Shift -= 4;\r
+ } while ( 0 <= Shift );\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Output an IP address to the HTML page\r
+\r
+ @param [in] SocketFD Socket file descriptor\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pAddress Address of the socket address\r
+\r
+ @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendIpAddress (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN struct sockaddr_in * pAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Output the IPv4 address\r
+ //\r
+ Status = HttpSendValue ( SocketFD, pPort, (UINT8)pAddress->sin_addr.s_addr );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 8 ));\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 16 ));\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendByte ( SocketFD, pPort, '.' );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendValue ( SocketFD, pPort, (UINT8)( pAddress->sin_addr.s_addr >> 24 ));\r
+ if ( !EFI_ERROR ( Status )) {\r
+ //\r
+ // Output the port number\r
+ //\r
+ Status = HttpSendByte ( SocketFD, pPort, ':' );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendValue ( SocketFD, pPort, htons ( pAddress->sin_port ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Send a Unicode string\r
+\r
+ @param [in] SocketFD The socket's file descriptor to add to the list.\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] pString A zero terminated Unicode string\r
+\r
+ @retval EFI_SUCCESS The request was successfully processed\r
+\r
+**/\r
+EFI_STATUS\r
+HttpSendUnicodeString (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN CONST UINT16 * pString\r
+ )\r
+{\r
+ UINT8 Data;\r
+ UINT16 Character;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Walk the characters in he string\r
+ //\r
+ while ( 0 != ( Character = *pString++ )) {\r
+ //\r
+ // Convert the character to UTF-8\r
+ //\r
+ if ( 0 != ( Character & 0xf800 )) {\r
+ //\r
+ // Send the upper 4 bits\r
+ //\r
+ Data = (UINT8)(( Character >> 12 ) & 0xf );\r
+ Data |= 0xe0;\r
+ Status = HttpSendByte ( SocketFD,\r
+ pPort,\r
+ Data );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the next 6 bits\r
+ //\r
+ Data = (UINT8)(( Character >> 6 ) & 0x3f );\r
+ Data |= 0x80;\r
+ Status = HttpSendByte ( SocketFD,\r
+ pPort,\r
+ Data );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the last 6 bits\r
+ //\r
+ Data = (UINT8)( Character & 0x3f );\r
+ Data |= 0x80;\r
+ }\r
+ else if ( 0 != ( Character & 0x0780 )) {\r
+ //\r
+ // Send the upper 5 bits\r
+ //\r
+ Data = (UINT8)(( Character >> 6 ) & 0x1f );\r
+ Data |= 0xc0;\r
+ Status = HttpSendByte ( SocketFD,\r
+ pPort,\r
+ Data );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Send the last 6 bits\r
+ //\r
+ Data = (UINT8)( Character & 0x3f );\r
+ Data |= 0x80;\r
+ }\r
+ else {\r
+ Data = (UINT8)( Character & 0x7f );\r
+ }\r
+\r
+ //\r
+ // Send the last data byte\r
+ //\r
+ Status = HttpSendByte ( SocketFD,\r
+ pPort,\r
+ Data );\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Output a value to the HTML page\r
+\r
+ @param [in] SocketFD Socket file descriptor\r
+ @param [in] pPort The WSDT_PORT structure address\r
+ @param [in] Value Value to display\r
+\r
+ @retval EFI_SUCCESS Successfully displayed the address\r
+**/\r
+EFI_STATUS\r
+HttpSendValue (\r
+ IN int SocketFD,\r
+ IN WSDT_PORT * pPort,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ BOOLEAN bDisplayZeros;\r
+ UINT64 Digit;\r
+ CONST UINT64 * pEnd;\r
+ CONST UINT64 * pDivisor;\r
+ CONST UINT64 pDivisors [ ] = {\r
+ 10000000000000000000L,\r
+ 1000000000000000000L,\r
+ 100000000000000000L,\r
+ 10000000000000000L,\r
+ 1000000000000000L,\r
+ 100000000000000L,\r
+ 10000000000000L,\r
+ 1000000000000L,\r
+ 100000000000L,\r
+ 10000000000L,\r
+ 1000000000L,\r
+ 100000000L,\r
+ 10000000L,\r
+ 1000000L,\r
+ 100000L,\r
+ 10000L,\r
+ 1000L,\r
+ 100L,\r
+ 10L\r
+ };\r
+ EFI_STATUS Status;\r
+ UINT64 Temp;\r
+\r
+ //\r
+ // Assume success\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Walk the list of divisors\r
+ //\r
+ bDisplayZeros = FALSE;\r
+ pDivisor = &pDivisors[0];\r
+ pEnd = &pDivisor [ sizeof ( pDivisors ) / sizeof ( pDivisors [0])];\r
+ while ( pEnd > pDivisor ) {\r
+ //\r
+ // Determine the next digit\r
+ //\r
+ Digit = Value / *pDivisor;\r
+\r
+ //\r
+ // Suppress leading zeros\r
+ //\r
+ if (( 0 != Digit ) || bDisplayZeros ) {\r
+ bDisplayZeros = TRUE;\r
+\r
+ //\r
+ // Display the digit\r
+ //\r
+ Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Digit ));\r
+ if ( EFI_ERROR ( Status )) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Determine the remainder\r
+ //\r
+ Temp = *pDivisor * Digit;\r
+ Value -= Temp;\r
+ }\r
+\r
+ //\r
+ // Set the next divisor\r
+ //\r
+ pDivisor += 1;\r
+ }\r
+\r
+ //\r
+ // Display the final digit\r
+ //\r
+ if ( !EFI_ERROR ( Status )) {\r
+ Status = HttpSendByte ( SocketFD, pPort, (UINT8)( '0' + Value ));\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ return Status;\r
+}\r
address for the file\r
@param [in] pErrno Address of the errno variable\r
\r
- @returns A pointer to the socket protocol structure or NULL if\r
+ @return A pointer to the socket protocol structure or NULL if\r
an invalid file descriptor was passed in.\r
\r
**/\r
\r
@param [in] pDescriptor Descriptor address for the file\r
\r
- @returns This routine returns 0 upon success and -1 upon failure.\r
+ @return This routine returns 0 upon success and -1 upon failure.\r
In the case of failure, errno contains more information.\r
\r
**/\r
\r
@param [in] Events Mask of events to detect\r
\r
- @returns Detected events for the socket\r
+ @return Detected events for the socket\r
\r
**/\r
short\r
\r
@param [in] pErrno Address of the errno variable\r
\r
- @returns The file descriptor for the socket or -1 if an error occurs.\r
+ @return The file descriptor for the socket or -1 if an error occurs.\r
\r
**/\r
int\r
@param [in] LengthInBytes Number of bytes to read\r
@param [in] pBuffer Address of the buffer to receive the data\r
\r
- @returns The number of bytes read or -1 if an error occurs.\r
+ @return The number of bytes read or -1 if an error occurs.\r
\r
**/\r
ssize_t\r
@param [in] LengthInBytes Number of bytes to write\r
@param [in] pBuffer Address of the data\r
\r
- @returns The number of bytes written or -1 if an error occurs.\r
+ @return The number of bytes written or -1 if an error occurs.\r
\r
**/\r
ssize_t\r
\r
@param [in] pErrno Address of the errno variable\r
\r
- @returns A pointer to the socket protocol structure or NULL if\r
+ @return A pointer to the socket protocol structure or NULL if\r
an invalid file descriptor was passed in.\r
\r
**/\r
of the remote network address buffer. Upon return,\r
contains the length of the remote network address.\r
\r
- @returns ::accept returns zero if successful and -1 when an error occurs.\r
+ @return ::accept returns zero if successful and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
of the remote network address buffer. Upon return,\r
contains the length of the remote network address.\r
\r
- @returns ::accept returns zero if successful and -1 when an error occurs.\r
+ @return ::accept returns zero if successful and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
of the remote network address buffer. Upon return,\r
contains the length of the remote network address.\r
\r
- @returns This routine returns zero if successful and -1 when an error occurs.\r
+ @return This routine returns zero if successful and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>\r
documentation for the bind routine is available online for reference.\r
\r
- @param [in] s Socket file descriptor returned from ::socket.\r
+ @param[in] s Socket file descriptor returned from ::socket.\r
\r
- @param [in] name Address of a sockaddr structure that contains the\r
+ @param[in] name Address of a sockaddr structure that contains the\r
connection point on the local machine. An IPv4 address\r
of INADDR_ANY specifies that the connection is made to\r
all of the network stacks on the platform. Specifying a\r
number from the dynamic range. Specifying a specific\r
port number causes the network layer to use that port.\r
\r
- @param [in] namelen Specifies the length in bytes of the sockaddr structure.\r
+ @param[in] namelen Specifies the length in bytes of the sockaddr structure.\r
\r
- @returns The bind routine returns zero (0) if successful and -1 upon failure.\r
+ @return The bind routine returns zero (0) if successful and -1 upon failure.\r
\r
**/\r
int\r
/**\r
Worker routine to close the socket.\r
\r
- @param [in] pSocketProtocol Socket protocol structure address\r
+ @param[in] pSocketProtocol Socket protocol structure address\r
\r
- @param [in] pErrno Address of the errno variable\r
+ @param[in] pErrno Address of the errno variable\r
\r
@retval EFI_SUCCESS Successfully closed the socket\r
\r
/**\r
Close the socket\r
\r
- @param [in] pDescriptor Descriptor address for the file\r
+ @param[in] pDescriptor Descriptor address for the file\r
\r
- @returns This routine returns 0 upon success and -1 upon failure.\r
+ @return This routine returns 0 upon success and -1 upon failure.\r
In the case of failure, errno contains more information.\r
\r
**/\r
@param [in] s Socket file descriptor returned from ::socket.\r
\r
@param [in] address Network address of the remote system\r
- \r
+\r
@param [in] address_len Length of the remote network address\r
\r
- @returns ::connect returns zero if successful and -1 when an error occurs.\r
+ @return ::connect returns zero if successful and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
struct __filedes * pDescriptor;\r
EFI_SOCKET_PROTOCOL * pSocketProtocol;\r
EFI_STATUS Status;\r
- \r
+\r
//\r
// Locate the context for this socket\r
//\r
&errno );\r
} while ( bBlocking && ( EFI_NOT_READY == Status ));\r
}\r
- \r
+\r
//\r
// Return the new socket file descriptor\r
//\r
\r
@param [in] address_len Length of the remote network address structure\r
\r
- @returns ::getpeername returns zero (0) if successful or -1 when an error occurs.\r
+ @return ::getpeername returns zero (0) if successful or -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
\r
@param [in] address_len Length of the local network address structure\r
\r
- @returns ::getsockname returns zero (0) if successful or -1 when an error occurs.\r
+ @return ::getsockname returns zero (0) if successful or -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
waiting for the application to call accept. Connection attempts\r
received while the queue is full are refused.\r
\r
- @returns The listen routine returns zero (0) if successful and -1 upon failure.\r
+ @return The listen routine returns zero (0) if successful and -1 upon failure.\r
\r
**/\r
int\r
\r
@param [in] Events Mask of events to detect\r
\r
- @returns Detected events for the socket\r
+ @return Detected events for the socket\r
\r
**/\r
short\r
@param [in] LengthInBytes Number of bytes to read\r
@param [in] pBuffer Address of the buffer to receive the data\r
\r
- @returns The number of bytes read or -1 if an error occurs.\r
+ @return The number of bytes read or -1 if an error occurs.\r
\r
**/\r
ssize_t\r
@param [in] s Socket file descriptor returned from ::socket.\r
\r
@param [in] buffer Address of a buffer to receive the data.\r
- \r
+\r
@param [in] length Length of the buffer in bytes.\r
\r
@param [in] flags Message control flags\r
\r
- @returns ::recv returns the number of valid bytes in the buffer,\r
+ @return ::recv returns the number of valid bytes in the buffer,\r
zero if no data was received, and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
)\r
{\r
ssize_t BytesRead;\r
- \r
+\r
//\r
// Receive the data from the remote system\r
//\r
@param [in] s Socket file descriptor returned from ::socket.\r
\r
@param [in] buffer Address of a buffer to receive the data.\r
- \r
+\r
@param [in] length Length of the buffer in bytes.\r
\r
@param [in] flags Message control flags\r
\r
@param [in] address_len Length of the remote network address structure\r
\r
- @returns ::recvfrom returns the number of valid bytes in the buffer,\r
+ @return ::recvfrom returns the number of valid bytes in the buffer,\r
zero if no data was received, and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
@param [in] s Socket file descriptor returned from ::socket.\r
\r
@param [in] buffer Address of a buffer containing the data to send.\r
- \r
+\r
@param [in] length Length of the buffer in bytes.\r
\r
@param [in] flags Message control flags\r
\r
- @returns ::send returns the number of data bytes that were\r
+ @return ::send returns the number of data bytes that were\r
sent and -1 when an error occurs. In the case of\r
an error, errno contains more details.\r
\r
@param [in] s Socket file descriptor returned from ::socket.\r
\r
@param [in] buffer Address of a buffer containing the data to send.\r
- \r
+\r
@param [in] length Length of the buffer in bytes.\r
\r
@param [in] flags Message control flags\r
\r
@param [in] tolen Length of remote system address structure\r
\r
- @returns ::send returns the number of data bytes that were\r
+ @return ::send returns the number of data bytes that were\r
sent and -1 when an error occurs. In the case of\r
an error, errno contains more details.\r
\r
@param [in] s Socket file descriptor returned from ::socket.\r
\r
@param [in] how Which operations to shutdown\r
- \r
- @returns ::shutdown returns the zero (0) if successful or -1 when an\r
+\r
+ @return ::shutdown returns the zero (0) if successful or -1 when an\r
error occurs. In the latter case, errno contains more details.\r
\r
**/\r
address for the file\r
@param [in] pErrno Address of the errno variable\r
\r
- @returns A pointer to the socket protocol structure or NULL if\r
+ @return A pointer to the socket protocol structure or NULL if\r
an invalid file descriptor was passed in.\r
\r
**/\r
Build a file descriptor for a socket.\r
\r
@param [in] pSocketProtocol Socket protocol structure address\r
- \r
+\r
@param [in] pErrno Address of the errno variable\r
\r
- @returns The file descriptor for the socket or -1 if an error occurs.\r
+ @return The file descriptor for the socket or -1 if an error occurs.\r
\r
**/\r
int\r
<li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>\r
</ul>\r
\r
- @returns This routine returns a file descriptor for the socket.\r
+ @return This routine returns a file descriptor for the socket.\r
\r
**/\r
INT32\r
\r
@param [in] pErrno Address of the errno variable\r
\r
- @returns A pointer to the socket protocol structure or NULL if\r
+ @return A pointer to the socket protocol structure or NULL if\r
an invalid file descriptor was passed in.\r
\r
**/\r
@param [in] LengthInBytes Number of bytes to write\r
@param [in] pBuffer Address of the data\r
\r
- @returns The number of bytes written or -1 if an error occurs.\r
+ @return The number of bytes written or -1 if an error occurs.\r
\r
**/\r
ssize_t\r
@param [in] pSocketProtocol Address of the socket protocol structure.\r
\r
@param [in] pSockAddr Network address of the remote system.\r
- \r
+\r
@param [in] SockAddrLength Length in bytes of the network address.\r
- \r
+\r
@param [out] pErrno Address to receive the errno value upon completion.\r
- \r
+\r
@retval EFI_SUCCESS The connection was successfully established.\r
@retval EFI_NOT_READY The connection is in progress, call this routine again.\r
@retval Others The connection attempt failed.\r
Get the local address.\r
\r
@param [in] pSocketProtocol Address of the socket protocol structure.\r
- \r
+\r
@param [out] pAddress Network address to receive the local system address\r
\r
@param [in,out] pAddressLength Length of the local network address structure\r
Get the peer address.\r
\r
@param [in] pSocketProtocol Address of the socket protocol structure.\r
- \r
+\r
@param [out] pAddress Network address to receive the remote system address\r
\r
@param [in,out] pAddressLength Length of the remote network address structure\r
documentation is available online.\r
\r
@param [in] pSocketProtocol Address of the socket protocol structure.\r
- \r
+\r
@param [in] Flags Message control flags\r
- \r
+\r
@param [in] BufferLength Length of the the buffer\r
- \r
+\r
@param [in] pBuffer Address of a buffer to receive the data.\r
- \r
+\r
@param [in] pDataLength Number of received data bytes in the buffer.\r
\r
@param [out] pAddress Network address to receive the remote system address\r
remote network connection.\r
\r
@param [in] pSocketProtocol Address of the socket protocol structure.\r
- \r
+\r
@param [in] Flags Message control flags\r
- \r
+\r
@param [in] BufferLength Length of the the buffer\r
- \r
+\r
@param [in] pBuffer Address of a buffer containing the data to send\r
- \r
+\r
@param [in] pDataLength Address to receive the number of data bytes sent\r
\r
@param [in] pAddress Network address of the remote system address\r
operations.\r
\r
@param [in] pSocketProtocol Address of the socket protocol structure.\r
- \r
+\r
@param [in] How Which operations to stop\r
- \r
+\r
@param [out] pErrno Address to receive the errno value upon completion.\r
\r
@retval EFI_SUCCESS - Socket operations successfully shutdown\r
of the remote network address buffer. Upon return,\r
contains the length of the remote network address.\r
\r
- @returns This routine returns zero if successful and -1 when an error occurs.\r
+ @return This routine returns zero if successful and -1 when an error occurs.\r
In the case of an error, errno contains more details.\r
\r
**/\r
character set whose multibyte character representation is a single byte when in the initial\r
shift state.\r
\r
- @Returns The wctob function returns EOF if c does not correspond to a multibyte\r
+ @return The wctob function returns EOF if c does not correspond to a multibyte\r
character with length one in the initial shift state. Otherwise, it\r
returns the single-byte representation of that character as an\r
unsigned char converted to an int.\r
/** If ps is not a null pointer, the mbsinit function determines whether the\r
pointed-to mbstate_t object describes an initial conversion state.\r
\r
- @Returns The mbsinit function returns nonzero if ps is a null pointer\r
+ @return The mbsinit function returns nonzero if ps is a null pointer\r
or if the pointed-to object describes an initial conversion\r
state; otherwise, it returns zero.\r
**/\r
terminating null wide character, the resulting state described is the\r
initial conversion state.\r
\r
- @Returns If conversion stops because a wide character is reached that\r
+ @return If conversion stops because a wide character is reached that\r
does not correspond to a valid multibyte character, an\r
encoding error occurs: the wcsrtombs function stores the\r
value of the macro EILSEQ in errno and returns (size_t)(-1);\r
\r
@param [in] timeout Length of time in milliseconds to wait for the event\r
\r
- @returns The number of file descriptors with detected events. Zero\r
+ @return The number of file descriptors with detected events. Zero\r
indicates that the call timed out and -1 indicates an error.\r
\r
**/\r
\r
/** Gets the current working directory.\r
\r
- The getcwd() function shall place an absolute pathname of the current \r
- working directory in the array pointed to by buf, and return buf. The \r
- pathname copied to the array shall contain no components that are \r
- symbolic links. The size argument is the size in bytes of the character \r
- array pointed to by the buf argument. \r
- \r
+ The getcwd() function shall place an absolute pathname of the current\r
+ working directory in the array pointed to by buf, and return buf. The\r
+ pathname copied to the array shall contain no components that are\r
+ symbolic links. The size argument is the size in bytes of the character\r
+ array pointed to by the buf argument.\r
+\r
@param[in,out] buf The buffer to fill.\r
@param[in] size The number of bytes in buffer.\r
\r
@retval NULL Size was 0.\r
@return buf The function completed successfully. See errno for info.\r
**/\r
-char \r
-*getcwd (char *buf, size_t size) \r
+char\r
+*getcwd (char *buf, size_t size)\r
{\r
CONST CHAR16 *Cwd;\r
\r
errno = ERANGE;\r
return (NULL);\r
}\r
- \r
+\r
return (UnicodeStrToAsciiStr(Cwd, buf));\r
}\r
\r