bootload启动流程(补充二)--Eboot磁盘分区及读写函数分析

来源:互联网 发布:淘宝申请退款是灰的 编辑:程序博客网 时间:2024/06/05 17:22

WriteRegionsToBootMedia ( )的详细分析

       这个函数的原型如下:

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);

        }//如果没有读到TOC在这里初始化TOC并且将相关信息写入

    }

    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);

    }//确认这里是BINFS

    // 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); 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(  PAGES_PER_BLOCK,              //logic 0 is 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;

//计算偏移

        // Set the file pointer (byte indexing) to the correct offset for this particular region.

        if ( !BP_SetDataPointer(hPart, dwStoreOffset) )

        {

            EdbgOutputDebugString("ERROR: StoreImageToBootMedia: Failed to set data pointer in BINFS partition (offset=0x%x)./r/n", dwStoreOffset);

            return(FALSE);

        }//设置补偿

        // Write the region to the BINFS partition.

        if ( !BP_WriteData(hPart, (LPBYTE)dwRegionStart, dwRegionLength) )

        {

            EdbgOutputDebugString("ERROR: StoreImageToBootMedia: Failed to write region to BINFS partition (start=0x%x, length=0x%x)./r/n", dwRegionStart, dwRegionLength);

            return(FALSE);

        }//将镜像文件写入FLASH

        // update our TOC?

        if ((g_pTOC->id[g_dwTocEntry].dwLoadAddress == g_BINRegionInfo.Region[nCount].dwRegionStart) &&

             g_pTOC->id[g_dwTocEntry].dwTtlSectors == FILE_TO_SECTOR_SIZE(dwRegionLength) )

        {//这个条件在打算写入FLASH前给定的

            g_pTOC->id[g_dwTocEntry].dwStoreOffset = dwStoreOffset;

            g_pTOC->id[g_dwTocEntry].dwJumpAddress = 0; // Filled upon return to OEMLaunch

//这个跳转地址在之后写入TOC的时候还会更新,这样做是为了这个函数调用的通用性

            g_pTOC->id[g_dwTocEntry].dwImageType = g_ImageType;

            g_pTOC->id[g_dwTocEntry].sgList[0].dwSector = FILE_TO_SECTOR_SIZE(g_dwLastWrittenLoc);

            g_pTOC->id[g_dwTocEntry].sgList[0].dwLength = g_pTOC->id[g_dwTocEntry].dwTtlSectors;

            // copy Kernel Region to SDRAM for jump

            memcpy((void*)g_pTOC->id[g_dwTocEntry].dwLoadAddress, (void*)dwRegionStart, dwRegionLength);//拷贝镜像到下载地址

            EdbgOutputDebugString("Updateded TOC!/r/n");

        }

        else if( (dwChainStart == g_BINRegionInfo.Region[nCount].dwRegionStart) &&

                 (dwChainLength == g_BINRegionInfo.Region[nCount].dwRegionLength))

        {

            //  Update our TOC for Chain region

            g_pTOC->chainInfo.dwLoadAddress = dwChainStart;

            g_pTOC->chainInfo.dwFlashAddress = FILE_TO_SECTOR_SIZE(g_dwLastWrittenLoc);

            g_pTOC->chainInfo.dwLength = FILE_TO_SECTOR_SIZE(dwMaxRegionLength[nCount]);

 

            EdbgOutputDebugString("Written Chain Region to the Flash/n");

            EdbgOutputDebugString("LoadAddress = 0x%X; FlashAddress = 0x%X; Length = 0x%X/n",

                                  g_pTOC->chainInfo.dwLoadAddress,

                                  g_pTOC->chainInfo.dwFlashAddress,

                                  g_pTOC->chainInfo.dwLength);

            // Now copy it to the SDRAM

            memcpy((void *)g_pTOC->chainInfo.dwLoadAddress, (void *)dwRegionStart, dwRegionLength);

//            memcpy((void *)0x8c050000, (void *)dwRegionStart, dwRegionLength);

        }

    }

    // create extended partition in whatever is left

    //

    hPartEx = BP_OpenPartition( NEXT_FREE_LOC,

                                USE_REMAINING_SPACE,

                                PART_DOS32,

                                TRUE,

                                PART_OPEN_ALWAYS);

 

    if (hPartEx == INVALID_HANDLE_VALUE )

    {

        EdbgOutputDebugString("*** WARN: StoreImageToBootMedia: Failed to open/create Extended partition ***/r/n");

    }

//创建剩下的FLASHFAT格式

    EdbgOutputDebugString("-WriteRegionsToBootMedia/r/n");

    return(TRUE);

}

之后就是再提一下BP_WriteData()函数,它与BP_ReadData()类似,主要是对如果不对齐block的情况进行处理。我将主要代码搬过来看看就可以了:

DWORD dwBlock = Log2Phys (pPartState->dwDataPointer / g_FlashInfo.wDataBytesPerSector + pPartState->pPartEntry->Part_StartSector) / g_FlashInfo.wSectorsPerBlock;//块地址

    DWORD dwOffsetBlock = (pPartState->dwDataPointer + pPartState->pPartEntry->Part_StartSector * g_FlashInfo.wDataBytesPerSector) % g_dwDataBytesPerBlock;//块偏移

    // Update the global indicating last written physical address.  Global variable is used by the caller.

    g_dwLastWrittenLoc = dwBlock * g_dwDataBytesPerBlock + dwOffsetBlock;

    // If current pointer is not on a block boundary, copy bytes up to the first block boundary

    if (dwOffsetBlock)

    {

        if (!ReadBlock(dwBlock, g_pbBlock, g_pSectorInfoBuf)) {

            RETAILMSG (1, (TEXT("WriteData: failed to read block (0x%x)./r/n"), dwBlock));

            return(FALSE);

        }

        DWORD dwNumBytesWrite = g_dwDataBytesPerBlock - dwOffsetBlock;

        if (dwNumBytesWrite > dwLength)

            dwNumBytesWrite = dwLength;

        memcpy(g_pbBlock + dwOffsetBlock, pbBuffer, dwNumBytesWrite);  

        if (!FMD_EraseBlock(dwBlock)) {

            RETAILMSG (1, (TEXT("WriteData: failed to erase block (0x%x)./r/n"), dwBlock));

            return FALSE;

        }

        if (!WriteBlock(dwBlock, g_pbBlock, g_pSectorInfoBuf)) {

            RETAILMSG (1, (TEXT("WriteData: failed to write block (0x%x)./r/n"), dwBlock));

            return(FALSE);

        }

        dwLength -= dwNumBytesWrite;

        pbBuffer += dwNumBytesWrite;

        dwBlock++;

    }

//这块对镜像写入的前端处理

    // Compute number of blocks.

    dwNumBlocks = (dwLength / g_dwDataBytesPerBlock);

    while (dwNumBlocks--)

    {

        // 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(dwBlock))

        {

            ++dwBlock;

            ++dwNumBlocks;        // Compensate for fact that we didn't write any blocks.

            continue;

        }

        if (!ReadBlock(dwBlock, NULL, g_pSectorInfoBuf)) {

            RETAILMSG (1, (TEXT("WriteData: failed to read block (0x%x)./r/n"), dwBlock));

            return(FALSE);

        }

        if (!FMD_EraseBlock(dwBlock)) {

            RETAILMSG (1, (TEXT("WriteData: failed to erase block (0x%x)./r/n"), dwBlock));

            return FALSE;

        }

        if (!WriteBlock(dwBlock, pbBuffer, g_pSectorInfoBuf)) {

            RETAILMSG (1, (TEXT("WriteData: failed to write block (0x%x)./r/n"), dwBlock));

            return(FALSE);

        }

        ++dwBlock;

        pbBuffer += g_dwDataBytesPerBlock;

    }

//处理成块的镜像文件

    DWORD dwNumExtraBytes = (dwLength % g_dwDataBytesPerBlock);

    if (dwNumExtraBytes)

    {

        // Skip bad blocks

        while (IS_BLOCK_UNUSABLE(dwBlock))

        {

            dwBlock++;

            if (dwBlock >= g_FlashInfo.dwNumBlocks)

            {

                // This should never happen since partition has already been created

                RETAILMSG (1, (TEXT("WriteData: corrupt partition.  Reformat flash./r/n")));               

                return FALSE;

            }

        }

       

        if (!ReadBlock(dwBlock, g_pbBlock, g_pSectorInfoBuf)) {

            RETAILMSG (1, (TEXT("WriteData: failed to read block (0x%x)./r/n"), dwBlock));

            return(FALSE);

        }

        memcpy(g_pbBlock, pbBuffer, dwNumExtraBytes);  

        if (!FMD_EraseBlock(dwBlock)) {

            RETAILMSG (1, (TEXT("WriteData: failed to erase block (0x%x)./r/n"), dwBlock));

            return FALSE;

        }

        if (!WriteBlock(dwBlock, g_pbBlock, g_pSectorInfoBuf)) {

            RETAILMSG (1, (TEXT("WriteData: failed to write block (0x%x)./r/n"), dwBlock));

            return(FALSE);

        }

    }

//镜像后端处理

    pPartState->dwDataPointer = dwNextPtrValue;

return(TRUE);

 

 

到这基本的磁盘方面的东西就介绍完了,最后就提一下MBR实际是在低格的时候创建的,而且其block位置也在低格的时候确定,而与分区的地址没有关系。所以分区的地址应该是镜像文件的开始地址,而在读取镜像文件的时候MBR也是通过搜索找到的,而与镜像地址没关系。从这里你也可以发现实际MBRBLOCK地址前不能有完好并且未使用的block,不然这个块会被处理为MBR的。这个大家注意一下就好了。(EBOOT分析结束)如果有不清楚的可以联系我:mail : gsujianwen@163.com

原创粉丝点击