📄 flash.c
字号:
}
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_RESERVED) == 0) break;
block++;
}
OALMSG(OAL_INFO, (L"OEMStartEraseFlash: "
L"There is %d reserved blocks (including %d bad)\r\n", block, badBlocks
));
// Calculate base block
baseSector = (address + g_flash.sectorSize - 1);
baseSector /= (g_flash.sectorSize + sizeof(SectorInfo));
baseBlock = (baseSector + g_flash.sectorsPerBlock - 1)/g_flash.sectorsPerBlock;
OALMSG(OAL_INFO, (L"OEMStartEraseFlash: "
L"DIO image base block %d (sector %d)\r\n", baseBlock, baseSector
));
OALMSG(OAL_INFO, (L"OEMStartEraseFlash: "
L"Base block shifted by %d bad blocks\r\n", badBlocks
));
// Make correction for bad blocks
baseBlock += badBlocks;
// Base block must be above reserved blocks
if (baseBlock < block) {
OALMSG(OAL_ERROR, (L"ERROR: OEMStartEraseFlash: "
L"Image starts before reserved blocks\r\n"
));
goto cleanUp;
}
// Skip blocks
while (block < baseBlock && block < g_flash.blocks) {
// 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++;
baseBlock++;
badBlocks++;
continue;
}
block++;
}
// Check for error
if (block >= g_flash.blocks) goto cleanUp;
// Save base block
g_flash.baseBlock = block;
// Erase all remaining blocks
while (block < g_flash.blocks) {
// If block is bad, we have to offset it
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMStartEraseFlash: "
L"Skip bad block %d\r\n", block
));
block++;
continue;
}
// Erase block
if (!EraseBlock(block)) {
FMD_SetBlockStatus(block, BLOCK_STATUS_BAD);
block++;
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMStartEraseFlash: "
L"Block %d erase failed, mark block as bad\r\n", block
));
continue;
}
// Move to next block
block++;
}
OALMSG(OAL_INFO, (L"OEMStartEraseFlash: "
L"DIO image starts at block %d\r\n", g_flash.baseBlock
));
// We are done
rc = TRUE;
cleanUp:
// Close FMD driver
if (hFMD != NULL) FMD_Deinit(hFMD);
return rc;
}
//------------------------------------------------------------------------------
BOOL ContinueWriteFlashBinDIO(UINT32 address, UINT8 *pData, UINT32 size)
{
BOOL rc = FALSE, ok;
UINT32 count;
SECTOR_ADDR sector;
BLOCK_ID block, checkBlock;
SectorInfo *pSectorInfo;
UINT32 blockSize, sectorSize;
// If flash alread failed, there is nothing more to do
if (g_flash.failure) goto cleanUp;
// First we need to calculate position where to write
sectorSize = g_flash.sectorSize + sizeof(SectorInfo);
blockSize = g_flash.sectorsPerBlock * sectorSize;
block = address/blockSize;
sector = (address - block * blockSize)/sectorSize;
// Shift block by base
block += g_flash.baseBlock;
// We must find all bad block before actual one
checkBlock = g_flash.baseBlock;
while (checkBlock < block && checkBlock < g_flash.blocks) {
if ((FMD_GetBlockStatus(checkBlock) & BLOCK_STATUS_BAD) != 0) {
block++;
}
checkBlock++;
}
// Write record
count = 0;
while (count < size && block < g_flash.blocks) {
// Check for invalid block
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMContinueEraseFlash: "
L"Skip bad block %d\r\n", block
));
block++;
continue;
}
// Write sectors
while (sector < g_flash.sectorsPerBlock && count < size) {
// First we have to check for empty sectors
pSectorInfo = (SectorInfo*)(pData + count + g_flash.sectorSize);
// Don't write empty sector
if (
pSectorInfo->dwReserved1 == 0xFFFFFFFF &&
pSectorInfo->wReserved2 == 0xFFFF &&
pSectorInfo->bOEMReserved == 0xFF
) {
// Move to next sector
count += sectorSize;
sector++;
ok = TRUE;
continue;
}
// Never ever write sector with bad block
if (pSectorInfo->bBadBlock != 0xFF) {
OALMSG(OAL_ERROR, (L"ERROR: EBOOT!OEMContinueEraseFlash: "
L"Incorrect or corrupted DIO BIN file - "
L"bad block flag set\r\n"
));
goto cleanUp;
}
// Write sector
if (!(ok = WriteSector(
block * g_flash.sectorsPerBlock + sector, pData + count,
pSectorInfo
))) break;
// Move to next sector
count += sectorSize;
sector++;
}
// When sector write failed, mark block as bad and move back
if (!ok) {
OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMContinueEraseFlash: "
L"Block %d/sector %d write failed, mark block as bad\r\n",
block, sector
));
// First move back
count -= sector * sectorSize;
// Mark block as bad
FMD_SetBlockStatus(block, BLOCK_STATUS_BAD);
block++;
continue;
}
// We are done with block
sector = 0;
block++;
}
// Before we leave erase buffer
memset(pData, 0xFF, size);
// If we wrote all, we are succesfull
rc = count >= size;
cleanUp:
if (!rc) g_flash.failure = TRUE;
return rc;
}
//------------------------------------------------------------------------------
BOOL FinishFlashBinDIO()
{
// Change boot device to NAND
g_bootCfg.bootDevLoc.IfcType = Internal;
g_bootCfg.bootDevLoc.LogicalLoc = BSP_NAND_REGS_PA + 0x10;
// Done
OALMSG(OAL_INFO, (L"OEMFinishEraseFlash: DIO image written\r\n"));
return !g_flash.failure;
}
//------------------------------------------------------------------------------
BOOL WriteFlashXLDR(UINT32 address, UINT32 size)
{
BOOL rc = FALSE, ok;
HANDLE hFMD = NULL;
ROMHDR *pTOC;
FlashInfo flashInfo;
UINT32 blockSize, sectorSize;
SectorInfo sectorInfo;
BLOCK_ID block;
UINT32 *pInfo, ix, xldrSize, count;
UINT8 *pData;
OALMSG(OAL_INFO, (L"OEMWriteFlash: Writing XLDR image to flash\r\n"));
// Open FMD to access NAND
hFMD = FMD_Init(NULL, NULL, NULL);
if (hFMD == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"FMD_Init call failed!\r\n"
));
goto cleanUp;
}
// Get flash info
if (!FMD_GetInfo(&flashInfo)) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"FMD_GetInfo call failed!\r\n"
));
goto cleanUp;
}
blockSize = flashInfo.dwBytesPerBlock;
sectorSize = flashInfo.wDataBytesPerSector;
if (address == 0) address = IMAGE_XLDR_CODE_PA;
// Get data location
pData = OEMMapMemAddr(address, address);
// Verify that we get CE image.
pInfo = (UINT32*)(pData + ROM_SIGNATURE_OFFSET);
if (*pInfo++ != ROM_SIGNATURE) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"Image Signature not found\r\n"
));
goto cleanUp;
}
// We are on correct location....
pTOC = (ROMHDR*)OEMMapMemAddr(address, (UINT32)*pInfo);
// Let see
DumpTOC(pTOC);
// Verify that this is XLDR image
if (pTOC->numfiles > 0 || pTOC->nummods > 1) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"XLDR image must have only one module and no file\r\n"
));
goto cleanUp;
}
// TODO: Strip module info to minimize XLDR size
xldrSize = pTOC->physlast - pTOC->physfirst - 0x1000;
// Check for maximal XLRD size
if (xldrSize > 0x3ff8) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"XLDR image size 0x%04x doesn't fit to limit 0x4000\r\n", xldrSize
));
goto cleanUp;
}
// First we have to move image 8 bytes forward
memcpy(pData + 8, pData + 0x1000, xldrSize);
// Fill empty space with 0xFFs
memset(
pData + 0x8 + xldrSize, 0xFF,
IMAGE_XLDR_CODE_SIZE - 0x8 - xldrSize
);
// Create XLRD header
pInfo = (UINT32*)pData;
pInfo[0] = xldrSize;
pInfo[1] = IMAGE_XLDR_CODE_PA+0x1000;
// First offset given
block = 0;
count = 0;
while (count < IMAGE_XLDR_CODE_SIZE && block < flashInfo.dwNumBlocks) {
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
// note: XLDR must start in block 0!
// try to recover block 0 even if marked bad, otherwise skip!
if (block != 0)
{
block++;
OALMSG(OAL_INFO, (L"$"));
continue;
}
else
{
OALMSG(OAL_WARN, (L"WARN: OEMWriteFlash: "
L"block 0 marked as bad, try to recover block"));
}
}
// Erase block
if (!EraseBlock(block)) {
FMD_SetBlockStatus(block, BLOCK_STATUS_BAD);
block++;
OALMSG(OAL_INFO, (L"#"));
if (block==0) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"couldn't erase block 0, device may not boot"));
}
continue;
}
// Now write sectors
ix = 0;
ok = TRUE;
while (
ix < flashInfo.wSectorsPerBlock && count < IMAGE_XLDR_CODE_SIZE
) {
// Prepare sector info
memset(§orInfo, 0xFF, sizeof(sectorInfo));
sectorInfo.bOEMReserved &= ~(OEM_BLOCK_READONLY|OEM_BLOCK_RESERVED);
sectorInfo.dwReserved1 = 0;
sectorInfo.wReserved2 = 0;
// Write sector
ok = WriteSector(
block * flashInfo.wSectorsPerBlock + ix, pData + count,
§orInfo
);
// When write fail, break sector write loop
if (!ok) break;
// Move to next sector
count += sectorSize;
ix++;
OALMSG(OAL_INFO, (L"."));
}
// When sector write failed, mark block as bad and move back
if (!ok) {
if (block==0) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"write error in block 0, device may not boot"));
}
// First move back
count -= ix * flashInfo.wDataBytesPerSector;
// Mark block as bad
FMD_SetBlockStatus(block, BLOCK_STATUS_BAD);
block++;
OALMSG(OAL_INFO, (L"%"));
continue;
}
// We are done with block
block++;
}
OALMSG(OAL_INFO, (L"\r\nOEMWriteFlash: XLDR written\r\n"));
// Done
rc = (count >= xldrSize);
cleanUp:
if (hFMD != NULL) FMD_Deinit(hFMD);
return rc;
}
//------------------------------------------------------------------------------
BOOL WriteFlashEBOOT(UINT32 address, UINT32 size)
{
BOOL rc = FALSE, ok = FALSE;
HANDLE hFMD = NULL;
ROMHDR *pTOC;
FlashInfo flashInfo;
UINT32 blockSize, sectorSize;
SectorInfo sectorInfo;
BLOCK_ID block;
UINT32 *pInfo, ix, count;
UINT8 *pData;
OALMSG(OAL_INFO, (L"OEMWriteFlash: Writing EBOOT image to flash\r\n"));
// Open FMD to access NAND
hFMD = FMD_Init(NULL, NULL, NULL);
if (hFMD == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"FMD_Init call failed!\r\n"
));
goto cleanUp;
}
// Get flash info
if (!FMD_GetInfo(&flashInfo)) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"FMD_GetInfo call failed!\r\n"
));
goto cleanUp;
}
blockSize = flashInfo.dwBytesPerBlock;
sectorSize = flashInfo.wDataBytesPerSector;
// Check if image fit
if (size > IMAGE_EBOOT_CODE_SIZE) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"EBOOT image too big (size 0x%08x, maximum size 0x%08x)\r\n",
size, IMAGE_EBOOT_CODE_SIZE
));
goto cleanUp;
}
OALMSG(OAL_INFO, (L"OEMWriteFlash: "
L"Flash has %d blocks, %d bytes/block, %d sectors/block\r\n",
flashInfo.dwNumBlocks, flashInfo.dwBytesPerBlock,
flashInfo.wSectorsPerBlock
));
// Get data location
pData = OEMMapMemAddr(address, address);
// Verify that we get CE image.
pInfo = (UINT32*)(pData + ROM_SIGNATURE_OFFSET);
if (*pInfo++ != ROM_SIGNATURE) {
OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: "
L"Image Signature not found\r\n"
));
goto cleanUp;
}
pInfo++;
// We are on correct location....
pTOC = (ROMHDR*)((UINT32)*pInfo + IMAGE_WINCE_CODE_PA);
// Let see
DumpTOC(pTOC);
// Fill unused space with 0xFF
if (size < IMAGE_EBOOT_CODE_SIZE) memset(
pData + size, 0xFF, IMAGE_EBOOT_CODE_SIZE - size
);
// Skip OMAP2420 boot sector
block = 0;
count = 0;
while (count < IMAGE_XLDR_CODE_SIZE && block < flashInfo.dwNumBlocks) {
if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) {
block++;
OALMSG(OAL_INFO, (L"$"));
continue;
}
count += blockSize;
block++;
}
OALMSG(OAL_INFO, (L"OEMWriteFlash: "
L"EBOOT image starts at block %d\r\n", block
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -