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

📄 flsnand.cpp

📁 基于WINCE的文件系统FAL驱动
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        if (IS_VALID_BOOTSEC(g_pFLSBuffer)) 
        {
            if (!g_hookInterface.pReadSector (dwSector+1, g_pFLSBuffer, NULL, 1)) {
                return FALSE;
            }
            if (IS_VALID_FLS(g_pFLSBuffer)) 
            {           
                // Cache the flash layout sector information
                PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer);
                g_dwNumReserved = pFLS->cbReservedEntries / sizeof(ReservedEntry);
                g_dwNumRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);

                // ReservedEntry table starts at the end of the PFlashLayoutSector struct.                
                PReservedEntry pEntry = (PReservedEntry)(pFLS+1);

                if (g_dwNumReserved)
                {
                    // Not enough room in the statically allocated buffer to store reserved table.
                    if (g_dwNumReserved > MAX_RESERVES)
                        return FALSE;

                    memcpy (g_pLogicalReservedTable, pEntry, g_dwNumReserved * sizeof(ReservedEntry));
                }
                
                // FlashRegion table starts after the ReservedEntry table. 
                if (g_dwNumRegions)
                {
                    pRegion = (PFlashRegion)((LPBYTE)pEntry + pFLS->cbReservedEntries); 
                }
            }
            break;
        }
    }

    if (!g_dwNumRegions) 
    {
        g_dwNumRegions = 1;
    }

    // Not enough room in the statically allocated buffer to store region table.
    if (g_dwNumRegions > MAX_REGIONS)
        return FALSE;

    if (pRegion)
    {
        memcpy (g_pRegionTable, pRegion, g_dwNumRegions * sizeof(FlashRegion));
    }
    else
    {
        g_pRegionTable[0].dwStartPhysBlock = 0;
        g_pRegionTable[0].dwNumPhysBlocks = g_flashInfo.dwNumBlocks;
        g_pRegionTable[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;        
        g_pRegionTable[0].dwBytesPerBlock = g_flashInfo.dwBytesPerBlock;
        g_pRegionTable[0].regionType = FILESYS;
        g_pRegionTable[0].dwSectorsPerBlock = g_flashInfo.wSectorsPerBlock;
        g_pRegionTable[0].dwCompactBlocks = DEFAULT_COMPACTION_BLOCKS;    
    }
    
    return TRUE;
}

// --------------------------------------------------------------------
// --------------------------------------------------------------------
// Reserved regions in the FLS are specified as number of logical blocks
// for that region.  We need to translate that to physical start and length 
// ranges, accounting for bad blocks and skipping any blocks that are marked
// reserved through the SectorInfo.  All reserved regions in the FLS are put
// at the beginning of flash
//
static BOOL DefineReserveRegions()
{
    DWORD dwStartPhysBlock = 0;
    DWORD dwCurPhysBlock = 0;    

    // Find the starting physical block.  Blocks marked reserved through the SectorInfo
    // may preceed reserved regions, and are not part of the region.
    while ((dwStartPhysBlock < g_flashInfo.dwNumBlocks) && 
            g_hookInterface.pGetBlockStatus(dwStartPhysBlock) & (BLOCK_STATUS_RESERVED | BLOCK_STATUS_BAD)) 
    {
        dwStartPhysBlock++;
    }
    
    dwCurPhysBlock = dwStartPhysBlock;
    
    for (DWORD i = 0; i < g_dwNumReserved; i++)
    {
        DWORD dwNumLogBlocks = g_pLogicalReservedTable[i].dwNumBlocks;
    
        while (dwNumLogBlocks--) 
        {
            // Determine the physical range of the region, skipping bad blocks
            // Blocks marked reserved through the SectorInfo that are inside
            // the reserved region will be treated as part of the region.
            while ((dwCurPhysBlock < g_flashInfo.dwNumBlocks) && 
                    g_hookInterface.pGetBlockStatus(dwCurPhysBlock) & BLOCK_STATUS_BAD) 
            {
                dwCurPhysBlock++;
            }
            dwCurPhysBlock++;
        }
        
        // Store the physical start and num blocks
        g_pPhysReservedTable[i].dwStartBlock = dwStartPhysBlock;
        g_pPhysReservedTable[i].dwNumBlocks = dwCurPhysBlock - dwStartPhysBlock;
        
        dwStartPhysBlock = dwCurPhysBlock;
    }

    g_dwStartNonResBlock = dwCurPhysBlock;

    return TRUE;
}

// --------------------------------------------------------------------
// --------------------------------------------------------------------
static BOOL ReadWriteReserved (PReservedReq pReq, BOOL fRead)
{

    PCSTR szName = pReq->szName;
    LPBYTE pBuffer = pReq->pBuffer;

    if ((pBuffer = (LPBYTE)MapCallerPtr((LPVOID)(pReq->pBuffer), pReq->dwLen)) == NULL)
    {
        DEBUGMSG(1, (TEXT("ReadWriteReserved() - MapCallerPtr() failed, couldn't obtain pointer to buffer.\r\n")));
        goto Error;
    }

    for (DWORD i = 0; i < g_dwNumReserved; i++)
    {
        if (_strnicmp(szName, g_pLogicalReservedTable[i].szName, RESERVED_NAME_LEN) == 0)
        {
            //
            // Found a region name match
            //
            
            // Verify the request is in the valid range.  pReq->dwStart is the starting byte offset into
            // the region to start reading/writing and pReq->dwLen is number of bytes.  Verify that
            // both are within the size in bytes of the region            
            DWORD dwRegionSize = g_pLogicalReservedTable[i].dwNumBlocks * g_flashInfo.dwBytesPerBlock;
            if ((pReq->dwStart >= dwRegionSize) || (pReq->dwStart + pReq->dwLen > dwRegionSize)) 
            {
                DEBUGMSG(1, (TEXT("ReadWriteReserved: Invalid request.  Start: 0x%x.  Len: 0x%x\r\n"), pReq->dwStart, pReq->dwLen));
                goto Error;
            }
            if (pReq->dwStart % g_flashInfo.wDataBytesPerSector)
            {
                DEBUGMSG(1, (TEXT("ReadWriteReserved: Invalid request.  Start: 0x%x is not sector aligned.\r\n"), pReq->dwStart));
                goto Error;
            }     
            
            if ((DWORD)pBuffer & (sizeof(DWORD) - 1))
            {
                DEBUGMSG(1, (TEXT("ReadWriteReserved: Unaligned pointer 0x%x.\r\n"), pBuffer));
                goto Error;
            }
            
                
            DWORD dwStartBlockOffset = pReq->dwStart / g_flashInfo.dwBytesPerBlock;
            DWORD dwPhysBlock = g_pPhysReservedTable[i].dwStartBlock;
            DWORD dwRemain = pReq->dwLen;
            DWORD dwNumValidBlocks = 0;

            // Find the starting physical block to read/write
            while (dwRemain && dwPhysBlock < g_flashInfo.dwNumBlocks) 
            {
                DWORD dwSectorOffset = 0;
                
                if (IsBlockBad(dwPhysBlock)) 
                {
                    dwPhysBlock++;
                    continue;
                }

                if (dwNumValidBlocks < dwStartBlockOffset)
                {
                    dwPhysBlock++;
                    dwNumValidBlocks++;
                    continue;
                }

                if (!fRead)
                {
                    if (!g_hookInterface.pEraseBlock(dwPhysBlock)) 
                    {
                        DEBUGMSG(1, (TEXT("ReadWriteReserved: FMD_EraseBlock failed 0x%x.\r\n"), dwPhysBlock));
                        goto Error;
                    }
                }

                // If this is the starting block, determine the sector offset
                // into the block to start.
                if (dwNumValidBlocks == dwStartBlockOffset)
                {
                    dwSectorOffset = (pReq->dwStart % g_flashInfo.dwBytesPerBlock) / g_flashInfo.wDataBytesPerSector;
                }

                while (dwSectorOffset < g_flashInfo.wSectorsPerBlock && dwRemain)
                {
                    BYTE abTmpBuffer[MAX_PAGE_SIZE];
                    LPBYTE pTmpBuffer = pBuffer;
                    DWORD dwBytes = g_flashInfo.wDataBytesPerSector;
                    DWORD dwSector = dwPhysBlock * g_flashInfo.wSectorsPerBlock + dwSectorOffset;
                    
                    // Double buffer if the remaining bytes do not make up an entire sector
                    if (dwRemain < g_flashInfo.wDataBytesPerSector)
                    {
                        if (!fRead)
                        {
                            memset (abTmpBuffer, 0xff, g_flashInfo.wDataBytesPerSector);
                            memcpy (abTmpBuffer, pBuffer, dwRemain);
                        }
                        pTmpBuffer = abTmpBuffer;
                        dwBytes = dwRemain;
                    }

                    if (fRead)
                    {
                        if (!g_hookInterface.pReadSector (dwSector, pTmpBuffer, NULL, 1))
                        {
                            DEBUGMSG(1, (TEXT("ReadWriteReserved: FMD_ReadSector failed 0x%x.\r\n"), dwSector));
                            goto Error;
                        }
                        if (dwRemain < g_flashInfo.wDataBytesPerSector)
                        {
                            memcpy (pBuffer, abTmpBuffer, dwBytes);
                        }
                    }
                    else
                    {
                        if (!g_hookInterface.pWriteSector (dwSector, pTmpBuffer, NULL, 1))
                        {
                            DEBUGMSG(1, (TEXT("ReadWriteReserved: FMD_WriteSector failed 0x%x.\r\n"), dwSector));
                            goto Error;
                        }
                    }

                    dwRemain -= dwBytes;
                    pBuffer += dwBytes;
                    dwSectorOffset++;
                }
                
                dwPhysBlock++;
                dwNumValidBlocks++;
            }
                       
            return TRUE;

        }
    }

Error:
    return FALSE;    
}

// --------------------------------------------------------------------
// --------------------------------------------------------------------
static BOOL RawWriteBlocks (PRawWriteBlocksReq pReq) 
{
    DWORD dwEndBlock = pReq->dwStartBlock + pReq->dwNumBlocks - 1;
    LPBYTE pBuffer = pReq->pBuffer;

    if (pReq->dwStartBlock >= g_flashInfo.dwNumBlocks|| 
         dwEndBlock >= g_flashInfo.dwNumBlocks ||
         dwEndBlock < pReq->dwStartBlock)
    {
        DEBUGMSG(1, (TEXT("RawWriteBlocks: Invalid request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
        return FALSE;
    }  

    // Size of the buffer must include SectorInfo
    if (pReq->cbBuffer < (pReq->dwNumBlocks * g_flashInfo.wSectorsPerBlock * 
        (g_flashInfo.wDataBytesPerSector + sizeof(SectorInfo))))
    {
        DEBUGMSG(1, (TEXT("RawWriteBlocks: Insufficient buffer: (0x%x)\r\n"), pReq->cbBuffer));
        return FALSE;
    }  

    DWORD dwStartPhysBlock = 0;
    DWORD dwNumLogBlocks = 0;
    
    static DWORD dwLastLogicalBlock = INVALID_BLOCK_ID;
    static DWORD dwLastPhysicalBlock = INVALID_BLOCK_ID;

    if (dwLastLogicalBlock == pReq->dwStartBlock) {

        // Use the cached last block if caller is writing to sequential blocks
        //
        dwStartPhysBlock = dwLastPhysicalBlock;
        
    } else {

        // Find the starting physical block by skipping any bad blocks
        //
        while (dwNumLogBlocks < pReq->dwStartBlock) 
        {
            if (dwStartPhysBlock >= g_flashInfo.dwNumBlocks)    
            {
                DEBUGMSG(1, (TEXT("RawWriteBlocks: Not enough good blocks to complete request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
                return FALSE;
            }  
                
            if (!(g_hookInterface.pGetBlockStatus(dwStartPhysBlock) & BLOCK_STATUS_BAD))
            {
                dwNumLogBlocks++;
            }
            dwStartPhysBlock++;    
        }        
    }

    DWORD dwPhysBlock = dwStartPhysBlock;
    dwNumLogBlocks = pReq->dwNumBlocks;

    // Write out the requested blocks sequentially, skipping any bad blocks.
    //
    while (dwNumLogBlocks)
    {    
        if (dwStartPhysBlock >= g_flashInfo.dwNumBlocks)    
        {
            DEBUGMSG(1, (TEXT("RawWriteBlocks: Not enough good blocks to complete request: (0x%x, 0x%x)\r\n"), pReq->dwStartBlock, pReq->dwNumBlocks));
            return FALSE;
        }  

        if (g_hookInterface.pGetBlockStatus(dwPhysBlock) & BLOCK_STATUS_BAD)
        {
            dwPhysBlock++;
            continue;
        }
    
        if (!WriteBlock (dwPhysBlock, pBuffer))
        {
            DEBUGMSG(1, (TEXT("RawWriteBlocks: WriteBlock failed (0x%x).\r\n"), dwPhysBlock));
            return FALSE;
        }
            
        pBuffer += (g_flashInfo.dwBytesPerBlock + g_flashInfo.wSectorsPerBlock * sizeof(SectorInfo));
        dwPhysBlock++;
        dwNumLogBlocks--;
    }

    dwLastPhysicalBlock = dwPhysBlock;
    dwLastLogicalBlock = pReq->dwStartBlock + pReq->dwNumBlocks;

    return TRUE;
}

// --------------------------------------------------------------------
// --------------------------------------------------------------------
static BOOL WriteBlock (DWORD dwBlock, LPBYTE pBuffer)
{
    DWORD dwStartSector;

    if (!g_hookInterface.pGetInfo(&g_flashInfo)) {
        return FALSE;
    }
    
    dwStartSector = dwBlock * g_flashInfo.wSectorsPerBlock;

    if (!g_hookInterface.pEraseBlock (dwBlock))
    {
        DEBUGMSG(1, (TEXT("WriteBlock: FMD_EraseBlock failed (0x%x).\r\n"), dwBlock));
        return FALSE;
    }

    if (!pBuffer)
    {
        // No buffer to write, simply return success after erasing
        return TRUE;
    }

    // Write out each sector one at a time.  The buffer contains the sector data followed by the
    // SectorInfo for the particular sector. 
    for (DWORD iSector = dwStartSector; iSector < dwStartSector + g_flashInfo.wSectorsPerBlock; iSector++)
    {
        if (!g_hookInterface.pWriteSector (iSector, pBuffer, (PSectorInfo)(pBuffer + g_flashInfo.wDataBytesPerSector), 1)) 
        {
            DEBUGMSG(1, (TEXT("WriteBlock: FMD_WriteSector failed (0x%x).\r\n"), iSector));
            return FALSE;
        }
        pBuffer += (g_flashInfo.wDataBytesPerSector + sizeof(SectorInfo));            
    }
    return TRUE;
}

⌨️ 快捷键说明

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