www.pudn.com > iMx31_WCE600.rar > sboot.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) 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:  sboot.c 
// 
//  Core routines for the Serial bootloader. 
// 
//----------------------------------------------------------------------------- 
 
#include  
#include  
#include  
 
//----------------------------------------------------------------------------- 
// External Functions 
 
//----------------------------------------------------------------------------- 
// External Variables 
extern BSP_ARGS *g_pBSPArgs; 
extern PCSP_PBC_REGS g_pPBC; 
extern PCSP_IOMUX_REGS g_pIOMUX; 
extern PCSP_CCM_REGS g_pCCM; 
extern BOOT_CFG   g_BootCFG; 
extern BOOT_BINDIO_CONTEXT g_BinDIO; 
 
//----------------------------------------------------------------------------- 
// Global Variables 
 
static PCSP_UART_REG g_pUART; 
 
// serial packet header and trailer definitions 
static const UCHAR packetHeaderSig[] = { 'k', 'I', 'T', 'L' }; 
 
__declspec(align(4)) BYTE g_buffer[KITL_MTU]; 
 
BOOT_CFG *pBootArgs = &g_BootCFG; 
 
//----------------------------------------------------------------------------- 
// Defines 
#define DEF_BAUD_RATE 115200 
// DEF_BAUD_RATE must be one of 115200, 57600, 38400, 19200, 9600 
 
// Use the serial bootloader in conjunction with the serial kitl transport 
// Both the transport and the download service expect packets with the 
// same header format. Packets not of type DLREQ, DLPKT, or DLACK are  
// ignored by the serial bootloader. 
 
#define KITL_MAX_DEV_NAMELEN      16 
#define KITL_MTU                  1520 
 
#define HEADER_SIG_BYTES    sizeof(packetHeaderSig) 
 
#define KS_PKT_KITL         0xAA 
#define KS_PKT_DLREQ        0xBB 
#define KS_PKT_DLPKT        0xCC 
#define KS_PKT_DLACK        0xDD 
#define KS_PKT_JUMP         0xEE 
 
// serial port definitions 
#define UART_UCR2_CTS_ACTIVE	0x1000 
#define UART_RX_FRAMING_ERR		0x1000 
#define UART_RX_PARITY_ERR		0x400 
#define UART_RX_OVERRUN			0x2000 
#define UART_RX_ERRORS			(UART_RX_FRAMING_ERR | UART_RX_PARITY_ERR | UART_RX_OVERRUN) 
 
#define TIMEOUT_RECV    5 // seconds 
 
 
//----------------------------------------------------------------------------- 
// Types 
 
// packet header 
#include  
typedef struct tagSERIAL_PACKET_HEADER  
{ 
    UCHAR headerSig[HEADER_SIG_BYTES]; 
    UCHAR pktType; 
    UCHAR Reserved; 
    USHORT payloadSize; // not including this header     
    UCHAR crcData; 
    UCHAR crcHdr; 
 
} SERIAL_PACKET_HEADER, *PSERIAL_PACKET_HEADER; 
#include  
 
// packet payload 
typedef struct tagSERIAL_BOOT_REQUEST  
{ 
    UCHAR PlatformId[KITL_MAX_DEV_NAMELEN+1]; 
    UCHAR DeviceName[KITL_MAX_DEV_NAMELEN+1]; 
    USHORT reserved; 
 
} SERIAL_BOOT_REQUEST, *PSERIAL_BOOT_REQUEST; 
 
typedef struct tagSERIAL_BOOT_ACK 
{ 
    DWORD fJumping; 
 
} SERIAL_BOOT_ACK, *PSERIAL_BOOT_ACK; 
 
typedef struct tagSERIAL_JUMP_REQUST 
{ 
    DWORD dwKitlTransport; 
     
} SERIAL_JUMP_REQUEST, *PSERIAL_JUMP_REQUEST; 
 
typedef struct tagSERIAL_BLOCK_HEADER 
{ 
    DWORD uBlockNum; 
     
} SERIAL_BLOCK_HEADER, *PSERIAL_BLOCK_HEADER; 
 
 
//----------------------------------------------------------------------------- 
// Local Variables 
 
 
//------------------------------------------------------------------------------ 
// Local Functions 
// 
BOOL OEMSerialSendRaw(LPBYTE pbFrame, USHORT cbFrame); 
BOOL OEMSerialRecvRaw(LPBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite); 
BOOL RecvHeader(PSERIAL_PACKET_HEADER pHeader, BOOLEAN bWaitInfinite); 
BOOL RecvPacket(PSERIAL_PACKET_HEADER pHeader, PBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite); 
BOOL WaitForJump(VOID); 
BOOL WaitForBootAck(BOOL *pfJump); 
BOOL SerialSendBlockAck(DWORD uBlockNumber); 
BOOL SerialSendBootRequest(VOID); 
static BOOL SBOOTReadData (DWORD cbData, LPBYTE pbData); 
 
void ResetDefaultBootCFG(BOOT_CFG *pBootCFG); 
 
// OS launch function type 
typedef void (*PFN_LAUNCH)(); 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  OEMBootInit 
// 
//  Parameters: 
//      None. 
// 
//  Returns: 
//      None. 
//------------------------------------------------------------------------------ 
void OEMBootInit (void) 
{ 
    KITLOutputDebugString("Microsoft Windows CE Serial Bootloader %d.%d for MX32 ADS (%s %s)\r\n", 
                          SBOOT_VERSION_MAJOR, SBOOT_VERSION_MINOR, __DATE__, __TIME__); 
 
	return; 
} 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  OEMGetMagicNumber 
// 
//  Parameters: 
//      None. 
// 
//  Returns: 
//      Magic number of SBOOT version. 
//------------------------------------------------------------------------------ 
UINT32 OEMGetMagicNumber() 
{ 
	return SBOOT_CFG_MAGIC_NUMBER; 
} 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  GetPreDownloadInfo 
// 
//  Parameters:         
//      None. 
// 
//  Returns: 
//      TRUE for Download/FALSE for jump to resident OS image 
//------------------------------------------------------------------------------ 
BOOL GetPreDownloadInfo (PBOOT_CFG p_bootCfg) 
{ 
    BOOL fGotJump = FALSE; 
	BOOL bParityEnable = TRUE; 
	SERIAL_INFO serInfo; 
	DWORD dwParity = p_bootCfg->Parity; 
 
    switch (p_bootCfg->Channel) 
	{ 
		case 1: 
			p_bootCfg->dwSerPhysAddr = CSP_BASE_REG_PA_UART1; 
			break; 
 
		case 2: 
			p_bootCfg->dwSerPhysAddr = CSP_BASE_REG_PA_UART2; 
			break; 
 
		case 3: 
			p_bootCfg->dwSerPhysAddr = CSP_BASE_REG_PA_UART3; 
			break; 
 
		case 4: 
			p_bootCfg->dwSerPhysAddr = CSP_BASE_REG_PA_UART4; 
			break; 
 
		case 5: 
			p_bootCfg->dwSerPhysAddr = CSP_BASE_REG_PA_UART5; 
			break; 
 
		default: 
			p_bootCfg->dwSerPhysAddr = DEFAULT_SBOOT_BASE_REG; 
			break; 
 
	} 
 
	g_pUART = (PCSP_UART_REG) OALPAtoUA(p_bootCfg->dwSerPhysAddr); 
    if (g_pUART == NULL) 
    { 
        return FALSE; 
    } 
 
	if (p_bootCfg->Parity == SBOOT_PARITY_NONE) 
	{ 
		bParityEnable = FALSE; 
		dwParity = SBOOT_PARITY_EVEN; 
	} 
 
	serInfo.baudRate = p_bootCfg->BaudRate; 
	serInfo.uartBaseAddr = p_bootCfg->dwSerPhysAddr; 
	serInfo.dataBits = p_bootCfg->DataBits; 
	serInfo.parity = dwParity; 
	serInfo.bParityEnable = bParityEnable; 
	serInfo.flowControl = p_bootCfg->FlowCtrl; 
	serInfo.stopBits = p_bootCfg->StopBit; 
		 
    OALSerialInit(&serInfo); 
 
    // send boot requests indefinitely 
    do 
    { 
        EdbgOutputDebugString("Sending sboot request...\r\n"); 
        if(!SerialSendBootRequest()) 
        { 
            EdbgOutputDebugString("Failed to send sboot request\r\n"); 
            return BL_ERROR; 
        } 
    } 
    while(!WaitForBootAck(&fGotJump)); 
 
    // ack block zero to start the download 
    SerialSendBlockAck(0); 
 
    EdbgOutputDebugString("Received sboot request ack... starting download\r\n"); 
 
    return fGotJump  ? BL_JUMP : BL_DOWNLOAD; 
 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  GetLaunchInfo 
// 
//  Parameters:         
//     None. 
// 
//  Returns: 
//      None. 
//------------------------------------------------------------------------------ 
void GetLaunchInfo (void) 
{ 
    // wait for jump packet indefinitely 
    if(WaitForJump() == FALSE) 
    { 
	    EdbgOutputDebugString("Failed to wait for jump message\r\n"); 
    } 
 
    return; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  OEMReadData 
// 
//  This function reads data from the transport during the download process.  
//  It is called by the BLCOMMON framework. 
// 
//  Parameters: 
//      cbData  
//          [in] Amount of data, in bytes, to read.  
// 
//      pbData  
//          [out] Pointer to read buffer.  
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
// 
//----------------------------------------------------------------------------- 
BOOL OEMReadData(DWORD cbData, LPBYTE pbData) 
{ 
	BOOL bRet = TRUE; 
 
    // TODO: increment bytes read to track download progress. 
	// Save read data size and location. It is used in workaround 
	// for download BIN DIO images larger than RAM. 
	g_BinDIO.readSize = cbData; 
	g_BinDIO.pReadBuffer = pbData; 
 
	bRet = SBOOTReadData(cbData, pbData); 
	 
	return bRet; 
} 
 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  SBOOTReadData 
// 
//  This function reads data from the serial transport during the download.  
// 
//  Parameters: 
//      cbData  
//          [in] Amount of data, in bytes, to read.  
// 
//      pbData  
//          [out] Pointer to read buffer.  
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
static BOOL SBOOTReadData (DWORD cbData, LPBYTE pbData) 
{ 
    static DWORD dwBlockNumber = 0; 
     
    static USHORT cbDataBuffer = 0;     
    static BYTE dataBuffer[KITL_MTU] = {0}; 
 
    // the first DWORD in the local buffer is the block header which contains 
    // the sequence number of the block received 
    static PSERIAL_BLOCK_HEADER pBlockHeader = (PSERIAL_BLOCK_HEADER)dataBuffer; 
    static PBYTE pBlock = dataBuffer + sizeof(PSERIAL_BLOCK_HEADER); 
 
    SERIAL_PACKET_HEADER header; 
    USHORT cbPacket; 
 
    LPBYTE pOutBuffer = pbData; 
 
    while(cbData) 
    { 
        // if there is no data in the local buffer, read some 
        // 
        while(0 == cbDataBuffer) 
        { 
             // read from port 
             cbPacket = sizeof(dataBuffer); 
             if(RecvPacket(&header, dataBuffer, &cbPacket, TRUE)) 
             { 
                // ignore non-download packet types 
                if(KS_PKT_DLPKT == header.pktType) 
                {                     
                    // make sure we received the correct block in the sequence 
                    if(dwBlockNumber == pBlockHeader->uBlockNum) 
                    { 
                        cbDataBuffer = header.payloadSize - sizeof(SERIAL_BLOCK_HEADER); 
                        dwBlockNumber++; 
                    } 
                    else 
                    { 
                        EdbgOutputDebugString("Received out of sequence block %u\r\n", pBlockHeader->uBlockNum); 
                        EdbgOutputDebugString("Expected block %u\r\n", dwBlockNumber); 
                    } 
                     
                    // ack, or re-ack the sender 
                    if(dwBlockNumber > 0) 
                    { 
                        // block number has already been incremented when appropriate 
                        SerialSendBlockAck(dwBlockNumber - 1); 
                    } 
                } 
             } 
        } 
         
        // copy from local buffer into output buffer 
        // 
 
        // if there are more than the requested bytes, copy and shift 
        // the local data buffer 
        if(cbDataBuffer > cbData) 
        { 
            // copy requested bytes from local buffer into output buffer             
            memcpy(pOutBuffer, pBlock, cbData); 
            cbDataBuffer = (USHORT)(cbDataBuffer - cbData); 
 
            // shift the local buffer accordingly because not all data was used 
            memmove(pBlock, pBlock + cbData, cbDataBuffer); 
            cbData = 0; 
        } 
        else // cbDataBuffer <= cbData 
        { 
            // copy all bytes in local buffer to output buffer 
            memcpy(pOutBuffer, pBlock, cbDataBuffer); 
            cbData -= cbDataBuffer; 
            pOutBuffer += cbDataBuffer; 
            cbDataBuffer = 0; 
        } 
    } 
 
    return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  CalcChksum 
// 
//  This function calculates the checksum of the serial data.  
// 
//  Parameters: 
//      pBuf 
//          [in] Data Buffer.  
// 
//      len 
//          [in] Length of the buffer.  
// 
//  Returns: 
//      Checksum calculated 
//----------------------------------------------------------------------------- 
UCHAR CalcChksum(PUCHAR pBuf, USHORT len) 
{ 
    USHORT s = 0; 
    UCHAR csum = 0; 
 
    for(s = 0; s < len; s++) 
        csum = (UCHAR)(csum + (*(pBuf + s))); 
     
    return csum; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  SerialSendBootRequest 
// 
//  This function sends Boot requests through serial interface.  
// 
//  Parameters: 
//      None 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL SerialSendBootRequest(VOID) 
{ 
    BYTE buffer[sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BOOT_REQUEST)] = {0}; 
    PSERIAL_PACKET_HEADER pHeader = (PSERIAL_PACKET_HEADER)buffer; 
    PSERIAL_BOOT_REQUEST pBootReq = (PSERIAL_BOOT_REQUEST)(buffer + sizeof(SERIAL_PACKET_HEADER)); 
 
    // create boot request 
    PREFAST_SUPPRESS(5425, "Suppressed since it requires coredll.lib which increases the image drastically"); 
    strcpy((CHAR *)pBootReq->PlatformId, (const CHAR *)g_pBSPArgs->deviceId); 
 
    // create header 
    memcpy(pHeader->headerSig, packetHeaderSig, HEADER_SIG_BYTES); 
    pHeader->pktType = KS_PKT_DLREQ; 
    pHeader->payloadSize = sizeof(SERIAL_BOOT_REQUEST); 
    pHeader->crcData = CalcChksum((PBYTE)pBootReq, sizeof(SERIAL_BOOT_REQUEST)); 
    pHeader->crcHdr = CalcChksum((PBYTE)pHeader,  
        sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr)); 
 
	INSREG32BF(&g_pUART->UCR2, UART_UCR2_IRTS, UART_UCR2_IRTS_IGNORERTS);	 
    OEMSerialSendRaw(buffer, sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BOOT_REQUEST)); 
	OUTREG32(&g_pUART->UCR2,  
                INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_IRTS)); 
 
    return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  SerialSendBlockAck 
// 
//  This function sends Boot requests through serial interface.  
// 
//  Parameters: 
//      uBlockNumber 
//           [in] Serial Block data 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL SerialSendBlockAck(DWORD uBlockNumber) 
{ 
    BYTE buffer[sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BLOCK_HEADER)]; 
    PSERIAL_PACKET_HEADER pHeader = (PSERIAL_PACKET_HEADER)buffer; 
    PSERIAL_BLOCK_HEADER pBlockAck = (PSERIAL_BLOCK_HEADER)(buffer + sizeof(SERIAL_PACKET_HEADER)); 
 
    // create block ack 
    pBlockAck->uBlockNum = uBlockNumber; 
 
    // create header 
    memcpy(pHeader->headerSig, packetHeaderSig, HEADER_SIG_BYTES); 
    pHeader->pktType = KS_PKT_DLACK; 
    pHeader->payloadSize = sizeof(SERIAL_BLOCK_HEADER); 
    pHeader->crcData = CalcChksum((PBYTE)pBlockAck, sizeof(SERIAL_BLOCK_HEADER)); 
    pHeader->crcHdr = CalcChksum((PBYTE)pHeader, 
        sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr)); 
 
    OEMSerialSendRaw(buffer, sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BLOCK_HEADER)); 
 
    return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  WaitForBootAck 
// 
//  This function will fail if a boot ack is not received in a timely manner 
//  so that another boot request can be sent 
// 
//  Parameters: 
//      pfJump 
//           [out] TRUE if recvd boot ack 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL WaitForBootAck(BOOL *pfJump) 
{ 
    BOOL fRet = FALSE; 
    USHORT cbBuffer = KITL_MTU; 
    SERIAL_PACKET_HEADER header = {0}; 
    PSERIAL_BOOT_ACK pBootAck = (PSERIAL_BOOT_ACK)g_buffer; 
 
    EdbgOutputDebugString("Waiting for sboot ack...\r\n"); 
    if(RecvPacket(&header, g_buffer, &cbBuffer, FALSE)) 
    { 
        // header checksum already verified 
        if(KS_PKT_DLACK == header.pktType &&  
            sizeof(SERIAL_BOOT_ACK) == header.payloadSize) 
        { 
            EdbgOutputDebugString("Received sboot ack\r\n"); 
            *pfJump = pBootAck->fJumping; 
            fRet = TRUE; 
        } 
    } 
 
    return fRet; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  WaitForBootAck 
// 
//  This function waits indefinitely for jump command 
// 
//  Parameters: 
//      None 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL WaitForJump(VOID) 
{ 
    USHORT cbBuffer = KITL_MTU; 
    SERIAL_PACKET_HEADER header = {0}; 
    PSERIAL_JUMP_REQUEST pJumpReq = (PSERIAL_JUMP_REQUEST)g_buffer; 
 
    // wait indefinitely for a jump request 
    for (;;) 
    { 
        if(RecvPacket(&header, g_buffer, &cbBuffer, TRUE)) 
        { 
            // header & checksum already verified 
            if(KS_PKT_JUMP == header.pktType &&  
                sizeof(SERIAL_JUMP_REQUEST) == header.payloadSize) 
            {  
				if (pJumpReq->dwKitlTransport == KTS_SERIAL) 
					g_pBSPArgs->kitl.devLoc.PhysicalLoc = (PVOID)(BSP_BASE_REG_PA_SERIALKITL); 
 
				if (pJumpReq->dwKitlTransport & KTS_PASSIVE_MODE) 
					g_pBSPArgs->kitl.flags = OAL_KITL_FLAGS_PASSIVE; 
 
                SerialSendBlockAck(0); 
 
				if (pJumpReq->dwKitlTransport == KTS_SERIAL) 
				{ 
					CHAR cLoop = 5; 
					// Keep sending ACK till Platform Builder stops sending JUMP packets 
					// Retry for a maximum of 5 times 
					do  
					{ 
						if ( !((RecvPacket(&header, g_buffer, &cbBuffer, TRUE)) && 
							(KS_PKT_JUMP == header.pktType)) ) 
						{ 
							cLoop = 0; 
						} 
						SerialSendBlockAck(0); 
						cLoop--; 
					} while (cLoop > 0); 
				} 
				else if (pJumpReq->dwKitlTransport == KTS_ETHER) 
				{ 
				        UINT32 EthDevice = InitSpecifiedEthDevice(&g_pBSPArgs->kitl,  ETH_DEVICE_CS8900A); 
				        if (EthDevice == -1) 
				        { 
				            // No device was found ...  
				            // 
				            KITLOutputDebugString("ERROR: Failed to detect and initialize Ethernet controller for KITL.\r\n"); 
				            return FALSE; 
				        } 
						else 
						{ 
							// Make sure MAC address has been programmed. 
							// 
							if (!g_pBSPArgs->kitl.mac[0] && !g_pBSPArgs->kitl.mac[1] && !g_pBSPArgs->kitl.mac[2]) 
							{ 
								KITLOutputDebugString("ERROR: Invalid Ethernet address read from Ethernet controller.\n"); 
								return(FALSE); 
							} 
 
							KITLOutputDebugString("INFO: MAC address: %x-%x-%x-%x-%x-%x\r\n", 
								g_pBSPArgs->kitl.mac[0] & 0x00FF, g_pBSPArgs->kitl.mac[0] >> 8, 
								g_pBSPArgs->kitl.mac[1] & 0x00FF, g_pBSPArgs->kitl.mac[1] >> 8, 
								g_pBSPArgs->kitl.mac[2] & 0x00FF, g_pBSPArgs->kitl.mac[2] >> 8); 
						} 
				} 
                return TRUE; 
            } 
        } 
    } 
 
#if 0 // Remove-W4: Warning C4702 workaround 
    // never reached 
    return FALSE;     
#endif 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  RecvPacket 
// 
//  This function receives serial packet 
// 
//  Parameters: 
//      pHeader 
//          [in] Serial packet header 
// 
//      pbFrame 
//          [in] Serial frame data 
// 
//      pcbFrame 
//          [in] Length of frame 
// 
//      bWaitInfinite 
//          [in] Time to wait in secs 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL RecvPacket(PSERIAL_PACKET_HEADER pHeader, PBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite) 
{ 
    // receive header 
    if(!RecvHeader(pHeader, bWaitInfinite)) 
    { 
        EdbgOutputDebugString("failed to receive header\r\n"); 
        return FALSE; 
    } 
 
    // verify packet checksum 
    if(pHeader->crcHdr != CalcChksum((PBYTE)pHeader,  
        sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr))) 
    { 
        EdbgOutputDebugString("header checksum failure\r\n"); 
        return FALSE; 
    } 
 
    // make sure sufficient buffer is provided 
    if(*pcbFrame < pHeader->payloadSize) 
    { 
        EdbgOutputDebugString("insufficient buffer size; ignoring packet\r\n"); 
        return FALSE; 
    } 
 
    // receive data 
    *pcbFrame = pHeader->payloadSize; 
    if(!OEMSerialRecvRaw(pbFrame, pcbFrame, bWaitInfinite)) 
    { 
        //EdbgOutputDebugString("failed to read packet data\r\n"); 
        return FALSE; 
    } 
 
    // verify data checksum 
    if(pHeader->crcData != CalcChksum(pbFrame, *pcbFrame)) 
    { 
        EdbgOutputDebugString("data checksum failure\r\n"); 
        return FALSE; 
    } 
 
    // verify packet type -- don't return any packet that is not 
    // a type the bootloader expects to receive 
    if(KS_PKT_DLPKT != pHeader->pktType && 
       KS_PKT_DLACK != pHeader->pktType && 
       KS_PKT_JUMP != pHeader->pktType) 
    { 
        EdbgOutputDebugString("received non-download packet type %x\r\n", pHeader->pktType); 
        return FALSE; 
    } 
 
    return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  RecvHeader 
// 
//  This function receives serial header packet 
// 
//  Parameters: 
//      pHeader 
//          [in] Serial packet header 
// 
//      bWaitInfinite 
//          [in] Time to wait in secs 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL RecvHeader(PSERIAL_PACKET_HEADER pHeader, BOOLEAN bWaitInfinite) 
{ 
    USHORT cbRead; 
    UINT i = 0; 
    cbRead = sizeof(UCHAR); 
    // read the header bytes 
    while(i < HEADER_SIG_BYTES) 
    { 
        if(!OEMSerialRecvRaw((PBYTE)&(pHeader->headerSig[i]), &cbRead, bWaitInfinite) || sizeof(UCHAR) != cbRead) 
        { 
            EdbgOutputDebugString("failed to receive header signature\r\n"); 
            return FALSE; 
        } 
 
        if(pHeader->headerSig[i] == packetHeaderSig[i]) 
        { 
            i++; 
        } 
 
        else 
        { 
            i = 0; 
        } 
    } 
 
    // read the remaining header 
    cbRead = sizeof(SERIAL_PACKET_HEADER) - HEADER_SIG_BYTES; 
    if(!OEMSerialRecvRaw((PUCHAR)pHeader + HEADER_SIG_BYTES, &cbRead, bWaitInfinite) || 
        sizeof(SERIAL_PACKET_HEADER) - HEADER_SIG_BYTES != cbRead) 
    { 
        EdbgOutputDebugString("failed to receive header data\r\n"); 
        return FALSE; 
    } 
     
    // verify the header checksum 
    if(pHeader->crcHdr != CalcChksum((PUCHAR)pHeader,  
        sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr))) 
    { 
        EdbgOutputDebugString("header checksum fail\r\n"); 
        return FALSE; 
    } 
 
    return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  OEMSerialRecvRaw 
// 
//  This is platform specific function to receive data 
// 
//  Parameters: 
//      pbFrame 
//          [in] Serial frame data 
// 
//      pcbFrame 
//          [in] Length of frame 
// 
//      bWaitInfinite 
//          [in] Time to wait in secs 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL OEMSerialRecvRaw(LPBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite) 
{ 
	USHORT ct = 0; 
    DWORD tStart = 0; 
#if 0 // Remove-W4: Warning C4189 workaround 
    UCHAR uStatus = 0; 
#endif 
	UINT32 urxd; 
	 
	INSREG32BF(&g_pUART->UCR2, UART_UCR2_IRTS, UART_UCR2_IRTS_IGNORERTS);	 
	INSREG32BF(&g_pUART->UCR2, UART_UCR2_CTS, UART_UCR2_CTS_LOW); 
     
	for(ct = 0; ct < *pcbFrame; ct++) 
    { 
		if (!bWaitInfinite) 
		{ 
			tStart = OEMEthGetSecs(); 
		} 
 
		while (!(INREG32(&g_pUART->USR2) & CSP_BITFMASK(UART_USR2_RDR))) 
        { 
            if(!bWaitInfinite && (OEMEthGetSecs() - tStart > TIMEOUT_RECV)) 
            { 
                *pcbFrame = 0; 
				OUTREG32(&g_pUART->UCR2,  
					INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_CTS)); 
				OUTREG32(&g_pUART->UCR2,  
						INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_IRTS)); 
				 
                return FALSE; 
            }             
        } 
 
		// read char from FIFO 
        urxd = INREG32(&g_pUART->URXD); 
 
        // check and clear comm errors 
        // If error detected in current character 
		if (urxd & UART_RX_ERRORS) 
        { 
            // clear the queue 
            EdbgOutputDebugString("Comm errors have occurred; status = 0x%x\r\n", urxd); 
			OUTREG32(&g_pUART->UCR2,  
					INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_CTS)); 
			OUTREG32(&g_pUART->UCR2,  
						INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_IRTS)); 
			return FALSE; 
        } 
 
        *(pbFrame + ct) = (BYTE)(urxd & 0xFF); 
    } 
 
	OUTREG32(&g_pUART->UCR2,  
            INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_CTS)); 
	OUTREG32(&g_pUART->UCR2,  
                INREG32(&g_pUART->UCR2)&~CSP_BITFMASK(UART_UCR2_IRTS)); 
	 
  return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
//  Function:  OEMSerialSendRaw 
// 
//  This is platform specific function to send data 
// 
//  Parameters: 
//      pbFrame 
//          [in] Serial frame data 
// 
//      pcbFrame 
//          [in] Length of frame 
// 
//  Returns: 
//      TRUE for success/FALSE for failure. 
//----------------------------------------------------------------------------- 
BOOL OEMSerialSendRaw(LPBYTE pbFrame, USHORT cbFrame) 
{ 
	UINT ct; 
 
    // block until send is complete; no timeout 
    for(ct = 0; ct < cbFrame; ct++) 
    {             
        // check that send transmitter holding register is not full 
        while(INREG32(&g_pUART->UTS) & CSP_BITFMASK(UART_UTS_TXFULL)); 
 
        // write character to port 
        OUTREG32(&g_pUART->UTXD, (UCHAR)*(pbFrame+ct)); 
    } 
    return TRUE; 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  ResetDefaultBootCFG 
// 
//  Resets the debug bootloader configuration information (menu settings, etc.). 
// 
//  Parameters: 
//      BootCfg  
//          [out] Points to bootloader configuration that will be filled with 
//          default data.  
// 
//  Returns: 
//      TRUE indicates success. FALSE indicates failure. 
// 
//----------------------------------------------------------------------------- 
void ResetDefaultBootCFG(BOOT_CFG *pBootCFG) 
{ 
#ifdef DEBUG // Remove-W4: Warning C4189 workaround 
    BOOT_CFG BootCfg = {0}; 
#endif 
 
    KITLOutputDebugString("\r\nResetting factory default configuration...\r\n"); 
 
    pBootCFG->autoDownloadImage			= BOOT_CFG_AUTODOWNLOAD_NONE; 
    pBootCFG->dwLaunchAddr				= (DWORD)OALPAtoCA(IMAGE_BOOT_NKIMAGE_RAM_PA_START); 
    pBootCFG->dwPhysStart				= 0; 
    pBootCFG->dwPhysLen					= 0; 
    pBootCFG->mac[0]					= 0x0000; 
    pBootCFG->mac[1]					= 0x0000; 
    pBootCFG->mac[2]					= 0x0000;  
    pBootCFG->ConfigMagicNumber			= SBOOT_CFG_MAGIC_NUMBER; 
	pBootCFG->numBootMe					= 50; 
    pBootCFG->delay						= 3; 
 
	pBootCFG->Channel			= DEFAULT_SBOOT_CHANNEL; 
	pBootCFG->dwSerPhysAddr	= DEFAULT_SBOOT_BASE_REG; 
    pBootCFG->BaudRate			= DEFAULT_SBOOT_BAUDRATE;  
    pBootCFG->DataBits			= SBOOT_DATABITS_8; 
    pBootCFG->Parity           = SBOOT_PARITY_NONE; 
	pBootCFG->StopBit			= SBOOT_STOPBITS_1; 
	pBootCFG->FlowCtrl			= SBOOT_FLOWCTRL_OFF; 
	 
    // save it back to flash 
    if (!FlashStoreBootCFG((BYTE*) pBootCFG, sizeof(BOOT_CFG)))  
    { 
        KITLOutputDebugString("ERROR: ResetDefaultBootCFG: failed to store configuration to flash.\r\n"); 
    } 
#ifdef DEBUG 
    else 
    { 
        KITLOutputDebugString("INFO: ResetDefaultBootCFG: factory default configuration saved to flash.\r\n"); 
 
        // DEBUG 
        // read it back to verify 
        if (!FlashLoadBootCFG((BYTE*) &BootCfg, sizeof(BOOT_CFG)))  
        { 
            KITLOutputDebugString("WARNING: ResetDefaultBootCFG: failed to load configuration for double check.\r\n"); 
        } 
        else 
        { 
            if (0 != memcmp((const void *)&BootCfg, (const void*)pBootCFG, sizeof(BOOT_CFG))) 
            { 
                KITLOutputDebugString("WARNING: ResetDefaultBootCFG: saved and retrieved data not equal.\r\n"); 
            } 
            else 
            { 
                KITLOutputDebugString("INFO: ResetDefaultBootCFG: factory default configuration verified in flash.\r\n"); 
            } 
        } 
        // END DEBUG 
    } 
#endif     
}