⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ebsimp.c

📁 windows mobile 5 下的底层驱动包
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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.

Module Name:  
    ebsimp.c
Abstract:  

    This contains the code to simplify bootloader development. It uses
    TFTP and DHCP functions. The intend is to hide all the ether details
    behind the scene for bootloader development. The bootloader can then
    be reduced to the following using the following routine.

      if (!EbootInitEtherTransport (....)) {
          while (1);  // spin forever
      }
      // main loop of download
      While (EbootEtherReadData (...)) {
          // process the data
          ProcessData (...);
      }

    For real implementation, please refer to sources under platform\ODO\eboot.
    
Functions:


Notes: 

--*/
#include <windows.h>
#include "tftp.h"
#include "dhcp.h"
#include "udp.h"
#include "eboot.h"

#define MAX_DHCP_RETRY      3   // max retries on IP conflict

#define MAX_BOOTME_CNT     40   // Max number of BOOTMEs sent
#define BOOTME_INTERVAL     3   // send bootme every 3 seconds

DWORD g_DhcpTimeout = 10;       // DHCP default timeout in 10 seconds

static LPBYTE gpbData;
static UINT16 gwLength;
static BYTE gFrameBuffer[ETHER_MTU];
static EDBG_ADDR *gpEdbgAddr;
static EDBG_ADDR gHostAddr;
static fTftpLinked = FALSE;
static EDBG_OS_CONFIG_DATA *gpCfgData;

static UINT16 EbootSimpleCallback (char *pszFileName, TFtpdCallBackOps Operation, BYTE *pbData, 
                                   UINT16 *cwLength, char **ppszErrorMsg )
{
    switch (Operation) {
    case TFTPD_OPEN:
        EdbgOutputDebugString( "EthDown::TFTPD_OPEN::%s\r\n", pszFileName);
        fTftpLinked = TRUE;
        gpbData = NULL;
        gwLength = 0;
        break;
    case TFTPD_WRITE:
        gpbData = pbData;
        gwLength = *cwLength;
        break;
    default:
        EdbgOutputDebugString( "EthDown::Illegal Operation Code %u\r\n", Operation );
        break;
    }
    return 0;
}

BOOL EbootInitTftpSimple (EDBG_ADDR *pEdbgAddr, UINT16 wOdoWKSP, UINT16 wHostWKSP, char *pszFileName)
{
    // Set up TFTP server.  Note that internally, we store port numbers in network byte order.
    EbootInitTFtp (wOdoWKSP, wHostWKSP);
    EbootInitTFtpd ();
    if (EbootTFtpdServerRegister (pszFileName, EbootSimpleCallback)) {
        EdbgOutputDebugString( "Server Registration Failed\r\n" );
        return FALSE;
    }
    gpEdbgAddr = pEdbgAddr;
    return TRUE;
}

// Ethernet frame type is in 7th word of buffer
#define FRAMETYPE(x)    ntohs(*(USHORT *)((x) + 6*sizeof(USHORT)))

BOOL EbootEtherReadData (DWORD cbData, LPBYTE pbData)
{
    USHORT wCopied;
    USHORT wLen, wDestPort, wSrcPort, wUDPDataLen, *pwUDPData;

    if (!gpEdbgAddr) {
        EdbgOutputDebugString ("EbootSimpleTFTP not initialized\r\n" );
        return FALSE;
    }
    while (cbData) {

        // wait for the next input
        while (!gwLength) {

            // get another frame and pass it to TFTP handler
            wLen = sizeof (gFrameBuffer);
            if (OEMEthGetFrame (gFrameBuffer, &wLen)        // frame available?
                && (0x0800 == FRAMETYPE (gFrameBuffer))     // IP packet?
                && !EbootCheckUDP(gpEdbgAddr, gFrameBuffer, &wDestPort, &wSrcPort, &pwUDPData, &wUDPDataLen)  // UDP?
                && EbootTFtpReceiver (gpEdbgAddr, gFrameBuffer, wDestPort, wSrcPort, pwUDPData, wUDPDataLen)) { // hand it to TFTP
		// EbootTFtpReceiver returns 1 when a new link is formed - this really isn't an error but we shouldn't keep the data either.
                gwLength = 0;
            }
        }
        wCopied = (cbData > gwLength)? gwLength : (USHORT) cbData;
        memcpy (pbData, gpbData, wCopied);
        gpbData += wCopied;
        gwLength -= wCopied;
        pbData += wCopied;
        cbData -= wCopied;
    }
    return TRUE;
}


// check if anyone using the IP address we're using
BOOL EbootCheckIP (EDBG_ADDR *pEdbgAddr)
{
    DWORD dwCurSec;
    USHORT wLen;

    // Send a gratuitous ARP (an ARP of our new IP address) to verify that no other
    // station is using our IP address.
    if (EbootGratuitousARP (pEdbgAddr, gFrameBuffer)) {
        EdbgOutputDebugString("EbootGratuitousARP failed\r\n");
        return FALSE;
    }

    // wait a while (ARP_RESPONSE_WAIT seconds) and see if anyone is responding 
    // to the Gratuitous ARP
    dwCurSec = OEMEthGetSecs ();
    while (OEMEthGetSecs () - dwCurSec < ARP_RESPONSE_WAIT) {
        wLen = sizeof (gFrameBuffer);
        if (OEMEthGetFrame (gFrameBuffer, &wLen)        // frame available?
            && (0x0806 == FRAMETYPE (gFrameBuffer))     // ARP packet?
            && (EbootProcessARP (pEdbgAddr, gFrameBuffer) == PROCESS_ARP_RESPONSE)) { // to us?
            return FALSE;
        }
    }
    return TRUE;
}

BOOL EbootGetDHCPAddr (EDBG_ADDR *pEdbgAddr, DWORD *pdwSubnetMask, DWORD *pdwDHCPLeaseTime)
{
    USHORT wLen, wDestPort, wSrcPort, wUDPDataLen, *pwUDPData;
    BOOL fGotIP = FALSE;
    int nRetries;
    DWORD dwCurSec;

    for (nRetries = 0; nRetries < MAX_DHCP_RETRY; nRetries ++) {
        // initialize DHCP, send DHCP request
        if (EbootInitDHCP (pEdbgAddr)) {
            EdbgOutputDebugString( "Error On InitDHCP() Call\r\n" );
            return FALSE;
        }

        dwCurSec = OEMEthGetSecs();
        // Loop until we get an IP address or timeout
        while (!fGotIP) {
            // see if DHCP timed out
            if ((OEMEthGetSecs() - dwCurSec) > g_DhcpTimeout)
                return FALSE;

            // try to re-transmit DHCP request
            EbootDHCPRetransmit (pEdbgAddr, NULL, NULL);

            // process DHCP packets
            wLen = sizeof (gFrameBuffer);
            if (OEMEthGetFrame (gFrameBuffer, &wLen)        // frame available?
                && (0x0800 == FRAMETYPE (gFrameBuffer))     // IP packet?
                && !EbootCheckUDP (pEdbgAddr, gFrameBuffer, &wDestPort, &wSrcPort, &pwUDPData, &wUDPDataLen)    // UDP?
                && (wDestPort == DHCP_CLIENT_PORT)          // DHCP src/dst port?
                && (wSrcPort == DHCP_SERVER_PORT)) {
                EbootProcessDHCP (pEdbgAddr,
                    pdwSubnetMask,
                    (BYTE *)pwUDPData,
                    wUDPDataLen,
                    pdwDHCPLeaseTime,
                    &fGotIP);
                EdbgOutputDebugString ("Got Response from DHCP server, IP address: %s\r\n",
                                      inet_ntoa(pEdbgAddr->dwIP));
            }
        }

        // verify that we are the only one using this address
        if (EbootCheckIP (pEdbgAddr)) {
            EdbgOutputDebugString ("No ARP response in %d seconds, assuming ownership of %s\r\n",
                                      ARP_RESPONSE_WAIT, inet_ntoa(pEdbgAddr->dwIP));
            return TRUE;
        }
        EdbgOutputDebugString( "Some other station has IP Address: %s !!! Retrying.\r\n", inet_ntoa(pEdbgAddr->dwIP));
        fGotIP = FALSE;
    }

    EdbgOutputDebugString ("Some other station has IP Address: %s !!! Aborting.\r\n", inet_ntoa(pEdbgAddr->dwIP));

    return FALSE;
}


BOOL EbootSendBootmeAndWaitForTftp (EDBG_ADDR *pEdbgAddr, UCHAR VersionMajor, UCHAR VersionMinor, 
                             char *szPlatformString, char *szDeviceName, 
                             UCHAR CPUId, DWORD dwBootFlags)
{
    DWORD dwCurSec = OEMEthGetSecs () - BOOTME_INTERVAL;
    USHORT wLen, wDestPort, wSrcPort, wUDPDataLen, *pwUDPData;
    int nRetries = 0;
    EdbgOutputDebugString ("+EbootSendBootmeAndWaitForTftp\r\n"); 
    while (!fTftpLinked) {
        if ((nRetries < MAX_BOOTME_CNT) && (OEMEthGetSecs () - dwCurSec >= BOOTME_INTERVAL)) {
            nRetries ++;
            dwCurSec += BOOTME_INTERVAL;
            // send a bootme message
            EbootSendBootme (pEdbgAddr, VersionMajor, VersionMinor, szPlatformString, szDeviceName, CPUId, dwBootFlags);
        }
        // get another frame and pass it to TFTP handler
        wLen = sizeof (gFrameBuffer);
        if (OEMEthGetFrame (gFrameBuffer, &wLen)) {       // frame available?
            switch (FRAMETYPE (gFrameBuffer)) {
            case 0x0800:    // IP packet
                if (!EbootCheckUDP(pEdbgAddr, gFrameBuffer, &wDestPort, &wSrcPort, &pwUDPData, &wUDPDataLen)) {  // UDP?
                    // EDBG command? (should only occur if eshell asked us to jump to existing image)
                    if (!EbootProcessEDBG (pEdbgAddr, &gHostAddr, gFrameBuffer, pwUDPData, wUDPDataLen, &fTftpLinked, &gpCfgData)) {
                        // no, pass it to TFTP
                        EbootTFtpReceiver (pEdbgAddr, gFrameBuffer, wDestPort, wSrcPort, pwUDPData, wUDPDataLen);
                    }
                }
                break;
            case 0x0806:    // ARP packet
                if (EbootProcessARP (pEdbgAddr, gFrameBuffer) == PROCESS_ARP_RESPONSE) {
                    EdbgOutputDebugString( "Some other station has IP Address: %s !!! Aborting.\r\n", inet_ntoa(pEdbgAddr->dwIP));
                    return FALSE;
                }
                break;
            default:
                break;
            }
        }
    }
    EdbgOutputDebugString ("-EbootSendBootmeAndWaitForTftp\r\n"); 
    return TRUE;
}

EDBG_OS_CONFIG_DATA *EbootWaitForHostConnect (EDBG_ADDR *pDevAddr, EDBG_ADDR *pHostAddr)
{
    USHORT wLen, wDestPort, wSrcPort, wUDPDataLen, *pwUDPData;
    BOOL fGotJumpimg = FALSE;
    while (!gpCfgData) {
        wLen = sizeof (gFrameBuffer);
        if (OEMEthGetFrame (gFrameBuffer, &wLen)        // frame available?
            && (0x0800 == FRAMETYPE (gFrameBuffer))     // IP packet?
            && !EbootCheckUDP (pDevAddr, gFrameBuffer, &wDestPort, &wSrcPort, &pwUDPData, &wUDPDataLen)) {    // UDP?
            // check EDBG for JUMP packet
            EbootProcessEDBG(pDevAddr, &gHostAddr, gFrameBuffer, pwUDPData, wUDPDataLen, &fGotJumpimg, &gpCfgData);
        }
    }
    if (pHostAddr) {
        memcpy (pHostAddr, &gHostAddr, sizeof (EDBG_ADDR));
    }
    return gpCfgData;
}


BOOL EbootInitEtherTransport (EDBG_ADDR *pEdbgAddr, LPDWORD pdwSubnetMask,
                              BOOL *pfJumpImg,         // will be set to TRUE if eshell asked us to jump to existing image
                              DWORD *pdwDHCPLeaseTime, // this parameter is overloaded. pass NULL to indicate static IP
                              UCHAR VersionMajor, UCHAR VersionMinor, 
                              char *szPlatformString, char *szDeviceName, 
                              UCHAR CPUId, DWORD dwBootFlags)
{
    // simple check on arguments
    if (!pEdbgAddr || !pdwSubnetMask || !szPlatformString) {
        return FALSE;
    }

    // find out IP address and verify it
    if (pdwDHCPLeaseTime) {
        if (!EbootGetDHCPAddr (pEdbgAddr, pdwSubnetMask, pdwDHCPLeaseTime)) {
            return FALSE;
        }
    } else {
        if (!EbootCheckIP (pEdbgAddr)) {
            EdbgOutputDebugString ("Some other station has IP Address: %s !!! Aborting.\r\n", inet_ntoa(pEdbgAddr->dwIP));
            return FALSE;
        }
        // This will tell CheckUDP() to only accept datagrams for our IP address
        ClearPromiscuousIP();
    }

    if (!EbootInitTftpSimple (pEdbgAddr, htons(EDBG_DOWNLOAD_PORT), htons(EDBG_DOWNLOAD_PORT), EDBG_DOWNLOAD_FILENAME)) {
        return FALSE;
    }
    if (!EbootSendBootmeAndWaitForTftp (pEdbgAddr, VersionMajor, VersionMinor, szPlatformString, szDeviceName, CPUId, dwBootFlags))
        return FALSE;

    *pfJumpImg = (NULL != gpCfgData);
    return TRUE;
}

⌨️ 快捷键说明

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