📄 flash.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
// File: flash.c
//
// This file implements boot loader functions related to image flash.
//
#include <eboot.h>
#include <bsp_nand_cfg.h>
//------------------------------------------------------------------------------
// Local Functions
static UINT32 ReadFlashIPL();
static UINT32 ReadFlashBINFS();
static UINT32 ReadFlashNK();
static BOOL StartWriteFlashBinDIO(UINT32 address, UINT32 size);
static BOOL ContinueWriteFlashBinDIO(UINT32 address, UINT8 *pData, UINT32 size);
static BOOL FinishFlashBinDIO();
static BOOL WriteFlashXLDR(UINT32 address, UINT32 size);
static BOOL WriteFlashEBOOT(UINT32 address, UINT32 size);
static BOOL WriteFlashIPL(UINT32 address, UINT32 size);
static BOOL WriteFlashBINFS(UINT32 address, UINT32 size);
static BOOL WriteFlashNK(UINT32 address, UINT32 size);
static BOOL WriteSector(SECTOR_ADDR sector, VOID *pBuffer, SectorInfo *pInfo);
static BOOL EraseBlock(BLOCK_ID block);
static VOID DumpTOC(ROMHDR *pTOC);
//------------------------------------------------------------------------------
// Local Variables
struct {
UINT32 sectorSize;
UINT32 sectorsPerBlock;
UINT32 blockSize;
UINT32 blocks;
BLOCK_ID baseBlock;
BOOL failure;
} g_flash;
//------------------------------------------------------------------------------
//
// Function: BLFlashDownload
//
// This function download image from flash memory to RAM.
//
UINT32 BLFlashDownload(BOOT_CFG *pConfig, OAL_KITL_DEVICE *pBootDevices)
{
UINT32 rc = BL_ERROR;
// We have do device initialization for some devices
switch (pConfig->bootDevLoc.IfcType) {
case Internal:
switch (pConfig->bootDevLoc.LogicalLoc) {
case BSP_NAND_REGS_PA + 0x10:
rc = ReadFlashIPL();
break;
case BSP_NAND_REGS_PA + 0x20:
rc = ReadFlashNK();
break;
}
break;
}
return rc;
}
//------------------------------------------------------------------------------
static UINT32 ReadFlashIPL()
{
UINT32 rc = BL_ERROR;
HANDLE hFMD = NULL;
FlashInfo flashInfo;
UINT32 offset;
SectorInfo sectorInfo;
SECTOR_ADDR sector, ix;
BLOCK_ID block;
UINT8 *pImage;
UINT32 *pInfo;
// Check if there is a valid image
OALMSG(OAL_INFO, (L"\r\nLoad IPL Image from flash memory\r\n"));
// Open FMD to access NAND
hFMD = FMD_Init(NULL, NULL, NULL);
if (hFMD == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
L"FMD_Init call failed\r\n"
));
goto cleanUp;
}
// Get flash info
if (!FMD_GetInfo(&flashInfo)) {
OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
L"FMD_GetInfo call failed\r\n"
));
goto cleanUp;
}
// Start from NAND start
block = 0;
sector = 0;
// First skip XLDR and EBOOT sectors.
// Documentation doesn't tell what should happen when there is bad block
// in boot sector. So guess and skip block with bad status.
offset = 0;
while (offset < IMAGE_XLDR_CODE_SIZE + IMAGE_EBOOT_CODE_SIZE) {
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) == 0) {
offset += flashInfo.dwBytesPerBlock;
}
block++;
sector += flashInfo.wSectorsPerBlock;
}
// Set address where to place image
pImage = (UINT8*)IMAGE_IPL_CODE_PA;
// Read image to memory
offset = 0;
while (offset < IMAGE_IPL_CODE_SIZE && block < flashInfo.dwNumBlocks) {
// Skip bad blocks
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
block++;
sector += flashInfo.wSectorsPerBlock;
OALMSG(OAL_INFO, (L"#"));
continue;
}
// Read sectors in block
ix = 0;
while (
ix < flashInfo.wSectorsPerBlock && offset < IMAGE_IPL_CODE_SIZE
) {
// When block read fail, there isn't what we can do more
if (!FMD_ReadSector(sector, pImage, §orInfo, 1)) {
OALMSG(OAL_ERROR, (L"\r\nERROR: BLFlashDownload: "
L"Failed read sector %d from flash\r\n", sector
));
goto cleanUp;
}
// Move to next sector
sector++;
pImage += flashInfo.wDataBytesPerSector;
offset += flashInfo.wDataBytesPerSector;
OALMSG(OAL_INFO, (L"."));
}
// Move to next block
block++;
}
OALMSG(OAL_INFO, (L"\r\n"));
// Check if IPL is image and dump its content
pInfo = (UINT32*)(IMAGE_IPL_CODE_PA + ROM_SIGNATURE_OFFSET);
if (*pInfo != ROM_SIGNATURE) {
OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
L"IPL image doesn't have ROM signature at 0x%08x\r\n", pInfo
));
goto cleanUp;
}
// Dump TOC
DumpTOC((ROMHDR*)pInfo[1]);
g_eboot.launchAddress = IMAGE_IPL_CODE_PA;
rc = BL_JUMP;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
static UINT32 ReadFlashNK()
{
UINT32 rc = BL_ERROR;
HANDLE hFMD = NULL;
FlashInfo flashInfo;
ROMHDR *pTOC;
UINT32 offset, size, toc;
UINT32 blockSize, sectorSize, sectorsPerBlock;
SectorInfo sectorInfo;
SECTOR_ADDR sector;
BLOCK_ID block;
UINT8 *pImage;
UINT32 *pInfo;
// Check if there is a valid image
OALMSG(OAL_INFO, (L"\r\nLoad NK image from flash memory\r\n"));
// Open FMD to access NAND
hFMD = FMD_Init(NULL, NULL, NULL);
if (hFMD == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
L"FMD_Init call failed\r\n"
));
goto cleanUp;
}
// Get flash info
if (!FMD_GetInfo(&flashInfo)) {
OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
L"FMD_GetInfo call failed\r\n"
));
goto cleanUp;
}
// Make block & sector size ready
blockSize = flashInfo.dwBytesPerBlock;
sectorSize = flashInfo.wDataBytesPerSector;
sectorsPerBlock = flashInfo.wSectorsPerBlock;
// Skip reserved blocks
block = 0;
while (block < flashInfo.dwNumBlocks) {
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: "
L"Skip bad block %d\r\n", block
));
block++;
continue;
}
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_RESERVED) == 0) break;
block++;
}
// Set address where to place image
pImage = (UINT8*)IMAGE_WINCE_CODE_PA;
size = IMAGE_WINCE_CODE_SIZE;
// Read image to memory
offset = 0;
toc = 0;
pTOC = NULL;
while (offset < size && block < flashInfo.dwNumBlocks) {
// Skip bad blocks
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
block++;
sector += flashInfo.wSectorsPerBlock;
continue;
}
// Read sectors in block
sector = 0;
while (sector < sectorsPerBlock && offset < size) {
// When block read fail, there isn't what we can do more
if (!FMD_ReadSector(
block * sectorsPerBlock + sector, pImage + offset,
§orInfo, 1
)) {
OALMSG(OAL_ERROR, (L"\r\nERROR: BLFlashDownload: "
L"Failed read sector %d from flash\r\n", sector
));
goto cleanUp;
}
// Move to next sector
sector++;
offset += sectorSize;
// Check for TOC
if (toc == 0 && offset >= ROM_TOC_OFFSET_OFFSET + sizeof(DWORD)) {
// Verify that we get CE image.
pInfo = (UINT32*)(pImage + ROM_SIGNATURE_OFFSET);
if (*pInfo != ROM_SIGNATURE) {
OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
L"Image Signature not found\r\n"
));
goto cleanUp;
}
toc = pInfo[2];
} else if (pTOC == NULL && offset >= toc + sizeof(ROMHDR) && offset >= toc) {
pTOC = (ROMHDR*)(pImage + toc);
DumpTOC(pTOC);
size = pTOC->physlast - pTOC->physfirst;
}
}
// Move to next block
block++;
}
g_eboot.launchAddress = IMAGE_WINCE_CODE_PA;
rc = BL_JUMP;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OEMStartEraseFlash
//
// This function is called by the bootloader to initiate the flash memory
// erasing process.
//
BOOL OEMStartEraseFlash(ULONG address, ULONG size)
{
BOOL rc = TRUE;
switch (g_eboot.type) {
case DOWNLOAD_TYPE_BINDIO:
rc = StartWriteFlashBinDIO(address, size);
break;
}
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OEMContinueEraseFlash
//
// This function is called by the bootloader to during download to provide
// ability to continue the flash block erasing operation.
//
VOID OEMContinueEraseFlash()
{
switch (g_eboot.type) {
case DOWNLOAD_TYPE_BINDIO:
ContinueWriteFlashBinDIO(
g_eboot.recordOffset, g_eboot.pReadBuffer, g_eboot.readSize
);
break;
}
}
//------------------------------------------------------------------------------
//
// Function: OEMFinishEraseFlash
//
// This function is called by the bootloader to finish flash erase before
// it will call OEMWriteFlash.
//
// On OMAP2420 we erase flash as part of OEMWriteFlash.
//
BOOL OEMFinishEraseFlash()
{
BOOL rc = TRUE;
switch (g_eboot.type) {
case DOWNLOAD_TYPE_BINDIO:
rc = FinishFlashBinDIO();
break;
}
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OEMWriteFlash
//
// This function is called by the bootloader to write the image that may
// be stored in a RAM file cache area to flash memory. This function is
// called once per each downloaded region.
//
BOOL OEMWriteFlash(ULONG address, ULONG size)
{
BOOL rc;
switch (g_eboot.type) {
case DOWNLOAD_TYPE_BINDIO:
rc = TRUE;
break;
case DOWNLOAD_TYPE_XLDR:
rc = WriteFlashXLDR(address, size);
break;
case DOWNLOAD_TYPE_EBOOT:
rc = WriteFlashEBOOT(address, size);
break;
case DOWNLOAD_TYPE_IPL:
rc = WriteFlashIPL(address, size);
break;
case DOWNLOAD_TYPE_FLASHRAM:
rc = WriteFlashNK(address, size);
break;
default:
rc = FALSE;
}
return rc;
}
//------------------------------------------------------------------------------
BOOL StartWriteFlashBinDIO(UINT32 address, UINT32 size)
{
BOOL rc = FALSE;
HANDLE hFMD = NULL;
FlashInfo flashInfo;
BLOCK_ID block, badBlocks, baseBlock;
SECTOR_ADDR baseSector;
UINT32 count;
// Open FMD to access NAND
hFMD = FMD_Init(NULL, NULL, NULL);
if (hFMD == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: EBOOT!OEMStartEraseFlash: "
L"FMD_Init call failed!\r\n"
));
goto cleanUp;
}
// Get & save flash info
if (!FMD_GetInfo(&flashInfo)) {
OALMSG(OAL_ERROR, (L"ERROR: EBOOT!OEMStartEraseFlash: "
L"FMD_GetInfo call failed!\r\n"
));
goto cleanUp;
}
g_flash.sectorSize = flashInfo.wDataBytesPerSector;
g_flash.sectorsPerBlock = flashInfo.wSectorsPerBlock;
g_flash.blockSize = flashInfo.dwBytesPerBlock;
g_flash.blocks = flashInfo.dwNumBlocks;
g_flash.failure = FALSE;
badBlocks = 0;
OALMSG(OAL_INFO, (L"OEMStartEraseFlash: "
L"Flash has %d blocks, %d bytes/block, %d sectors/block\r\n",
flashInfo.dwNumBlocks, flashInfo.dwBytesPerBlock,
flashInfo.wSectorsPerBlock
));
// Skip OMAP2420 boot sector and EBOOT or IPL image
block = 0;
count = 0;
while (
count < IMAGE_XLDR_CODE_SIZE + IMAGE_EBOOT_CODE_SIZE &&
block < flashInfo.dwNumBlocks
) {
// Skip bad block
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMStartEraseFlash: "
L"Skip bad block %d\r\n", block
));
block++;
badBlocks++;
continue;
}
// All blocks in boot sector and EBOOT/IPL must be reserved
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_RESERVED) == 0) {
OALMSG(OAL_ERROR, (L"ERROR: EBOOT!OEMStartEraseFlash: "
L"Block %d not marked as bad or reserved\r\n", block
));
OALMSG(OAL_ERROR, (L"ERROR: EBOOT!OEMStartEraseFlash: "
L"flash XLDR and EBOOT/IPL, then try again\r\n"
));
goto cleanUp;
}
count += flashInfo.dwBytesPerBlock;
block++;
}
// Skip remaining reserved blocks
while (block < flashInfo.dwNumBlocks) {
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMStartEraseFlash: "
L"Skip bad block %d\r\n", block
));
block++;
badBlocks++;
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -