CE5.0 - eboot加载NK.nb0的详细流程(转)

http://blog.chinaunix.net/u1/38994/showart.php?id=1883739

CE5.0 - eboot加载NK.nb0的详细流程

可以参考《 CE5.0 - eboot烧写NK.nb0的详细流程》

eboot
==>main             PLATFORM/SMDK2440A/Src/Bootloader/Eboot_usb/main.c|96| BootloaderMain(); //应该是这个
==>BootloaderMain   PLATFORM/SMDK2440A/Src/Bootloader/Eboot_usb/blcommon.c|106| if (!OEMPlatformInit ()) //应该是这个
==>OEMPlatformInit  PLATFORM/SMDK2440A/Src/Bootloader/Eboot/main.c|722| if ( !BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL) )
==>if ( !g_bDownloadImage ) {//如果不执行下载,那么执行下面的直接加载nk.nb0操作[luther.gliethttp]
    ...
        switch (g_ImageType) {
            ...
            case IMAGE_TYPE_RAMIMAGE:
                OALMSG(TRUE, (TEXT("OEMPlatformInit: IMAGE_TYPE_RAMIMAGE/r/n")));
                if ( !ReadOSImageFromBootMedia( ) ) //加载kernel
                {
                    OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit ERROR: Failed to load kernel region into RAM./r/n")));
                    return FALSE;
                }
                break;
    ...
    }
来具体看看ReadOSImageFromBootMedia的代码实现[luther.gliethttp]
/*
    @func   BOOL | ReadKernelRegionFromBootMedia |
            BinFS support. Reads the kernel region from Boot Media into RAM.  The kernel region is fixed up
            to run from RAM and this is done just before jumping to the kernel entry point.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL ReadOSImageFromBootMedia()
{
    HANDLE hPart;
    SectorInfo si;
    DWORD     chainaddr, flashaddr;
    DWORD i;

    OALMSG(OAL_FUNC, (TEXT("+ReadOSImageFromBootMedia/r/n")));

    if (!g_bBootMediaExist) //在/PLATFORM/SMDK2440A/Src/Bootloader/Eboot_usb/main.c|706| g_bBootMediaExist = TRUE;中如果BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL)成功,那么true赋值[luther.gliethttp]
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: WriteRawImageToBootMedia: device doesn't exist./r/n")));
        return(FALSE);
    }

    if ( !VALID_TOC(g_pTOC) )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: INVALID_TOC/r/n")));
        return(FALSE);
    }

    if ( !VALID_IMAGE_DESCRIPTOR(&g_pTOC->id[g_dwTocEntry]) ) //在TOC_Read()中执行了g_dwTocEntry = g_pBootCfg->ImageIndex;赋值操作[lutehr.gleithttp]
    {
        OALMSG(OAL_ERROR, (TEXT("ReadOSImageFromBootMedia: ERROR_INVALID_IMAGE_DESCRIPTOR: 0x%x/r/n"),
            g_pTOC->id[g_dwTocEntry].dwSignature));
        return FALSE;
    }

    if ( !OEMVerifyMemory(g_pTOC->id[g_dwTocEntry].dwLoadAddress, sizeof(DWORD)) ||
         !OEMVerifyMemory(g_pTOC->id[g_dwTocEntry].dwJumpAddress, sizeof(DWORD)) ||//最后检查跳转到的虚拟地址同时执行g_ImageType = IMAGE_TYPE_RAMIMAGE;赋值[luther.gliethttp]
         !g_pTOC->id[g_dwTocEntry].dwTtlSectors )
    {
        OALMSG(OAL_ERROR, (TEXT("ReadOSImageFromBootMedia: ERROR_INVALID_ADDRESS: (address=0x%x, sectors=0x%x, launch address=0x%x).../r/n"),
            g_pTOC->id[g_dwTocEntry].dwLoadAddress, g_pTOC->id[g_dwTocEntry].dwTtlSectors, g_pTOC->id[g_dwTocEntry].dwJumpAddress));
        return FALSE;
    }

    // Open the BINFS partition (it must exist).
    //
    hPart = BP_OpenPartition( NEXT_FREE_LOC,
                              USE_REMAINING_SPACE,
                              PART_BINFS,
                              TRUE,
                              PART_OPEN_EXISTING);
//因为在WriteOSImageToBootMedia()时,执行如下语句,创建PART_BINFS分区[luther.gliethttp]
/*  //为nk.nb0建立主分区,管理(IMAGE_START_BLOCK+1)*PAGES_PER_BLOCK开始的扇区,管理大小为SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))*PAGES_PER_BLOCK
    //将该分区所有信息登记到了MBR中,hPart为申请到的主分区表指针[luther.gliethttp]
    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 )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to open existing partition./r/n")));
        return(FALSE);
    }

    // Set the partition file pointer to the correct offset for the kernel region.
    //
    //因为在WriteOSImageToBootMedia()时,执行如下语句,
    //g_pTOC->id[g_dwTocEntry].dwStoreOffset = dwStoreOffset;//对期望Toc进行写操作,那么保存它的存储逻辑地址(以字节为单位)[luther.gliethttp]
    //将nk.nb0烧写时在该主分区的逻辑扇区号保存在了g_pTOC->id[g_dwTocEntry].dwStoreOffset中,
    //所以g_pTOC->id[g_dwTocEntry].dwStoreOffset之后的数据就是nk.nb0的raw数据了[luther.gliethttp]
    if ( !BP_SetDataPointer(hPart, g_pTOC->id[g_dwTocEntry].dwStoreOffset) )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to set data pointer in partition (offset=0x%x)./r/n"),
            g_pTOC->id[g_dwTocEntry].dwStoreOffset));
        return(FALSE);
    }

    // Read the kernel region from the Boot Media into RAM.
    //g_pTOC->id[g_dwTocEntry].dwTtlSectors等于nk.nb0大小,即29M,对应29M/512=0xE800个扇区,所以g_pTOC->id[g_dwTocEntry].dwTtlSectors中存放的数值为0xE800.[luther.gliethttp]
    //之所以能够在2秒内将29M数据加载完成,这完全归功于
    //加载地址0x80001000处dcache和icache都已打开[luther.gliethttp]
    if ( !BP_ReadData( hPart,
                       (LPBYTE)(g_pTOC->id[g_dwTocEntry].dwLoadAddress),
                       SECTOR_TO_FILE_SIZE(g_pTOC->id[g_dwTocEntry].dwTtlSectors)) )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to read kernel region from partition./r/n")));
        return(FALSE);
    }

    if (!g_pTOC->chainInfo.dwLoadAddress)
    {
        chainaddr = g_pTOC->chainInfo.dwLoadAddress;
        flashaddr = g_pTOC->chainInfo.dwFlashAddress;
        for ( i = 0; i < (g_pTOC->chainInfo.dwLength); i++ )
        {
            OALMSG(TRUE, (TEXT("chainaddr=0x%x, flashaddr=0x%x/r/n"), chainaddr, flashaddr+i));

            if ( !FMD_ReadSector(flashaddr+i, (PUCHAR)(chainaddr), &si, 1) ) {
                OALMSG(OAL_ERROR, (TEXT("TOC_Write ERROR: Unable to read/verify TOC/r/n")));
                return FALSE;
            }
            chainaddr += 512;
        }
    }
    OALMSG(OAL_FUNC, (TEXT("_ReadOSImageFromBootMedia/r/n")));
    return(TRUE);
}

HANDLE BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)
{
        DWORD dwPartIndex;
        BOOL fExists;

        ASSERT (g_pbMBRSector);
        
        if (!IsValidMBR()) {//找到第一个非坏块,同时非reserved的块,同时MBR的各个标志位信息都正确,就是所谓的MBR起始块[luther.gliethttp]
            DWORD dwFlags = 0;

            if (dwCreationFlags == PART_OPEN_EXISTING) {
                RETAILMSG(1, (TEXT("OpenPartition: Invalid MBR.  Cannot open existing partition 0x%x./r/n"), dwPartType));
                return INVALID_HANDLE_VALUE;
            }
            
            RETAILMSG(1, (TEXT("OpenPartition: Invalid MBR.  Formatting flash./r/n")));
            if (g_FlashInfo.flashType == NOR) {
                dwFlags |= FORMAT_SKIP_BLOCK_CHECK;
            }
            BP_LowLevelFormat (0, g_FlashInfo.dwNumBlocks, dwFlags);//如果没有找到,那么进行低格[luther.gliethttp]
            dwPartIndex = 0;
            fExists = FALSE;
        }
        else {
            fExists = GetPartitionTableIndex(dwPartType, fActive, &dwPartIndex);//获取dwPartType的主分区号,如果dwPartType已经存在的话[luther.gliethttp]
        }

        RETAILMSG(1, (TEXT("OpenPartition: Partition Exists=0x%x for part 0x%x./r/n"), fExists, dwPartType));
        if (fExists) {

            // Partition was found.  
            if (dwCreationFlags == PART_CREATE_NEW)
                return INVALID_HANDLE_VALUE;
            
            if (g_partStateTable[dwPartIndex].pPartEntry == NULL) {
                // Open partition.  If this is the boot section partition, then file pointer starts after MBR
                g_partStateTable[dwPartIndex].pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET + sizeof(PARTENTRY)*dwPartIndex);
                g_partStateTable[dwPartIndex].dwDataPointer = 0;
            }            
            return (HANDLE)&g_partStateTable[dwPartIndex];            
        }
        else {

            // If there are already 4 partitions, or creation flag specified OPEN_EXISTING, fail.
            if ((dwPartIndex == NUM_PARTS) || (dwCreationFlags == PART_OPEN_EXISTING))//如果已经没有空的主分区,即4个主分区全部占满,那么false.
                return INVALID_HANDLE_VALUE;

            // Create new partition
            return CreatePartition (dwStartSector, dwNumSectors, dwPartType, fActive, dwPartIndex);//否则在该空闲主分区建立本image分区信息[luther.gliethttp]
        }

        return INVALID_HANDLE_VALUE;
        
}

static BOOL GetPartitionTableIndex (DWORD dwPartType, BOOL fActive, PDWORD pdwIndex)
{
    PPARTENTRY pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET);
    DWORD iEntry = 0;
    
    for (iEntry = 0; iEntry < NUM_PARTS; iEntry++, pPartEntry++) {
        if ((pPartEntry->Part_FileSystem == dwPartType) && (((pPartEntry->Part_BootInd & PART_IND_ACTIVE) != 0) == fActive)) {
            *pdwIndex = iEntry;
            return TRUE;
        }
        if (!IsValidPart (pPartEntry)) {
            *pdwIndex = iEntry;
            return FALSE;
        }
    }

    return FALSE;
}

static HANDLE CreatePartition (DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwPartIndex)
{
    DWORD dwBootInd = 0;

    RETAILMSG(1, (TEXT("CreatePartition: Enter CreatePartition for 0x%x./r/n"), dwPartType));
    
    if (fActive)
        dwBootInd |= PART_IND_ACTIVE;
    if (dwPartType == PART_BOOTSECTION || dwPartType == PART_BINFS || dwPartType == PART_XIP)
        dwBootInd |= PART_IND_READ_ONLY;    

     // If start sector is invalid, it means find next free sector
    if (dwStartSector == NEXT_FREE_LOC) {//由本函数自由选定一个空闲扇区[luther.gliethttp]
        
        dwStartSector = FindFreeSector();//找到从g_dwMBRSectorNum开始的第一个没有被任何主分区管理的空闲扇区,该扇区之后的所有扇区都可以被该新主分区管理,因为到目前为止还没有任何主分区管理他们[luther.gliethttp]
        if (dwStartSector == INVALID_ADDR) {
            RETAILMSG(1, (TEXT("CreatePartition: can't find free sector./r/n")));
            return INVALID_HANDLE_VALUE;
        }

        // Start partitions on the next block if they are currently on the wrong block type.
        if (dwStartSector % g_FlashInfo.wSectorsPerBlock) {//如果该sector不是block的第一扇区,那么将使用下一个block第一扇区作为,
            DWORD dwBlock = dwStartSector / g_FlashInfo.wSectorsPerBlock;
            if (IS_PART_READONLY(dwBootInd) != IS_BLOCK_READONLY(dwBlock)) {
                dwStartSector = (dwBlock+1) * g_FlashInfo.wSectorsPerBlock;//下一个block为分区表管理的数据区首地址[luther.gliethttp]
            }
        }
    }

    if (IS_PART_READONLY(dwBootInd)) {
/*对于
WriteOSImageToBootMedia
==>BP_OpenPartition( NEXT_FREE_LOC,
                                USE_REMAINING_SPACE,
                                PART_DOS32,//非READONLY分区
                                TRUE,
                                PART_OPEN_ALWAYS);
不会执行到这里
*/

        // Allow read-only partitions to go to the end of disk, if requested.
        if (dwNumSectors == USE_REMAINING_SPACE) {

            DWORD dwLastLogSector = LastLogSector();//表示使用
            if (dwLastLogSector == INVALID_ADDR)
                return INVALID_HANDLE_VALUE;

            dwNumSectors = dwLastLogSector - dwStartSector + 1;//表示使用dwStartSector开始的所有剩余flash扇区空间[luther.gliethttp]
        }
    }
    else {

        DWORD dwLastLogSector = LastLogSector();//返回flash磁盘可用的结尾扇区号
        if (dwLastLogSector == INVALID_ADDR)
            return INVALID_HANDLE_VALUE;
//define SECTOR_WRITE_COMPLETED 0x0004  // Indicates data is valid for the FAL
//#define MINIMUM_FLASH_BLOCKS_TO_RESERVE                2
//#define PERCENTAGE_OF_MEDIA_TO_RESERVE                400        // 0.25% of the media {NOTE: 100% / 0.25% == 400}   //留有25%的free空间
        // Determine the number of blocks to reserve for the FAL compaction when creating an extended partition.
        DWORD dwReservedBlocks = g_FlashInfo.dwNumBlocks / PERCENTAGE_OF_MEDIA_TO_RESERVE;
        if((dwReservedBlocks = g_FlashInfo.dwNumBlocks / PERCENTAGE_OF_MEDIA_TO_RESERVE) < MINIMUM_FLASH_BLOCKS_TO_RESERVE) {//保证最少1/4空闲空间剩余
            dwReservedBlocks = MINIMUM_FLASH_BLOCKS_TO_RESERVE;
        }
        
        DWORD dwNumMaxSectors = dwLastLogSector - dwStartSector + 1 - dwReservedBlocks * g_FlashInfo.wSectorsPerBlock;//计算该分区所能支配的最大扇区数目[luther.gliethttp]

        // If dwNumSectors was provided, validate it isn't past the max.
        // If dwNumSectors is USE_REMAINING_SPACE, fill disk with max sectors.
        if ((dwNumSectors == USE_REMAINING_SPACE)  || (dwNumMaxSectors <  dwNumSectors)) {
            RETAILMSG(1, (TEXT("CreatePartition: Num sectors set to 0x%x to allow for compaction blocks./r/n"), dwNumMaxSectors));
            dwNumSectors = dwNumMaxSectors ;//将所有的可用扇区作为该主分区管理flash扇区[luther.gliethttp]
        }
    }
    
    if (!AreSectorsFree (dwStartSector, dwNumSectors)){//再次确认dwStartSector之后的dwNumSectors扇区确实没有被任何主分区管理[luther.gliethttp]
        RETAILMSG (1, (TEXT("CreatePartition: sectors [0x%x, 0x%x] requested are out of range or taken by another partition/r/n"), dwStartSector, dwNumSectors));
        return INVALID_HANDLE_VALUE;
    }
//至此dwStartSector之后的dwNumSectors个扇区可以由该主分区管理[luther.gliethttp]

    RETAILMSG(1, (TEXT("CreatePartition: Start = 0x%x, Num = 0x%x./r/n"), dwStartSector, dwNumSectors));
    
    AddPartitionTableEntry (dwPartIndex, dwStartSector, dwNumSectors, (BYTE)dwPartType, (BYTE)dwBootInd);//将该分区信息添加到该主分区表[luther.gliethttp]

    if (IS_PART_READONLY(dwBootInd)) {
        if (!WriteLogicalNumbers (dwStartSector, dwNumSectors, TRUE)) {
            RETAILMSG(1, (TEXT("CreatePartition: can't mark sector info./r/n")));
            return INVALID_HANDLE_VALUE;
        }
    }

    if (!WriteMBR()) //ok,主分区已经在BinFS的缓冲区设置完毕了,现在将BinFS缓冲区中的数据回写到flash.[luther.gliethttp]
        return INVALID_HANDLE_VALUE;

    g_partStateTable[dwPartIndex].pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET + sizeof(PARTENTRY)*dwPartIndex);
    g_partStateTable[dwPartIndex].dwDataPointer = 0;

    return (HANDLE)&g_partStateTable[dwPartIndex];            
}

static DWORD FindFreeSector()
{
    DWORD dwFreeSector = 1;//表示从该扇区之后的所有扇区都还没有一个主分区来管理他们,所以可以有效使用
    PPARTENTRY pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET);

    for (int i = 0; i < NUM_PARTS; i++) {
        if (!IsValidPart (pPartEntry))
            break;
        if ((pPartEntry->Part_StartSector + pPartEntry->Part_TotalSectors) > dwFreeSector)
            dwFreeSector = pPartEntry->Part_StartSector + pPartEntry->Part_TotalSectors;//这里明显是为了找到所有登记了的主分区,他们最大管理的扇区号,
            //(就像我们对pc进行分区一样,我们可以任意从分区表中删除一个fat32分区,然后该分区表对应的start_sector - end_sector就空闲出来了,当然这段空闲出来的分区,可以供
            //另外一次操作重新建立成ntfs分区,就是说dwFreeSectorb之后的所有扇区都是没有人管理的,即没有主分区来管理的,所以可以由新创建的主分区表项管理该dwFreeSector以后的
            //所有分区)[luther.gliethttp]
        RETAILMSG(1, (TEXT("FindFreeSector: FreeSector is: 0x%x after processing part 0x%x./r/n"), dwFreeSector, pPartEntry->Part_FileSystem));
        pPartEntry++;
    }

    DWORD dwLastLogSector = LastLogSector();//找到最靠后的那个空闲block块,然后返回该块的第一个扇区[luther.gliethttp]
    if (dwLastLogSector == INVALID_ADDR || dwFreeSector >= dwLastLogSector)//所以dwFreeSector不应该超过最大sector地址[luther.gliethttp]
        dwFreeSector = INVALID_ADDR;

    return dwFreeSector;
}

static DWORD LastLogSector()
{
    if (g_dwLastLogSector) {//在BP_Init中g_dwLastLogSector = 0;
       return g_dwLastLogSector;
    }

    DWORD dwMBRBlock = g_dwMBRSectorNum / g_FlashInfo.wSectorsPerBlock;
    DWORD dwUnusableBlocks = dwMBRBlock;

    for (DWORD i = dwMBRBlock; i < g_FlashInfo.dwNumBlocks; i++) {
        if (IS_BLOCK_UNUSABLE (i))
            dwUnusableBlocks++;//不可用块计数(坏块或者RESERVED块)
    }
    //找到最靠后的那个空闲block块,然后返回该块的第一个扇区[luther.gliethttp]
    //从该语句算法来看,所有UnusableBlocks不可用块都会放到整个flash的结尾,当然也可能只是统计一下整个flash可用sectors有多少[lutehr.gliethttp]
    g_dwLastLogSector = (g_FlashInfo.dwNumBlocks - dwUnusableBlocks) * g_FlashInfo.wSectorsPerBlock - 1;

    RETAILMSG(1, (TEXT("LastLogSector: Last log sector is: 0x%x./r/n"), g_dwLastLogSector));
    
    return g_dwLastLogSector;
}

static BOOL AreSectorsFree (DWORD dwStartSector, DWORD dwNumSectors)
{
    PPARTENTRY pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET);//4个主分区表的起始地址
    DWORD dwEndSector = dwStartSector + dwNumSectors - 1;//结尾扇区
    DWORD dwEndReservedSector;

    DWORD dwLastLogSector = LastLogSector();//返回所能管理的最后一个扇区号
    if ((dwLastLogSector == INVALID_ADDR) || (dwNumSectors > dwLastLogSector+1) || (dwEndSector > dwLastLogSector) ||
        (dwNumSectors == 0) || (dwStartSector > dwEndSector))
        return FALSE;
    
    for (int i = 0; i < NUM_PARTS; i++) {
        if (!IsValidPart (pPartEntry))
            break;        
        dwEndReservedSector = pPartEntry->Part_StartSector + pPartEntry->Part_TotalSectors - 1;
//检查dwStartSector之后的dwNumSectors个扇区是否被现有有效主分区所管理,
//我们当然期望没有被管理,这样我们才能成功创建我们需要的新主分区[luther.gliethttp]
        if (!(dwStartSector > dwEndReservedSector || dwEndSector < pPartEntry->Part_StartSector))
            return FALSE;

        pPartEntry++;
    }
    return TRUE;
}

//添加主分区信息
static void AddPartitionTableEntry(DWORD entry, DWORD startSector, DWORD totalSectors, BYTE fileSystem, BYTE bootInd)
{
    PARTENTRY partentry = {0};
    Addr startAddr;
    Addr endAddr;

    ASSERT(entry < 4);

    // no checking with disk info and start/total sectors because we allow
    // bogus partitions for testing purposes

    // initially known partition table entry
    partentry.Part_BootInd = bootInd;
    partentry.Part_FileSystem = fileSystem;
    partentry.Part_StartSector = startSector;
    partentry.Part_TotalSectors = totalSectors;

    // logical block addresses for the first and final sector (start on the second head)
    startAddr.type = LBA;
    startAddr.lba = partentry.Part_StartSector;
    endAddr.type = LBA;
    endAddr.lba = partentry.Part_StartSector + partentry.Part_TotalSectors-1;

    // translate the LBA addresses to CHS addresses
    startAddr = LBAtoCHS(&g_FlashInfo, startAddr);//添加磁道和柱面信息
    endAddr = LBAtoCHS(&g_FlashInfo, endAddr);

    // starting address
    partentry.Part_FirstTrack = (BYTE)(startAddr.chs.cylinder & 0xFF);
    partentry.Part_FirstHead = (BYTE)(startAddr.chs.head & 0xFF);
    // lower 6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bit cylinder #
    partentry.Part_FirstSector = (BYTE)((startAddr.chs.sector & 0x3F) | ((startAddr.chs.cylinder & 0x0300) >> 2));

    // ending address:
    partentry.Part_LastTrack = (BYTE)(endAddr.chs.cylinder & 0xFF);
    partentry.Part_LastHead = (BYTE)(endAddr.chs.head & 0xFF);
    // lower 6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bit cylinder #
    partentry.Part_LastSector = (BYTE)((endAddr.chs.sector & 0x3F) | ((endAddr.chs.cylinder & 0x0300) >> 2));

    memcpy(g_pbMBRSector+PARTTABLE_OFFSET+(sizeof(PARTENTRY)*entry), &partentry, sizeof(PARTENTRY));//将信息拷贝到BinFS的MBR临时缓冲区下的相应主分区空间[luther.gliethttp]
}

static Addr LBAtoCHS(FlashInfo *pFlashInfo, Addr lba)
{
    if(lba.type == CHS)
        return lba;

    Addr chs;
    DWORD tmp = pFlashInfo->dwNumBlocks * pFlashInfo->wSectorsPerBlock;

    chs.type = CHS;
    chs.chs.cylinder = (WORD)(lba.lba / tmp);
    tmp = lba.lba % tmp;
    chs.chs.head = (WORD)(tmp / pFlashInfo->wSectorsPerBlock);
    chs.chs.sector = (WORD)((tmp % pFlashInfo->wSectorsPerBlock) + 1);

    return chs;
}

//从主分区由BP_SetDataPointer设置的逻辑地址开始读取dwLength长度数据到pbBuffer缓冲区[luther.gliethttp]
BOOL BP_ReadData(HANDLE hPartition, LPBYTE pbBuffer, DWORD dwLength)
{
    if (hPartition == INVALID_HANDLE_VALUE)
        return FALSE;
    
    DWORD dwNumSects, dwBlockAddress;
    static LPBYTE pbSector = g_pbBlock;
    PPARTSTATE pPartState = (PPARTSTATE) hPartition;
    DWORD dwNextPtrValue = pPartState->dwDataPointer + dwLength;

    if (!pbBuffer || !pbSector || dwLength == 0)
        return(FALSE);

    RETAILMSG (1, (TEXT("ReadData: Start = 0x%x, Length = 0x%x./r/n"), pPartState->dwDataPointer, dwLength));

    // Check to make sure buffer size is within limits of partition
    if (((dwNextPtrValue - 1) / g_FlashInfo.wDataBytesPerSector) >= pPartState->pPartEntry->Part_TotalSectors) {
        RETAILMSG (1, (TEXT("ReadData: trying to read past end of partition./r/n")));
        return FALSE;
    }

    // Get the starting physical sector
    DWORD dwSectorAddr = Log2Phys (pPartState->dwDataPointer / g_FlashInfo.wDataBytesPerSector + pPartState->pPartEntry->Part_StartSector);

    // If current pointer is not on a sector boundary, copy bytes up to the first sector boundary
    DWORD dwOffsetSector = pPartState->dwDataPointer % g_FlashInfo.wDataBytesPerSector;
    if (dwOffsetSector)
    {
        if (!FMD_ReadSector(dwSectorAddr, pbSector, NULL, 1))
        {
            RETAILMSG (1, (TEXT("ReadData: failed to read sector (0x%x)./r/n"), dwSectorAddr));
            return(FALSE);
        }
        
        DWORD dwNumBytesRead = g_FlashInfo.wDataBytesPerSector - dwOffsetSector;
        if (dwNumBytesRead > dwLength)
            dwNumBytesRead = dwLength;
        
        memcpy(pbBuffer, pbSector + dwOffsetSector, dwNumBytesRead);   
        dwLength -= dwNumBytesRead;
        pbBuffer += dwNumBytesRead;
        dwSectorAddr++;
    }

    // Compute sector length.
    dwNumSects = (dwLength / g_FlashInfo.wDataBytesPerSector);

    // NAND FMD only supports single-sector reads at the moment.
    while (dwNumSects--)
    {
        dwBlockAddress = (dwSectorAddr / g_FlashInfo.wSectorsPerBlock);

        // If the block is marked bad, skip to next block.  Note that the assumption in our error checking
        // is that any truely bad block will be marked either by the factory during production or will be marked
        // during the erase and write verification phases.  If anything other than a bad block fails ECC correction
        // in this routine, it's fatal.
        if (IS_BLOCK_UNUSABLE(dwBlockAddress))
        {
            dwSectorAddr += g_FlashInfo.wSectorsPerBlock;
            ++dwNumSects;        // Compensate for fact that we didn't write any sector data.
            continue;
        }

        // Read the sector - if this fails ECC correction, we fail the whole read operation.
        // Note - only single sector reads supported at the moment.
        if (!FMD_ReadSector(dwSectorAddr, pbBuffer, NULL, 1))
        {
            RETAILMSG (1, (TEXT("ReadData: failed to read sector (0x%x)./r/n"), dwSectorAddr));
            return(FALSE);
        }

        ++dwSectorAddr;
        pbBuffer += g_FlashInfo.wDataBytesPerSector;
    }

    DWORD dwNumExtraBytes = (dwLength % g_FlashInfo.wDataBytesPerSector);
    if (dwNumExtraBytes)
    {
        // Skip bad blocks
        while (IS_BLOCK_UNUSABLE(dwSectorAddr / g_FlashInfo.wSectorsPerBlock))
        {
            dwSectorAddr += g_FlashInfo.wSectorsPerBlock;
            if ((dwSectorAddr / g_FlashInfo.wSectorsPerBlock) >= g_FlashInfo.dwNumBlocks)
            {
                // This should never happen since partition has already been created
                RETAILMSG (1, (TEXT("ReadData: corrupt partition.  Reformat flash./r/n")));                
                return FALSE;
            }
        }
        
        if (!FMD_ReadSector(dwSectorAddr, pbSector, NULL, 1))
        {
            RETAILMSG (1, (TEXT("ReadData: failed to read sector (0x%x)./r/n"), dwSectorAddr));
            return(FALSE);
        }
        memcpy(pbBuffer, pbSector, dwNumExtraBytes);
    }

    pPartState->dwDataPointer = dwNextPtrValue;
    return(TRUE);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值