4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This file contains an 'Intel UEFI Application' and is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync licensed for Intel CPUs and chipsets under the terms of your
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync license agreement with Intel or your vendor. This file may
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be modified by the user, subject to additional terms of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync license agreement
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2011 Intel Corporation. All rights reserved
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis software and associated documentation (if any) is furnished
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncunder a license and may only be used or copied in accordance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwith the terms of the license. Except as permitted by such
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynclicense, no part of this software or documentation may be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncreproduced, stored in a retrieval system, or transmitted in any
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncform or by any means without the express written consent of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIntel Corporation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is a simple TFTP server application
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTSDT_TFTP_SERVER mTftpServer; ///< TFTP server's control structure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Add a connection context to the list of connection contexts.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Context structure address, NULL if allocation fails
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use for/break instead of goto
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for ( ; ; ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate a new context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->AllocatePool ( EfiRuntimeServicesData,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Failed to allocate the context, Status: %r\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pContext->pEnd = &pContext->pBuffer[sizeof ( pContext->pBuffer )];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Display the new context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "0x%08x: Context for %d.%d.%d.%d:%d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 8 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 16 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pContext->RemoteAddress.sin_addr.s_addr >> 24 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add the context to the context list
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All done
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the connection context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Locate a remote connection context.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pIpAddress The start of the remote IP address in network order
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] Port The remote port number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Context structure address, NULL if not found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Walk the list of connection contexts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Attempt to locate the remote network connection
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (( pTftpServer->RemoteAddress.sin_addr.s_addr == pContext->RemoteAddress.sin_addr.s_addr )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && ( pTftpServer->RemoteAddress.sin_port == pContext->RemoteAddress.sin_port )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The connection was found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "0x%08x: pContext found\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the next context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the connection context structure address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Remove a context from the list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pContext The context structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Attempt to locate the context in the list
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if the context was found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the context from the list
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the next context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if the context was found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the work for the sockets.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Handle input events
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( 0 != ( pTftpServer->TftpPort.revents & POLLRDNORM )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receive the message from the remote system
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoteAddressLength = sizeof ( pTftpServer->RemoteAddress );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->RxBytes = recvfrom ( pTftpServer->TftpPort.fd,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->RemoteAddress.sin_len = (UINT8) RemoteAddressLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Received %d bytes from %d.%d.%d.%d:%d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ) & 0xff,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ) & 0xff,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ) & 0xff,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Lookup connection context using the remote system address and port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to determine if an existing connection to this remote
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // system exists
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the received message
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receive error on the TFTP server port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Close the server socket
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Failed receive on TFTP server port, errno: 0x%08x\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Handle the close event
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( 0 != ( pTftpServer->TftpPort.revents & POLLHUP )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Close the port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Scan the list of sockets and process any pending work
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (( DEBUG_SOCKET_POLL, "Entering SocketPoll\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if any ports are active
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - errno: %d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( 0 < FDCount ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process this port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (( DEBUG_SOCKET_POLL, "Exiting SocketPoll\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Convert a character to lower case
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] Character The character to convert
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The lower case equivalent of the character
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if the character is upper case
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (( 'A' <= Character ) && ( 'Z' >= Character )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Convert the character to lower caes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the converted character
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Case independent string comparison
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pString1 Zero terminated string address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pString2 Zero terminated string address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Returns the first character difference between string 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and string 2.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Walk the length of the strings
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the next characters
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Convert them to lower case
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Done when the characters differ
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( 0 != Difference ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Done at the end of the string
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while ( 0 != Char1 );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the difference
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the next TFTP option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pOption Address of a zero terminated option string
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pEnd End of buffer address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] ppNextOption Address to receive the address of the next
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync zero terminated option string
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Message processed successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Locate the end of the option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (( pEnd > pNextOption ) && ( 0 != *pNextOption )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Error - end of buffer reached
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Option without zero termination received!\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Zero terminated option found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Display the zero terminated ASCII option string
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Option: %a\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the next option address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the operation status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Place an option value into the option acknowledgement
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pOack Option acknowledgement address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] Value Value to translate into ASCII decimal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Option acknowledgement address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine the next value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Supress leading zeros
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( 0 != NextValue ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Output this digit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pOack++ = (UINT8)( Value - ( NextValue * 10 ) + '0' );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the next option acknowledgement location
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the TFTP request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pContext The context structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pOption Address of the first zero terminated option string
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pEnd End of buffer address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Start the OACK packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Let the OACK handle the parsing errors
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Walk the list of options
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the next option, skip junk at end of message
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TftpOptionGet ( pOption, pEnd, &pNextOption );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // blksize - See http://tools.ietf.org/html/rfc2348
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the block size, skip non-numeric block sizes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Propose a smaller block size if necessary
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the new block size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Using block size of %d bytes\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the OACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pOack = TftpOptionSet ( pOack, pContext->BlockSize );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // timeout - See http://tools.ietf.org/html/rfc2349
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if ( 0 == stricmp ((char *)pOption, "timeout" )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the timeout value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Using timeout of %d seconds\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the OACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pOack = TftpOptionSet ( pOack, pContext->Timeout );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if ( 0 == stricmp ((char *)pOption, "tsize" )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TftpOptionGet ( pValue, pEnd, &pNextOption );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the file size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Returning file size of %Ld bytes\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the OACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pOack = TftpOptionSet ( pOack, pContext->LengthInBytes );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unknown option - Ignore it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "WARNING - Skipping unknown option: %a\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the next option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the TFTP request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pOption Address of the first zero terminated option string
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pValue Address to receive the value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Option translated into a value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Walk the characters in the option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ( 0 != *pOption ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Convert the next digit to binary
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Invalid character '0x%02x' in the value\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the conversion status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the TFTP request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pContext Connection context structure address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the opcode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the parameters
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch ( Opcode ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Unknown TFTP opcode: %d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Expecting ACKs not data for pContext 0x%08x\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( pTftpServer->RxBytes > (ssize_t)( pContext->BlockSize + 2 + 2 )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Receive data length of %d > %d bytes (maximum block size) for pContext 0x%08x\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Expecting data not ACKs for pContext 0x%08x\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - File not open for %d.%d.%d.%d:%d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 8 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 16 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8)( pTftpServer->RemoteAddress.sin_addr.s_addr >> 24 ),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch ( Opcode ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Unable to process TFTP opcode: %d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Close the context if necessary
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the connection context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Locate the mode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Mode not found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - File mode not found\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Tell the client of the error
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TFTP - FileName: %a\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Locate the options
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // End of mode not found
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - File mode not valid\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Tell the client of the error
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TFTP - Mode: %a\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Verify the mode is supported
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // File access mode not supported
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - File mode %a not supported\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Tell the client of the error
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Open the file, close the context on error
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// TODO: Remove the following line
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine the file length
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the options
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read in the first portion of the file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the first block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the OACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the first block of data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TftpSendNextBlock ( pTftpServer, pContext );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the block number that is being ACKed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if this is the correct ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ACK for block 0x%04x received\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "WARNING - Expecting ACK 0x%0x4 not received ACK 0x%08x\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the expected ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the next expected ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the next packet of data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TftpSendNextBlock ( pTftpServer, pContext );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if the context should be closed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build and send an error packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pContext The context structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] Error Error number for the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pError Zero terminated error string address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Message processed successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Build the error packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy the zero terminated string into the buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while ( 0 != Character );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the error message
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pContext->TxBytes = pBuffer - &pContext->TxBuffer[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the operation status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send the next block of file system data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pContext The context structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Message processed successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine how much data needs to be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (( pContext->LengthInBytes < TFTP_MAX_BLOCK_SIZE )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync || ( LengthInBytes > (ssize_t)pContext->LengthInBytes )) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the TFTP opcode and block number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy the file data into the transmit buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the next block
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the operation status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create the port for the TFTP server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This routine polls the network layer to create the TFTP port for the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TFTP server. More than one attempt may be necessary since it may take
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync some time to get the IP address and initialize the upper layers of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the network stack.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (( DEBUG_SERVER_TIMER, "Entering TftpServerTimer\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Open the TFTP port on the server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Wait for a while
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CheckEvent ( pTftpServer->TimerEvent );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Attempt to create the socket for the TFTP server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->TftpPort.events = POLLRDNORM | POLLHUP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the socket address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TFTP Port: %d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->TftpServerAddress.sin_len = sizeof ( pTftpServer->TftpServerAddress );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->TftpServerAddress.sin_family = AF_INET;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->TftpServerAddress.sin_addr.s_addr = INADDR_ANY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pTftpServer->TftpServerAddress.sin_port = htons ( TftpPort );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Bind the socket to the TFTP port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (struct sockaddr *) &pTftpServer->TftpServerAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "0x%08x: Socket bound to port %d\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Release the socket if necessary
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Wait until the socket is open
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (( DEBUG_SERVER_TIMER, "Exiting TftpServerTimer\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Start the TFTP server port creation timer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The timer was successfully started.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ALREADY_STARTED The timer is already running.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Other The timer failed to start.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume the timer is already running
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the poll interval
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TriggerTime = TFTP_PORT_POLL_DELAY * ( 1000 * 10 );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (( DEBUG_TFTP_PORT, "TFTP port timer started\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Mark the timer running
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Failed to start TFTP port timer, Status: %r\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the operation status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Stop the TFTP server port creation timer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The TFTP port timer is stopped
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Other Failed to stop the TFTP port timer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume the timer is stopped
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Stop the port creation polling
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (( DEBUG_TFTP_PORT, "TFT[ port timer stopped\r\n" ));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Mark the timer stopped
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Failed to stop TFT[ port timer, Status: %r\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the operation status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send the next TFTP packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pTftpServer The TFTP server control structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] pContext The context structure address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Message processed successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume success
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the TFTP packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "0x%08x: pContext sending 0x%08x bytes\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "ERROR - Transmit failure, errno: 0x%08x\r\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the operation status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry point for the TFTP server application.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] Argc The number of arguments
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param [in] Argv The argument value array
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 The application exited normally.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Other An error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a timer event to start TFTP port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Run the TFTP server forever
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for ( ; ; ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Poll the network layer to create the TFTP port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // for the tftp server. More than one attempt may
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // be necessary since it may take some time to get
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the IP address and initialize the upper layers
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // of the network stack.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Poll the socket for activity
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// TODO: Remove the following test code
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Exit when the network connection is broken
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Done with the timer event
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CloseEvent ( pTftpServer->TimerEvent );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the final status