ethdown.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 235 行

C
235
字号
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.

Module Name:  
    ethdown.c

Abstract:  
    This contains an example of a registered TFTP server 
    process.  It is the EthDown() routine that handles the download
    of .BIN files to RAM.  

Functions:


Notes: 

--*/
#include <windows.h>
#include <halether.h>

#include "eboot.h"
#include "ethdown.h"

DWORD dwPhysStart;      // image physical starting address
DWORD dwPhysLen;        // image physical length
 
DWORD dwLaunchAddr;

DWORD v_PacketNum;


UINT16 EthDown( char *pszFileName, TFtpdCallBackOps Operation, BYTE *pbData, UINT16 *cwLength, char **ppszErrorMsg ) {

    static BINFileParseStates BINFileParseState;
    // Because the signature of the BIN file is 7 bytes long and the length of a TFTP data packet
    //  is typically 512 bytes long, it is very probable that the last 4 byte DWORD will be broken
    //  across two TFTP packets.  I use these two variables to store the broken DWORD.
    static DWORD dwDataTailFromLastPacket;  // The beginning of the broken DWORD that has been
                                            //  retained from the last packet.
    static BYTE bNumBytesInDataTail;        // The number of bytes that have been carried over from
                                            //  the last packet.  Note that these are numbered starting
                                            //  from low byte to high byte because this is little endian.
                                            // DANGER - This may not be true on all processors.
    DWORD UNALIGNED *pdwBuffer;         // Pointer to current data position within the current TFTP packet
    int iBufferPos;             // Position of processing within the pbData packet buffer
    DWORD dwCurDataWord;        // Usually, this is the data word at the current position within the
                                //  TFTP packet.  However, in order to compensate for the 7 byte preamble
                                //  misalignment, this word may be "doctored" at the beginning of parsing
                                //  a packet in order to include carry over byte(s) from the last packet.
    static DWORD UNALIGNED *pdwDest;        // Pointer to the address that the data is to be written too.
    static DWORD dwRecordLen;   // Total length of the record being processed
    static DWORD dwRecordPos;   // Position of processing within the record being processed
    static DWORD dwPerfectCRC;  // Theoretical CRC over the record being processed
    DWORD dwPartialCRC;         // Running CRC over the record being processed
    static BYTE *pbCRC;         // Pointer used to run through memory to calculate CRC
    DWORD i;

    switch( Operation ) {

        case TFTPD_OPEN:
            EdbgOutputDebugString( "EthDown::TFTPD_OPEN::%s\r\n", pszFileName );
            dwPhysLen = 0;
            break;

        case TFTPD_READ:
            *cwLength = 0;
            EdbgOutputDebugString( "EthDown::TFTPD_READ::%s returning %u bytes\r\n", pszFileName, *cwLength );
            break;

        case TFTPD_WRITE:
//          EdbgOutputDebugString( "EthDown::TFTPD_WRITE::%s with %u bytes\r\n", pszFileName, *cwLength );

            iBufferPos = 0;
            pdwBuffer = (DWORD *)pbData;

            if (dwPhysLen == 0) {
                v_PacketNum = 0;
            } else {
                v_PacketNum++;
            }
            
            // If this is the beginning of the file
            if (dwPhysLen == 0) {
                if (memcmp( pbData, "B000FF\x0A", 7 )) {
                    EdbgOutputDebugString( "EthDown::TFTPD_WRITE::This isn't a .BIN file.\r\n" );
                    *ppszErrorMsg = "File Is Not .BIN Format";
                    return 1;
                }

                // I need to DWORD align the rest of the data so that the DWORD accesses won't cause
                //  processor exceptions
                *cwLength -= 7;
                pdwBuffer = (DWORD UNALIGNED *) (pbData + 7); // memmove( pbData, pbData + 7, *cwLength );

                dwPhysStart = *pdwBuffer++;
                dwPhysLen = *pdwBuffer++;
                iBufferPos = 8;
                EdbgOutputDebugString("\r\nImage start 0x%X length 0x%X\r\n", dwPhysStart, dwPhysLen );
                bNumBytesInDataTail = 0;
                BINFileParseState = BIN_PHYSADDR;
            }
            // Check to see if this is the last packet and it's empty
            else if (*cwLength == 0)
                return 0;

            // Pull the rest of the 32-bit data word that was started in the last packet
            if (bNumBytesInDataTail) {
                dwCurDataWord = 0;
#ifdef BACKWARDS
                for( i = 0; i < 4UL-bNumBytesInDataTail; i++ )
                    dwCurDataWord |= pbData[i] << (((3UL-bNumBytesInDataTail) - i) * 8);
#else               
                for( i = 0; i < 4UL-bNumBytesInDataTail; i++ )
                    dwCurDataWord |= pbData[i] << ((i+bNumBytesInDataTail) * 8);
#endif              
                dwCurDataWord |= dwDataTailFromLastPacket;

                // DWORD align the buffer
                *cwLength -= 4 - bNumBytesInDataTail;
                pdwBuffer = (DWORD UNALIGNED *) (pbData + (4-bNumBytesInDataTail)); //memmove( pbData, pbData + (4-bNumBytesInDataTail), *cwLength );
                iBufferPos = -4;
            }
            else
                dwCurDataWord = *pdwBuffer++;

            // I'll keep looping until I get almost to the end of the packet buffer
            while( iBufferPos + 4 < *cwLength ) {
                switch( BINFileParseState ) {
                    case BIN_PHYSADDR:
                        pdwDest = (DWORD UNALIGNED *)dwCurDataWord;
                        pbCRC = (BYTE *)dwCurDataWord;

                        BINFileParseState = BIN_PHYSLEN;
                        break;
                    case BIN_PHYSLEN:
                        dwRecordLen = dwCurDataWord;
                        // Check and see if this is the last record, if so, launch
                        if (pdwDest == 0) {
                            dwLaunchAddr = dwRecordLen;
                            return 0;
                        }
                        BINFileParseState = BIN_CHECKSUM;
                        break;
                    case BIN_CHECKSUM:
                        dwPerfectCRC = dwCurDataWord;
                        dwRecordPos = 0;
                        BINFileParseState = BIN_DATA;
                        break;
                    case BIN_DATA:
                        // If we aren't at the end of the record yet read another DWORD.  Note that the number of
                        //  bytes in a record is guaranteed to always be DWORD aligned, so we can assume that there
                        //  won't be a partial DWORD at the end of a record.
                        *pdwDest++ = dwCurDataWord;
                        dwRecordPos += 4;
                        if (dwRecordPos < dwRecordLen)
                            BINFileParseState = BIN_DATA;
                        // If we have reached the end of the record
                        else {
                            // Check the CRC
                            dwPartialCRC = 0;
                            for( i = 0; i < dwRecordLen; i++ )
                                dwPartialCRC += *pbCRC++;
                            if (dwPartialCRC != dwPerfectCRC) {
                                EdbgOutputDebugString( "EthDown::TFTPD_WRITE::CRC Error - Calculated 0x%X Perfect 0x%X (dest = 0x%X)\r\n",
                                    dwPartialCRC, dwPerfectCRC, pdwDest );
                                *ppszErrorMsg = "CRC Error";
                                return 1;
                            }
                            BINFileParseState = BIN_PHYSADDR;
                        }
                        break;
                } // switch(BINFileParseState)
                dwCurDataWord = *pdwBuffer++;
                iBufferPos += 4;
            } // while not at end of buffer

            // Store the fragmented DWORD until we get the next packet
            bNumBytesInDataTail = (BYTE)(*cwLength - iBufferPos);
            dwDataTailFromLastPacket = dwCurDataWord;

            // Mask off the garbage that was picked up from the end of the packet buffer 
            switch( bNumBytesInDataTail ) {
#ifdef BACKWARDS
                case 1:
                    EdbgOutputDebugString("last byte 0x%B (DWORD 0x%X)\r\n", pbData[511], dwDataTailFromLastPacket);
                    dwDataTailFromLastPacket &= 0xFF000000UL;
                    break;
                case 2:
                    EdbgOutputDebugString("last 2byte 0x%B (DWORD 0x%X)\r\n", pbData[510], dwDataTailFromLastPacket);
                    dwDataTailFromLastPacket &= 0xFFFF0000UL;
                    break;
                case 3:
                    EdbgOutputDebugString("last 3byte 0x%B (DWORD 0x%X)\r\n", pbData[509], dwDataTailFromLastPacket);
                    dwDataTailFromLastPacket &= 0xFFFFFF00UL;
                    break;
#else                
                case 1:
                    dwDataTailFromLastPacket &= 0x000000FFUL;
                    break;
                case 2:
                    dwDataTailFromLastPacket &= 0x0000FFFFUL;
                    break;
                case 3:
                    dwDataTailFromLastPacket &= 0x00FFFFFFUL;
                    break;
#endif
            }

            break;

        case TFTPD_DESTROY:
            EdbgOutputDebugString( "EthDown::TFTPD_DESTROY::%s with %u bytes\r\n", pszFileName, *cwLength );
            for( i = 0; i < *cwLength; i++ ) {
                if (i > 0 && i % 8 == 0)
                    EdbgOutputDebugString( "    " );
                if (i > 0 && i % 16 == 0)
                    EdbgOutputDebugString( "\r\n" );
                EdbgOutputDebugString( "%B ", pbData[i] );
            }
            break;

        default:
            EdbgOutputDebugString( "EthDown::Illegal Operation Code %u\r\n", Operation );
            return 1;
            break;

    } // switch

    return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?