fmd.cpp

来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C++ 代码 · 共 840 行 · 第 1/3 页

CPP
840
字号
}


//
// Store TOC to Nand
// BUGBUG: only uses 1 sector for now.
//
BOOL TOC_Write(void)
{
    SectorInfo si, si2;

    EdbgOutputDebugString("+TOC_Write\r\n");

    if ( !g_bBootMediaExist ) {
        EdbgOutputDebugString("TOC_Write WARN: no boot media\r\n");
        return FALSE;
    }

    // is it a valid TOC?
    if ( !VALID_TOC(g_pTOC) ) {
        EdbgOutputDebugString("TOC_Write ERROR: INVALID_TOC Signature: 0x%x\r\n", g_pTOC->dwSignature);
        return FALSE;
    }

    // is it a valid image descriptor?
    if ( !VALID_IMAGE_DESCRIPTOR(&g_pTOC->id[g_dwTocEntry]) ) {
        EdbgOutputDebugString("TOC_Write ERROR: INVALID_IMAGE[%u] Signature: 0x%x\r\n",
            g_dwTocEntry, g_pTOC->id[g_dwTocEntry].dwSignature);
        return FALSE;
    }

    // in order to write a sector we must erase the entire block first
// !! BUGBUG: must cache the TOC first so we don't trash other image descriptors !!
//    RETAILMSG(1, (TEXT("Erasing Block: %u\r\n"), TOC_BLOCK));
    if ( !FMD_EraseBlock(TOC_BLOCK) ) {
        RETAILMSG(1, (TEXT("TOC_Write ERROR: EraseBlock[%d] \r\n"), TOC_BLOCK));
        return FALSE;
    }

    // setup our metadata so filesys won't stomp us
    si.dwReserved1 = 0;
    si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
    si.bBadBlock = BADBLOCKMARK;
    si.wReserved2 = 0;

    // write the sector & metadata
//    RETAILMSG(1, (TEXT("FMD_WriteSector............. \r\n")));
    if ( !FMD_WriteSector(TOC_SECTOR, (PUCHAR)&g_TOC, &si, 1) ) {
        EdbgOutputDebugString("TOC_Write ERROR: Unable to save TOC\r\n");
        return FALSE;
    }

    // read it back & verify both data & metadata
//    RETAILMSG(1, (TEXT("FMD_ReadSector............. \r\n")));
    if ( !FMD_ReadSector(TOC_SECTOR, (PUCHAR)&toc, &si2, 1) ) {
        EdbgOutputDebugString("TOC_Write ERROR: Unable to read/verify TOC\r\n");
        return FALSE;
    }

//    RETAILMSG(1, (TEXT("memcmp............. \r\n")));
    if ( 0 != memcmp(&g_TOC, &toc, SECTOR_SIZE) ) {
        EdbgOutputDebugString("TOC_Write ERROR: TOC verify failed\r\n");
        return FALSE;
    }

    if ( 0 != memcmp(&si, &si2, sizeof(si)) ) {
        EdbgOutputDebugString("TOC_Write ERROR: SectorInfo verify failed: %x %x %x %x\r\n",
            si.dwReserved1, si.bOEMReserved, si.bBadBlock, si.wReserved2);
        return FALSE;
    }

//	TOC_Print();

    EdbgOutputDebugString("-TOC_Write\r\n");
    return TRUE;
}


/*
    @func   PVOID | GetKernelExtPointer | Locates the kernel region's extension area pointer.
    @rdesc  Pointer to the kernel's extension area.
    @comm
    @xref
*/
PVOID GetKernelExtPointer(DWORD dwRegionStart, DWORD dwRegionLength)
{
    DWORD dwCacheAddress = 0;
    ROMHDR *pROMHeader;
    DWORD dwNumModules = 0;
    TOCentry *pTOC;

    if (dwRegionStart == 0 || dwRegionLength == 0)
        return(NULL);

    if (*(LPDWORD) OEMMapMemAddr(dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET) != ROM_SIGNATURE)
        return NULL;

    // A pointer to the ROMHDR structure lives just past the ROM_SIGNATURE (which is a longword value).  Note that
    // this pointer is remapped since it might be a flash address (image destined for flash), but is actually cached
    // in RAM.
    //
    dwCacheAddress = *(LPDWORD) OEMMapMemAddr(dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
    pROMHeader     = (ROMHDR *) OEMMapMemAddr(dwRegionStart, dwCacheAddress);

    // Make sure there are some modules in the table of contents.
    //
    if ((dwNumModules = pROMHeader->nummods) == 0)
        return NULL;

    // Locate the table of contents and search for the kernel executable and the TOC immediately follows the ROMHDR.
    //
    pTOC = (TOCentry *)(pROMHeader + 1);

    while (dwNumModules--) {
        LPBYTE pFileName = OEMMapMemAddr(dwRegionStart, (DWORD)pTOC->lpszFileName);
        // EdbgOutputDebugString("GetKernelExtPointer: found module[%u]: %s\r\n", dwNumModules, pFileName);
        if (!strcmp((const char *)pFileName, "nk.exe")) {
            return ((PVOID)(pROMHeader->pExtensions));
        }
        ++pTOC;
    }

    return NULL;
}


/*
    @func   BOOL | WriteRegionsToBootMedia | Stores the image cached in RAM to the Boot Media.
    The image may be comprised of one or more BIN regions.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL WriteRegionsToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr)
{
    BYTE nCount;
    DWORD dwNumExts;
    PXIPCHAIN_SUMMARY pChainInfo = NULL;
    EXTENSION *pExt = NULL;
    DWORD dwBINFSPartLength = 0;
    HANDLE hPart, hPartEx;
    DWORD dwStoreOffset;
    DWORD dwMaxRegionLength[BL_MAX_BIN_REGIONS] = {0};
    DWORD dwChainStart, dwChainLength;

    //  Initialize the variables
    dwChainStart = dwChainLength = 0;

    EdbgOutputDebugString("+WriteRegionsToBootMedia: ImageStart: 0x%x, ImageLength: 0x%x, LaunchAddr:0x%x\r\n",
                            dwImageStart, dwImageLength, dwLaunchAddr);

    if ( !g_bBootMediaExist ) {
        EdbgOutputDebugString("ERROR: WriteRegionsToBootMedia: device doesn't exist.\r\n");
        return(FALSE);
    }

    if ( !VALID_TOC(g_pTOC) ) {
        EdbgOutputDebugString("WARN: WriteRegionsToBootMedia: INVALID_TOC\r\n");
        if ( !TOC_Init(g_dwTocEntry, g_ImageType, dwImageStart, dwImageLength, dwLaunchAddr) ) {
            EdbgOutputDebugString("ERROR: INVALID_TOC\r\n");
            return(FALSE);
        }
    }

    if ( !(IMAGE_TYPE_BINFS & g_pTOC->id[g_dwTocEntry].dwImageType) ) {
        EdbgOutputDebugString("ERROR: WriteRegionsToBootMedia: INVALID_IMAGE_TYPE: 0x%x\r\n",
            g_pTOC->id[g_dwTocEntry].dwImageType);
        return(FALSE);
    }

    // Look in the kernel region's extension area for a multi-BIN extension descriptor.
    // This region, if found, details the number, start, and size of each BIN region.
    //
    //for (nCount = 0, dwNumExts = 0 ; (nCount < g_BINRegionInfo.dwNumRegions) && !pChainInfo ; nCount++)
    for (nCount = 0, dwNumExts = 0 ; (nCount < g_BINRegionInfo.dwNumRegions); nCount++)
    {
        // Does this region contain nk.exe and an extension pointer?
        //
        pExt = (EXTENSION *)GetKernelExtPointer(g_BINRegionInfo.Region[nCount].dwRegionStart,
                                                g_BINRegionInfo.Region[nCount].dwRegionLength );
        if ( pExt != NULL)
        {
            // If there is an extension pointer region, walk it until the end.
            //
            while (pExt)
            {
                DWORD dwBaseAddr = g_BINRegionInfo.Region[nCount].dwRegionStart;
                pExt = (EXTENSION *)OEMMapMemAddr(dwBaseAddr, (DWORD)pExt);
                EdbgOutputDebugString("INFO: OEMLaunch: Found chain extenstion: '%s' @ 0x%x\r\n", pExt->name, dwBaseAddr);
                if ((pExt->type == 0) && !strcmp(pExt->name, "chain information"))
                {
                    pChainInfo = (PXIPCHAIN_SUMMARY) OEMMapMemAddr(dwBaseAddr, (DWORD)pExt->pdata);
                    dwNumExts = (pExt->length / sizeof(XIPCHAIN_SUMMARY));
                    EdbgOutputDebugString("INFO: OEMLaunch: Found 'chain information' (pChainInfo=0x%x  Extensions=0x%x).\r\n", (DWORD)pChainInfo, dwNumExts);
                    break;
                }
                pExt = (EXTENSION *)pExt->pNextExt;
            }
        }
        else {
            //  Search for Chain region. Chain region doesn't have the ROMSIGNATURE set
            DWORD   dwRegionStart = g_BINRegionInfo.Region[nCount].dwRegionStart;
            DWORD   dwSig = *(LPDWORD) OEMMapMemAddr(dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET);

            if ( dwSig != ROM_SIGNATURE) {
                //  It is the chain
                dwChainStart = dwRegionStart;
                dwChainLength = g_BINRegionInfo.Region[nCount].dwRegionLength;
                EdbgOutputDebugString("Found the Chain region: StartAddress: 0x%X; Length: 0x%X\n", dwChainStart, dwChainLength);
            }
        }
    }

    // Determine how big the Total BINFS partition needs to be to store all of this.
    //
    if (pChainInfo && dwNumExts == g_BINRegionInfo.dwNumRegions)    // We're downloading all the regions in a multi-region image...
    {
        DWORD i;
        EdbgOutputDebugString("Writing multi-regions\r\n");

        for (nCount = 0, dwBINFSPartLength = 0 ; nCount < dwNumExts ; nCount++)
        {
            dwBINFSPartLength += (pChainInfo + nCount)->dwMaxLength;
            EdbgOutputDebugString("BINFSPartMaxLength[%u]: 0x%x, TtlBINFSPartLength: 0x%x \r\n",
                nCount, (pChainInfo + nCount)->dwMaxLength, dwBINFSPartLength);

            // MultiBINInfo does not store each Regions MAX length, and pChainInfo is not in any particular order.
            // So, walk our MultiBINInfo matching up pChainInfo to find each regions MAX Length
            for (i = 0; i < dwNumExts; i++) {
                if ( g_BINRegionInfo.Region[i].dwRegionStart == (DWORD)((pChainInfo + nCount)->pvAddr) ) {
                    dwMaxRegionLength[i] = (pChainInfo + nCount)->dwMaxLength;
                    EdbgOutputDebugString("dwMaxRegionLength[%u]: 0x%x \r\n", i, dwMaxRegionLength[i]);
                    break;
                }
            }
        }

    }
    else    // A single BIN file or potentially a multi-region update (but the partition's already been created in this latter case).
    {
        dwBINFSPartLength = g_BINRegionInfo.Region[0].dwRegionLength;
        EdbgOutputDebugString("Writing single region/multi-region update, dwBINFSPartLength: %u \r\n", dwBINFSPartLength);
    }

    // Open/Create the BINFS partition where images are stored.  This partition starts immediately after the MBR on the Boot Media and its length is
    // determined by the maximum image size (or sum of all maximum sizes in a multi-region design).
    // Parameters are LOGICAL sectors.
    //
/*    hPart = BP_OpenPartition( NEXT_FREE_LOC,
                              FILE_TO_SECTOR_SIZE(dwBINFSPartLength) + 1, // sizeof image + MBR sector
                              PART_BINFS,
                              TRUE,
                              PART_OPEN_ALWAYS);
*/

    hPart = BP_OpenPartition( (IMAGE_START_BLOCK+1)*PAGES_PER_BLOCK,	// next block of MBR
                              SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))*PAGES_PER_BLOCK, // align to block
                              PART_BINFS,
                              TRUE,
                              PART_OPEN_ALWAYS);

    if (hPart == INVALID_HANDLE_VALUE )
    {
        EdbgOutputDebugString("ERROR: WriteRegionsToBootMedia: Failed to open/create BINFS partition.\r\n");
        return(FALSE);
    }

    // Are there multiple BIN files in RAM (we may just be updating one in a multi-BIN solution)?
    //
    for (nCount = 0, dwStoreOffset = 0; nCount < g_BINRegionInfo.dwNumRegions ; nCount++)
    {
        DWORD dwRegionStart  = (DWORD)OEMMapMemAddr(0, g_BINRegionInfo.Region[nCount].dwRegionStart);

        DWORD dwRegionLength = g_BINRegionInfo.Region[nCount].dwRegionLength;

        // Media byte offset where image region is stored.
        dwStoreOffset += nCount ? dwMaxRegionLength[nCount-1] : 0;

        EdbgOutputDebugString("dwRegionStart: 0x%x, dwRegionLength: 0x%x, dwStoreOffset: 0x%x\r\n",
            dwRegionStart, dwRegionLength, dwStoreOffset);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?