⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
        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(&sectorInfo, 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,
                &sectorInfo
            );

            // 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 + -