?? 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 <bsp.h>
#include <loader.h>
#include <debugserial.h>
//-----------------------------------------------------------------------------
// 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 <pshpack1.h>
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 <poppack.h>
// 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));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -