#define BL_HDRSIG_SIZE 7
static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr)
{
BYTE hdr[BL_HDRSIG_SIZE];
DWORD dwRecLen, dwRecChk, dwRecAddr;
BOOL fIsFlash = FALSE;
LPBYTE lpDest = NULL;
int nPkgNum = 0;
BYTE nNumDownloadFiles = 1;
DWORD dwImageStart = 0;
DWORD dwImageLength = 0;
RegionInfo *pCurDownloadFile;
*pdwImageStart = *pdwImageLength = *pdwLaunchAddr = 0;
do
{
// read the 7 byte "magic number"
//
if (!OEMReadData (BL_HDRSIG_SIZE, hdr))
{
EdbgOutputDebugString ("\r\nUnable to read image signature.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// An N000FF packet is manufactured by Platform Builder when we're
// downloading multiple files or when we're downloading a .nb0 file.
//
if (!memcmp (hdr, "N000FF\x0A", BL_HDRSIG_SIZE))
{
// read the packet checksum.
//
if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))
{
EdbgOutputDebugString("\r\nUnable to read download manifest checksum.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// read BIN region descriptions (start address and length).
//
if (!OEMReadData (sizeof (DWORD), (LPBYTE) &g_DownloadManifest.dwNumRegions) ||
!OEMReadData ((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0]))
{
EdbgOutputDebugString("\r\nUnable to read download manifest information.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// verify the packet checksum.
//
if (!VerifyChecksum((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0], dwRecChk))
{
EdbgOutputDebugString ("\r\nDownload manifest packet failed checksum verification.\r\n");
HALT (BLERR_CHECKSUM);
return (FALSE);
}
// Provide the download manifest to the OEM. This gives the OEM the
// opportunity to provide start addresses for the .nb0 files (which
// don't contain placement information like .bin files do).
//
if (g_pOEMMultiBINNotify)
{
g_pOEMMultiBINNotify((PDownloadManifest)&g_DownloadManifest);
}
// look for next download...
nNumDownloadFiles = (BYTE)(g_DownloadManifest.dwNumRegions + 1); // +1 to account for this packet.
continue;
}
// Is this an old X000FF multi-bin packet header? It's no longer supported.
//
else if (!memcmp (hdr, "X000FF\x0A", BL_HDRSIG_SIZE))
{
EdbgOutputDebugString ("ERROR: The X000FF packet is an old-style multi-bin download manifest and it's no longer supported. \
\r\nPlease update your Platform Builder installation in you want to download multiple files.\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
// Is this a standard bin image? Check for the usual bin file signature.
//
else if (!memcmp (hdr, "B000FF\x0A", BL_HDRSIG_SIZE))
{
g_bBINDownload = TRUE;
if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)
|| !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength))
{
EdbgOutputDebugString ("Unable to read image start/length\r\n");
HALT (BLERR_MAGIC);
return (FALSE);
}
}
// If the header signature isn't recognized, we'll assume the
// download file is a raw .nb0 file.
//
else
{
g_bBINDownload = FALSE;
}
// If Platform Builder didn't provide a download manifest (i.e., we're
// only downloading a single .bin file), manufacture a manifest so we
// can notify the OEM.
//
if (!g_DownloadManifest.dwNumRegions)
{
g_DownloadManifest.dwNumRegions = 1;
g_DownloadManifest.Region[0].dwRegionStart = dwImageStart;
g_DownloadManifest.Region[0].dwRegionLength = dwImageLength;
// Provide the download manifest to the OEM.
//
if (g_pOEMMultiBINNotify)
{
g_pOEMMultiBINNotify((PDownloadManifest)&g_DownloadManifest);
}
}
// Locate the current download manifest entry (current download file).
//
pCurDownloadFile = &g_DownloadManifest.Region[g_DownloadManifest.dwNumRegions - nNumDownloadFiles];
// give the OEM a chance to verify memory
if (g_pOEMVerifyMemory && !g_pOEMVerifyMemory (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))
{
EdbgOutputDebugString ("!OEMVERIFYMEMORY: Invalid image\r\n");
HALT (BLERR_OEMVERIFY);
return (FALSE);
}
// check for flash image. Start erasing if it is.
if ((fIsFlash = OEMIsFlashAddr (pCurDownloadFile->dwRegionStart))
&& !OEMStartEraseFlash (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))
{
EdbgOutputDebugString ("Invalid Flash Address/Length\r\n");
HALT (BLERR_FLASHADDR);
return (FALSE);
}
// if we're downloading a binary file, we've already downloaded part of the image when searching
// for a file header. copy what we've read so far to the destination buffer, then finish downloading.
if (!g_bBINDownload)
{
lpDest = OEMMapMemAddr (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart);
memcpy(lpDest, hdr, BL_HDRSIG_SIZE);
// complete the file download...
// read data block
if (!OEMReadData ((pCurDownloadFile->dwRegionLength - BL_HDRSIG_SIZE), (lpDest + BL_HDRSIG_SIZE)))
{
EdbgOutputDebugString ("ERROR: failed when reading raw binary file.\r\n");
HALT (BLERR_CORRUPTED_DATA);
return (FALSE);
}
}
// we're downloading a .bin file - download each .bin record in turn...
else
{
while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr) &&
OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen) &&
OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))
{
// last record of .bin file uses sentinel values for address and checksum.
if (!dwRecAddr && !dwRecChk)
{
break;
}
// map the record address (FLASH data is cached, for example)
lpDest = OEMMapMemAddr (pCurDownloadFile->dwRegionStart, dwRecAddr);
// read data block
if (!OEMReadData (dwRecLen, lpDest))
{
EdbgOutputDebugString ("****** Data record %d corrupted, ABORT!!! ******\r\n", nPkgNum);
HALT (BLERR_CORRUPTED_DATA);
return (FALSE);
}
if (!VerifyChecksum (dwRecLen, lpDest, dwRecChk))
{
EdbgOutputDebugString ("****** Checksum failure on record %d, ABORT!!! ******\r\n", nPkgNum);
HALT (BLERR_CHECKSUM);
return (FALSE);
}
// Look for ROMHDR to compute ROM offset. NOTE: romimage guarantees that the record containing
// the TOC signature and pointer will always come before the record that contains the ROMHDR contents.
//
if (dwRecLen == sizeof(ROMHDR) && (*(LPDWORD) OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE))
{
DWORD dwTempOffset = (dwRecAddr - *(LPDWORD)OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG)));
ROMHDR *pROMHdr = (ROMHDR *)lpDest;
// Check to make sure this record really contains the ROMHDR.
//
if ((pROMHdr->physfirst == (pCurDownloadFile->dwRegionStart - dwTempOffset)) &&
(pROMHdr->physlast == (pCurDownloadFile->dwRegionStart - dwTempOffset + pCurDownloadFile->dwRegionLength)) &&
(DWORD)(HIWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast) &&
(DWORD)(LOWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast))
{
g_dwROMOffset = dwTempOffset;
EdbgOutputDebugString("rom_offset=0x%x.\r\n", g_dwROMOffset);
}
}
// verify partial checksum
OEMShowProgress (nPkgNum ++);
if (fIsFlash)
{
OEMContinueEraseFlash ();
}
}
}
// The image start address and length are passed back to the OEM code (OEMLaunch)
// in the following circumstances:
// 1. The file is a raw .nb0 file.
// 2. The file is a .bin file with a TOC that contains the kernel executable.
// 3. The file is a .bin file without a TOC.
//
// If the image is a .bin file with a TOC that doesn't contain the kernel exectuable,
// then it's a multi-xip/mulit-bin image for a non-kernel region and we don't pass
// the start address and length back to the OEM code. OEMLaunch can then save the
// start address and length with the assurance that if the values are non-zero, they
// represent the values for the NK region.
//
if (g_bBINDownload)
{
// Does this .bin file contain a TOC?
if (*(UINT32 *)(pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)
{
// Contain the kernel?
if (IsKernelRegion(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))
{
*pdwImageStart = pCurDownloadFile->dwRegionStart;
*pdwImageLength = pCurDownloadFile->dwRegionLength;
*pdwLaunchAddr = dwRecLen;
}
}
// No TOC - not made by romimage. However, if we're downloading more than one
// .bin file, it's probably chain.bin which doesn't have a TOC (and which isn't
// going to be downloaded on its own) and we should ignore it.
//
else if (g_DownloadManifest.dwNumRegions == 1)
{
*pdwImageStart = pCurDownloadFile->dwRegionStart;
*pdwImageLength = pCurDownloadFile->dwRegionLength;
*pdwLaunchAddr = dwRecLen;
}
}
else // Raw binary file.
{
*pdwImageStart = pCurDownloadFile->dwRegionStart;
*pdwLaunchAddr = pCurDownloadFile->dwRegionStart;
*pdwImageLength = pCurDownloadFile->dwRegionLength;
}
// write to flash if it's flash image
if (fIsFlash)
{
// finish the flash erase
if (!OEMFinishEraseFlash ())
{
HALT (BLERR_FLASH_ERASE);
return (FALSE);
}
// Before writing the image to flash, optionally check the image signature.
if (g_bBINDownload && g_pOEMCheckSignature)
{
if (!g_pOEMCheckSignature(pCurDownloadFile->dwRegionStart, g_dwROMOffset, *pdwLaunchAddr, TRUE))
HALT(BLERR_CAT_SIGNATURE);
}
}
}
while (--nNumDownloadFiles);
if (fIsFlash)
{
nNumDownloadFiles = (BYTE)g_DownloadManifest.dwNumRegions;
while (nNumDownloadFiles--)
{
if (!OEMWriteFlash (g_DownloadManifest.Region[nNumDownloadFiles].dwRegionStart, g_DownloadManifest.Region[nNumDownloadFiles].dwRegionLength))
{
HALT (BLERR_FLASH_WRITE);
return (FALSE);
}
}
}
return (TRUE);
}
|