www.pudn.com > iMx31_WCE600.rar > utils.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. 
// 
//----------------------------------------------------------------------------- 
// 
//  Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved. 
//  THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS 
//  AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT 
// 
//----------------------------------------------------------------------------- 
// 
//  File:  utils.c 
// 
//  Generic "utility" routines for the bootloader. 
// 
//----------------------------------------------------------------------------- 
#include "bsp.h" 
#include "loader.h" 
 
//----------------------------------------------------------------------------- 
// External Functions 
 
//----------------------------------------------------------------------------- 
// External Variables 
 
//----------------------------------------------------------------------------- 
// Defines 
 
 
//----------------------------------------------------------------------------- 
// Types 
 
 
//----------------------------------------------------------------------------- 
// Global Variables 
 
 
//----------------------------------------------------------------------------- 
// Local Variables 
 
 
//------------------------------------------------------------------------------ 
// Local Functions 
// 
void SetMAC(BOOT_CFG *pBootCfg); 
void CvtMAC(USHORT MacAddr[3], char *pszDottedD); 
static ULONG bstrtoul(PUCHAR pStr, UCHAR nBase); 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  SpinForever 
// 
//  Halts the bootloader. 
// 
//  Parameters: 
//      None. 
// 
//  Returns: 
//      None. 
// 
//----------------------------------------------------------------------------- 
void SpinForever(void) 
{ 
    KITLOutputDebugString("SpinForever...\r\n"); 
 
    for (;;) 
    { 
        ; 
    } 
} 
 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  OEMShowProgress 
// 
//  This function shows visual information, on an LED, for example,  
//  to let users know that the download is in progress. It is called as the  
//  download progresses. 
// 
//  Parameters: 
//      dwPacketNum  
//          [in] Equal to the packet number currently downloading. Knowing  
//          the total number of packets, a download percentage can be computed. 
// 
//  Returns: 
//      None. 
// 
//----------------------------------------------------------------------------- 
void OEMShowProgress(DWORD dwPacketNum) 
{ 
    // Remove-W4: Warning C4100 workaround 
    UNREFERENCED_PARAMETER(dwPacketNum); 
} 
 
 
//----------------------------------------------------------------------------- 
// 
//  Function: OEMEthGetSecs 
// 
//  This function returns the number of seconds that have passed since a  
//  certain fixed time.  This function handles time-outs while in polling  
//  mode. The origin of the count is unimportant as long as the count is  
//  incremental. 
// 
//  Parameters: 
//      None. 
// 
// Returns: 
//      Count of seconds that have passed since a certain fixed time. 
// 
//----------------------------------------------------------------------------- 
DWORD OEMEthGetSecs(void) 
{ 
    DWORD sec, hourmin; 
 
    pRTCRegisters_t pRTC = (pRTCRegisters_t) OALPAtoUA(CSP_BASE_REG_PA_RTC); 
 
    sec = INREG32(&pRTC->RTCSecCnt); 
    hourmin = INREG32(&pRTC->RTCHMCnt); 
    sec += (((((hourmin >> 8) & 0xFF) * 60) + (hourmin & 0xFF)) * 60); 
 
    return sec; 
} 
 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  OALGetTickCount 
// 
//  This function is called by some KITL libraries to obtain relative time 
//  since device boot. It is mostly used to implement timeout in network 
//  protocol. 
// 
//  Parameters: 
//      None. 
// 
// Returns: 
//      Returns the number of 1-millisecond ticks that have elapsed since  
//      the last system boot or reset. 
// 
//----------------------------------------------------------------------------- 
UINT32 OALGetTickCount() 
{ 
    return OEMEthGetSecs () * 1000; 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  SetMAC 
// 
//  Allows user to set a MAC address using the boot loader menu. 
// 
//  Parameters: 
//      eBootCFG 
//          [out] Points to bootloader configuration that will be updated with 
//          the MAC address entered by the user. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
void SetMAC(BOOT_CFG *pBootCfg) 
{ 
    CHAR szDottedD[24]; 
    USHORT cwNumChars = 0; 
    USHORT InChar = 0; 
    INT32  dwCharRead = OEM_DEBUG_READ_NODATA; 
 
    memset(szDottedD, '0', 24); 
 
    EdbgOutputDebugString ( "\r\nEnter new MAC address in hexadecimal (hh.hh.hh.hh.hh.hh): "); 
 
    while(!((InChar == 0x0d) || (InChar == 0x0a))) 
    { 
        dwCharRead = OEMReadDebugByte(); 
        if (dwCharRead != OEM_DEBUG_COM_ERROR && dwCharRead != OEM_DEBUG_READ_NODATA) 
        { 
            InChar = (USHORT)dwCharRead; 
            InChar = (USHORT)tolower(InChar); 
 
            // If it's a hex number or a period, add it to the string. 
            // 
            if (InChar == '.' || (InChar >= '0' && InChar <= '9') || (InChar >= 'a' && InChar <= 'f'))  
            { 
                if (cwNumChars < 17)  
                { 
                    szDottedD[cwNumChars++] = (char)InChar; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
            else if (InChar == 8)       // If it's a backspace, back up. 
            { 
                if (cwNumChars > 0)  
                { 
                    cwNumChars--; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
        } 
    } 
 
    EdbgOutputDebugString ( "\r\n"); 
 
    // If it's a carriage return with an empty string, don't change anything. 
    // 
    if (cwNumChars)  
    { 
        szDottedD[cwNumChars] = '\0'; 
        CvtMAC(pBootCfg->mac, szDottedD); 
        EdbgOutputDebugString("INFO: MAC address set to: %x:%x:%x:%x:%x:%x\r\n", 
                  pBootCfg->mac[0] & 0x00FF, pBootCfg->mac[0] >> 8, 
                  pBootCfg->mac[1] & 0x00FF, pBootCfg->mac[1] >> 8, 
                  pBootCfg->mac[2] & 0x00FF, pBootCfg->mac[2] >> 8); 
        return; 
    } 
    EdbgOutputDebugString("WARNING: SetCS8900MACAddress: Invalid MAC address.\r\n"); 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  bstrtoul 
// 
//  Provides boot loader implementation for strtoul. 
// 
//  Parameters: 
//      pStr  
//          [in] Null-terminated string to convert. 
// 
//      nBase 
//          [in] Number base to use for coversion. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
static ULONG bstrtoul(PUCHAR pStr, UCHAR nBase) 
{ 
    UCHAR nPos=0; 
    BYTE c; 
    ULONG nVal = 0; 
    UCHAR nCnt=0; 
    ULONG n=0; 
 
    // fulllibc doesn't implement isctype or iswctype, which are needed by 
    // strtoul, rather than including coredll code, here's our own simple strtoul. 
 
    if (pStr == NULL) 
        return(0); 
 
    for (nPos=0 ; nPos < strlen((const CHAR *)pStr) ; nPos++) 
    { 
        c = (BYTE)tolower(*(pStr + strlen((const CHAR *)pStr) - 1 - nPos)); 
        if (c >= '0' && c <= '9') 
            c -= '0'; 
        else if (c >= 'a' && c <= 'f') 
        { 
            c -= 'a'; 
            c  = (0xa + c); 
        } 
 
        for (nCnt = 0, n = 1 ; nCnt < nPos ; nCnt++) 
        { 
            n *= nBase; 
        } 
        nVal += (n * c); 
    } 
 
    return(nVal); 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  CvtMAC 
// 
//  Converts MAC address specified by the user in dotted string format 
//  into 16-bit numeric array. 
// 
//  Parameters: 
//      MacAddr  
//          [out] 16-bit numeric array for converted MAC address. 
// 
//      pszDottedD 
//          [in] Points to string containing MAC address. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
void CvtMAC(USHORT MacAddr[3], char *pszDottedD)  
{ 
    DWORD cBytes; 
    char *pszLastNum; 
    int atoi (const char *s); 
    int i=0; 
    BYTE *p = (BYTE *)MacAddr; 
 
    // Replace the dots with NULL terminators 
    pszLastNum = pszDottedD; 
    for(cBytes = 0 ; cBytes < 6 ; cBytes++) 
    { 
        while(*pszDottedD != '.' && *pszDottedD != '\0') 
        { 
            pszDottedD++; 
        } 
        if (pszDottedD == '\0' && cBytes != 5) 
        { 
            // zero out the rest of MAC address 
            while(i++ < 6) 
            { 
                *p++ = 0; 
            } 
            break; 
        } 
        *pszDottedD = '\0'; 
        *p++ = (BYTE)(bstrtoul((PUCHAR)pszLastNum, 16) & 0xFF); 
        i++; 
        pszLastNum = ++pszDottedD; 
    } 
} 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  SetBootMe 
// 
//  Allows user to set a BOOTME packet count using the boot loader menu. 
// 
//  Parameters: 
//      eBootCFG 
//          [out] Points to bootloader configuration that will be updated with 
//          the BOOTME packet count entered by the user. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
void SetBootMe(BOOT_CFG *pBootCFG) 
{ 
    char szCount[16]; 
    WORD cwNumChars = 0; 
    UINT16 InChar = 0; 
    INT32  dwCharRead = OEM_DEBUG_READ_NODATA; 
 
    KITLOutputDebugString ( "\r\nUse 0 for continuous boot me packets. \r\n"); 
    KITLOutputDebugString ( "Enter maximum number of boot me packets to send [0-255]: "); 
 
    while (!((InChar == 0x0d) || (InChar == 0x0a))) 
    { 
        dwCharRead = OEMReadDebugByte(); 
        if (dwCharRead != OEM_DEBUG_COM_ERROR && dwCharRead != OEM_DEBUG_READ_NODATA) 
        { 
            InChar = (UINT16)dwCharRead; 
            // If it's a number or a period, add it to the string 
            if ((InChar >= '0' && InChar <= '9')) 
            { 
                if (cwNumChars < 16) 
                { 
                    szCount[cwNumChars++] = (char)InChar; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
            // If it's a backspace, back up 
            else if (InChar == 8) 
            { 
                if (cwNumChars > 0) 
                { 
                    cwNumChars--; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
        } 
    } 
 
    // If it's a carriage return with an empty string, don't change anything. 
    if (cwNumChars) 
    { 
        szCount[cwNumChars] = '\0'; 
        pBootCFG->numBootMe = atoi(szCount); 
        if (pBootCFG->numBootMe > 255) 
        { 
            pBootCFG->numBootMe = 255; 
        } 
        else if (pBootCFG->numBootMe < 0) 
        { 
            pBootCFG->numBootMe = 1; 
        } 
    } 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  SetDelay 
// 
//  Allows user to set a boot delay using the boot loader menu. 
// 
//  Parameters: 
//      eBootCFG 
//          [out] Points to bootloader configuration that will be updated with 
//          the boot delay entered by the user. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
void SetDelay(BOOT_CFG *pBootCFG) 
{ 
    char szCount[16]; 
    WORD cwNumChars = 0; 
    UINT16 InChar = 0; 
    INT32  dwCharRead = OEM_DEBUG_READ_NODATA; 
 
    KITLOutputDebugString ( "\r\nEnter maximum number of seconds to delay [1-255]: "); 
 
    while (!((InChar == 0x0d) || (InChar == 0x0a))) 
    { 
        dwCharRead = OEMReadDebugByte(); 
        if (dwCharRead != OEM_DEBUG_COM_ERROR && dwCharRead != OEM_DEBUG_READ_NODATA) 
        { 
            InChar = (UINT16)dwCharRead; 
 
            // If it's a number or a period, add it to the string 
            if ((InChar >= '0' && InChar <= '9')) 
            { 
                if (cwNumChars < 16) 
                { 
                    szCount[cwNumChars++] = (char)InChar; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
            // If it's a backspace, back up 
            else if (InChar == 8) 
            { 
                if (cwNumChars > 0) 
                { 
                    cwNumChars--; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
        } 
    } 
 
    // If it's a carriage return with an empty string, don't change anything. 
    if (cwNumChars) 
    { 
        szCount[cwNumChars] = '\0'; 
        pBootCFG->delay = atoi(szCount); 
        if (pBootCFG->delay > 255) 
        { 
            pBootCFG->delay = 255; 
        } 
        else if (pBootCFG->delay < 1) 
        { 
            pBootCFG->delay = 1; 
        } 
    } 
}