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

📄 flash.c

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