Eboot 中给nandflash分区实现

来源:互联网 发布:mac创建win7安装u盘 编辑:程序博客网 时间:2024/05/21 16:56

提到分区就不得不提到MBR,不得不提到分区表。

什么是MBR

硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASH由BLOCK和Sector组成,所以NANDFLASH的第0BLOCK,第1Sector为主引导扇区,FDISK程序写到该扇区的内容称为主引导记录(MBR)。该记录占用512个字节,它用于硬盘启动时将系统控制权交给用户指定的,并在分区表中登记了的某个操作系统区。

 

MBR的组成
一个扇区的硬盘主引导记录MBR由如图6-15所示的4个部分组成。
·主引导程序(偏移地址0000H--0088H),它负责从活动分区中装载,并运行系统引导程序。
·出错信息数据区,偏移地址0089H--00E1H为出错信息,00E2H--01BDH全为0字节。
·分区表(DPT,Disk PartitionTable)含4个分区项,偏移地址01BEH--01FDH,每个分区表项长16个字节,共64字节为分区项1、分区项2、分区项3、分区项4。
·结束标志字,偏移地址01FE--01FF的2个字节值为结束标志55AA,如果该标志错误系统就不能启动。


图6-15 MBR的组成结构图

MBR中的分区信息结构


   占用512个字节的MBR中,偏移地址01BEH--01FDH的64个字节,为4个分区项内容(分区信息表)。它是由磁盘介质类型及用户在使用FDISK定义分区说确定的。在实际应用中,FDISK对一个磁盘划分的主分区可少于4个,但最多不超过4个。每个分区表的项目是16个字节,其内容含义如表6-19所示。
表6-19 分区项表(16字节)内容及含义

 

 

EBOOT中对NAND分区主要代码,eboot目录下的fmd.cpp文件,与NAND驱动基本相同,所以,要对NAND进行分区,就得对NAND驱动非常熟悉。透彻了解。然后就是
E:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp文件了。该文件主要通过调用NANDFLASH的读写操作来写入MBR,也是今天主要的分析对象。

 

主要函数。

 

HANDLE BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors,DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)

 


注:示例代码为本人EBOOT中分区实现源码(WINCE5.0+S3C2440+128MNAND,MBR写在第4个BLOCK,分一个BINFS格式分区和一个FAT格式分区)。

 

BOOL WriteRegionsToBootMedia(DWORD dwImageStart, DWORDdwImageLength, DWORD dwLaunchAddr)

在把SDRAM中的NK烧写到NAND中去之前,先创建一个BINFS分区。

hPart = BP_OpenPartition((NK_START_BLOCK+1)*PAGES_PER_BLOCK,  // next blockofMBR    BINFS_BLOCK*PAGES_PER_BLOCK,//SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))*PAGES_PER_BLOCK, //align to block

                             PART_BINFS,

                             TRUE,

                             PART_OPEN_ALWAYS);


第一个参数分区的起始sector 为(NK_START_BLOCK+1)*PAGES_PER_BLOCK,

第二个参数分区的结束 sector为BINFS_BLOCK*PAGES_PER_BLOCK,

第三个参数分区的格式为PART_BINFS,即BINFS格式,

第四个参数指示该分区为活动分区,fActive = TURE,

第五个参数PART_OPEN_ALWAYS指示如果分区不存在就创建该分区,存在就OPEN该分区,返回分区句柄。

 

HANDLE BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors,DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)

{

       DWORD dwPartIndex;

       BOOL fExists;

 

       ASSERT (g_pbMBRSector);

       

       if (!IsValidMBR()) {

           DWORD dwFlags = 0;

          

           //fly

            RETAILMSG(1, (TEXT("BP_OpenPartition:: dwStartSector=0x%x,dwNumSectors= 0x%x.,dwPartType = 0x%x/r/n"), dwStartSector,dwNumSectors,dwPartType));

           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;

           }

           //fly

            RETAILMSG(1, (TEXT("BP_LowLevelFormat: g_pbMBRSector=0x%x,g_dwMBRSectorNum= 0x%x./r/n"), *g_pbMBRSector,g_dwMBRSectorNum));

           BP_LowLevelFormat (SECTOR_TO_BLOCK(dwStartSector),SECTOR_TO_BLOCK(dwNumSectors), dwFlags);

           dwPartIndex = 0;

           fExists = FALSE;

       }

       else {

           fExists = GetPartitionTableIndex(dwPartType, fActive,&dwPartIndex);       

       }

 

       RETAILMSG(1, (TEXT("OpenPartition: Partition Exists=0x%x for part0x%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 sectionpartition, then file pointer starts after MBR

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

               g_partStateTable[dwPartIndex].dwDataPointer = 0;

           

          if ( dwNumSectors >g_partStateTable[dwPartIndex].pPartEntry->Part_TotalSectors)

             return CreatePartition (dwStartSector, dwNumSectors, dwPartType,fActive, dwPartIndex);

          else         

                  return(HANDLE)&g_partStateTable[dwPartIndex];           

       }

       else {

 

           // If there are already 4 partitions, or creation flag specifiedOPEN_EXISTING, fail.

           if ((dwPartIndex == NUM_PARTS) || (dwCreationFlags ==PART_OPEN_EXISTING))

               return INVALID_HANDLE_VALUE;

 

           // Create new partition

           return CreatePartition (dwStartSector, dwNumSectors, dwPartType,fActive, dwPartIndex);

       }

 

       return INVALID_HANDLE_VALUE;

       

}

进入函数,首先做的事就是检测MBR的有效性。通过函数IsValidMBR()实现。

检测MBR的有效性,首先要知道MBR保存在哪里,前面说过NANDFLASH的第0 BLOCK,第1Sector为主引导扇区,也就是MBR,但是NAND如果被当作启动芯片,○地址一般被BOOTLOADER代码占据,MBR只有放在后面的BLOCK中。所以我把第0个BLOCK放NBOOT,第1个BLOCK放TOC,第2个BLOCK放EBOOT,第3个BLOCK保留,第4个BLOCK就放MBR。

static BOOL IsValidMBR()

{

    // Checkto see if the MBR is valid

    // MBRblock is always located at logical sector 0

   g_dwMBRSectorNum =GetMBRSectorNum();       

 

    RETAILMSG(1, (TEXT("IsValidMBR: MBR sector = 0x%x/r/n"),g_dwMBRSectorNum));

  

    if((g_dwMBRSectorNum == INVALID_ADDR) || !FMD_ReadSector(g_dwMBRSectorNum, g_pbMBRSector, NULL, 1)) {

      RETAILMSG (1, (TEXT("IsValidMBR-----returnFALSE-------------------/r/n")));

       return FALSE; 

     

    return((g_pbMBRSector[0] == 0xE9) &&

        (g_pbMBRSector[1] == 0xfd) &&

        (g_pbMBRSector[2] == 0xff) &&

        (g_pbMBRSector[SECTOR_SIZE_FS-2] == 0x55)&&

        (g_pbMBRSector[SECTOR_SIZE_FS-1] == 0xAA));

IsValidMBR()实现的第一行就是给全局变量g_dwMBRSectorNum赋值,显而易见,g_dwMBRSectorNum就是指示保存MBR的那个Sector了。

g_dwMBRSectorNum =GetMBRSectorNum();  //是获得保存MBR的那个Sector

static DWORD GetMBRSectorNum ()

{

    DWORDdwBlockNum = 3, dwSector = 0;

   SectorInfo si;

       

    while(dwBlockNum < g_FlashInfo.dwNumBlocks) {

 

       if (!IS_BLOCK_UNUSABLE (dwBlockNum)) {

           dwSector = dwBlockNum * g_FlashInfo.wSectorsPerBlock;

           

           if (!FMD_ReadSector (dwSector, NULL, &si, 1)) {

               RETAILMSG(1, (TEXT("GetMBRSectorNum: Could not read sector0x%x./r/n"), dwSector));

               return INVALID_ADDR;

           }

           // Check to see if logical sector number is 0

           if (si.dwReserved1 == 0) {

             //RETAILMSG(1,(TEXT("dwBlockNum=%d/r/n"),dwBlockNum));

               return dwSector;

           }

       }

 

       dwBlockNum++;

 

    }

 

    returnINVALID_ADDR;

}

这里dwBlockNum直接给了个3,因为NBOOT,TOC,EBOOT已经把前三个BLOCK用了。所以MBR的选择直接排除了前三个BLOCK了。

#define IS_BLOCK_UNUSABLE(blockID) ((FMD_GetBlockStatus(blockID) &(BLOCK_STATUS_BAD|BLOCK_STATUS_RESERVED)) > 0)

然后确定BLOCK是否可使用的BLOCK,最后通si.dwReserved1 ==0来判断是不是选择这个Sector来保存MBR。

IsValidMBR()中还有一个重要的结构就是g_pbMBRSector数组,它就是MBR了。

函数返回时,MBR必须符合下列记录。

    return((g_pbMBRSector[0] == 0xE9) &&

        (g_pbMBRSector[1] == 0xfd) &&

        (g_pbMBRSector[2] == 0xff) &&

        (g_pbMBRSector[SECTOR_SIZE_FS-2] == 0x55)&&

        (g_pbMBRSector[SECTOR_SIZE_FS-1] == 0xAA));

可以看到只有开始三个字节为0XE9,FD,FF,当然,还有熟悉的结束标志符0X55AA。

 

如果没有检测到MBR,则先对NANDFLASH进行低级格式化。BP_LowLevelFormat(SECTOR_TO_BLOCK(dwStartSector), SECTOR_TO_BLOCK(dwNumSectors),dwFlags);再创建分区,CreatePartition (dwStartSector, dwNumSectors,dwPartType, fActive, dwPartIndex);。

 

BOOL BP_LowLevelFormat(DWORD dwStartBlock, DWORD dwNumBlocks,DWORD dwFlags)

{

   dwNumBlocks = min (dwNumBlocks, g_FlashInfo.dwNumBlocks);

 

   RETAILMSG(1,(TEXT("fly::Enter LowLevelFormat [0x%x, 0x%x]./r/n"),dwStartBlock,dwNumBlocks));// dwStartBlock + dwNumBlocks - 1));

 

    // Eraseall the flash blocks.

    if(!EraseBlocks(dwStartBlock, dwNumBlocks, dwFlags))

       return(FALSE);

 

    //Determine first good starting block

    while(IS_BLOCK_UNUSABLE (dwStartBlock)&& dwStartBlock <g_FlashInfo.dwNumBlocks) {

       dwStartBlock++;

    }

 

    if(dwStartBlock >= g_FlashInfo.dwNumBlocks) {

       RETAILMSG(1,(TEXT("BP_LowLevelFormat: no goodblocks/r/n")));       

       return FALSE;

    }

 

    // MBRgoes in the first sector of the starting block. This will be logical sector 0.

   g_dwMBRSectorNum = dwStartBlock * g_FlashInfo.wSectorsPerBlock;

 

   RETAILMSG(1,(TEXT("fly:g_dwMBRSectorNum=%d/r/n"),g_dwMBRSectorNum));

 

    // Createan MBR.

   CreateMBR();

   return(TRUE);

}

在对NANDFLASH进行低格时,主要对坏块的处理。if (!EraseBlocks(dwStartBlock,dwNumBlocks,dwFlags))检测每一个Sector,每个BLOCK只要有一个Sector不能读写这个块都会被处理成坏块,这样才能保证系统的稳定性。在函数的最后调用了   CreateMBR();来创建一个MBR。static BOOL CreateMBR()

{

    // This,plus a valid partition table, is all the CE partition manager needsto recognize

    // theMBR as valid. It does not contain boot code.

 

    memset(g_pbMBRSector, 0xff, g_FlashInfo.wDataBytesPerSector);

   g_pbMBRSector[0] = 0xE9;

   g_pbMBRSector[1] = 0xfd;

   g_pbMBRSector[2] = 0xff;

   g_pbMBRSector[SECTOR_SIZE_FS-2] = 0x55;

   g_pbMBRSector[SECTOR_SIZE_FS-1] = 0xAA;

 

    // Zeroout partition table so that mspart treats entries as empty.

    memset(g_pbMBRSector+PARTTABLE_OFFSET, 0, sizeof(PARTENTRY) *NUM_PARTS);

 

    returnWriteMBR();

 

当然。因为还没有进行分区,这里写入的MBR分区表部分是空的。static BOOLWriteMBR()

{

    DWORDdwMBRBlockNum = g_dwMBRSectorNum /g_FlashInfo.wSectorsPerBlock;

 

   //dwMBRBlockNum = 1 ;

 

   RETAILMSG(1, (TEXT("WriteMBR: MBR block = 0x%x,g_dwMBRSectorNum =0x%x./r/n"), dwMBRBlockNum,g_dwMBRSectorNum));

 

    memset(g_pbBlock, 0xff, g_dwDataBytesPerBlock);

    memset(g_pSectorInfoBuf, 0xff, sizeof(SectorInfo) *g_FlashInfo.wSectorsPerBlock);

       

    // Noneed to check return, since a failed read means data hasn't beenwritten yet.

    ReadBlock(dwMBRBlockNum, g_pbBlock, g_pSectorInfoBuf);

 

    if(!FMD_EraseBlock (dwMBRBlockNum)) {

       RETAILMSG (1, (TEXT("CreatePartition: error erasing block0x%x/r/n"), dwMBRBlockNum));

       return FALSE;

    }

 

    memcpy(g_pbBlock + (g_dwMBRSectorNum % g_FlashInfo.wSectorsPerBlock) *g_FlashInfo.wDataBytesPerSector, g_pbMBRSector,g_FlashInfo.wDataBytesPerSector);

   g_pSectorInfoBuf->bOEMReserved &=~OEM_BLOCK_READONLY;

   g_pSectorInfoBuf->wReserved2 &=~SECTOR_WRITE_COMPLETED;

   g_pSectorInfoBuf->dwReserved1 = 0;

 

   RETAILMSG(1, (TEXT("fly::WriteMBR: MBR block = 0x%x./r/n"),dwMBRBlockNum));

 

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

       RETAILMSG (1, (TEXT("CreatePartition: could not write to block0x%x/r/n"), dwMBRBlockNum));

       return FALSE;

    }

 

    returnTRUE;

   

}

在WriteMBR()函数中,就写入了判断MBR的一些标志到BLOCK,   g_pSectorInfoBuf->bOEMReserved &=~OEM_BLOCK_READONLY;

   g_pSectorInfoBuf->wReserved2 &=~SECTOR_WRITE_COMPLETED;

   g_pSectorInfoBuf->dwReserved1 = 0;

Wince系统启动时,具体是NANDFLASH驱动加载成功后,MOUNT文件系统到NANDFLASH之前,也会通过读取这些SectorInfo来得到MBR保存的BLOCK,进而读取MBR,获得分区信息,从而把各分区MOUNT到相应文件系统。格式化完成,MBR也写入成功后就可以开始新建分区了。

 

static HANDLE CreatePartition (DWORD dwStartSector, DWORDdwNumSectors, DWORD dwPartType, BOOL fActive, DWORDdwPartIndex)

{

    DWORDdwBootInd = 0;

 

   RETAILMSG(1, (TEXT("CreatePartition: Enter CreatePartition for0x%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){       

       dwStartSector = FindFreeSector();

       if (dwStartSector == INVALID_ADDR) {

           RETAILMSG(1, (TEXT("CreatePartition: can't find freesector./r/n")));

           return INVALID_HANDLE_VALUE;

       }

 

       // Start extended partition on a block boundary

       if ((dwPartType == PART_EXTENDED)&& (dwStartSector %g_FlashInfo.wSectorsPerBlock)) {

           dwStartSector = (dwStartSector / g_FlashInfo.wSectorsPerBlock + 1)* g_FlashInfo.wSectorsPerBlock;

       }

    }

 

    // If numsectors is invalid, fill the rest of the space up

    if(dwNumSectors == USE_REMAINING_SPACE) {

 

       DWORD dwLastLogSector = LastLogSector();

       if (dwLastLogSector == INVALID_ADDR)

           return INVALID_HANDLE_VALUE;

 

       // Determine the number of blocks to reserve for the FAL compactionwhen 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) {

           dwReservedBlocks = MINIMUM_FLASH_BLOCKS_TO_RESERVE;

       }

       

       dwNumSectors = dwLastLogSector - dwStartSector + 1 -dwReservedBlocks * g_FlashInfo.wSectorsPerBlock;

    }

  

    if(!AreSectorsFree (dwStartSector, dwNumSectors)){

       RETAILMSG (1, (TEXT("fly:::::CreatePartition: sectors [0x%x, 0x%x]requested are out of range or taken by another partition/r/n"),dwStartSector, dwNumSectors));

       return INVALID_HANDLE_VALUE;

    }

 

   RETAILMSG(1, (TEXT("CreatePartition: Start = 0x%x, Num =0x%x./r/n"), dwStartSector, dwNumSectors));

   

   AddPartitionTableEntry (dwPartIndex, dwStartSector, dwNumSectors,(BYTE)dwPartType, (BYTE)dwBootInd);

 

    if(dwBootInd & PART_IND_READ_ONLY) {

       if (!WriteLogicalNumbers (dwStartSector, dwNumSectors, TRUE)) {

           RETAILMSG(1, (TEXT("CreatePartition: can't mark sectorinfo./r/n")));

           return INVALID_HANDLE_VALUE;

       }

    }

 

    if(!WriteMBR())

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

}

如果第二个参数为-1,则视为将余下的所有空间划为一个分区。LastLogSector();函数获得最后一个逻辑Sector。staticDWORD LastLogSector()

{

    if(g_dwLastLogSector) {

      return g_dwLastLogSector;

    }

 

    DWORDdwMBRBlock = g_dwMBRSectorNum / g_FlashInfo.wSectorsPerBlock;

    DWORDdwUnusableBlocks = dwMBRBlock;

 

    for(DWORD i = dwMBRBlock; i < g_FlashInfo.dwNumBlocks;i++) {

       if (IS_BLOCK_UNUSABLE (i))

           dwUnusableBlocks++;

    }

   

   g_dwLastLogSector = (g_FlashInfo.dwNumBlocks - dwUnusableBlocks) *g_FlashInfo.wSectorsPerBlock - 1;

 

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

   

    returng_dwLastLogSector;

}

即g_dwLastLogSector = (g_FlashInfo.dwNumBlocks -dwUnusableBlocks) * g_FlashInfo.wSectorsPerBlock - 1;//(NAND的BLOCK总数 – MBR保存的那个BLOCK)* 每个BLOCK的Sector数 –保存MBR的那个Sector。得到的就是从MBR那个Sector之后的所有Sector,即逻辑大小。

AreSectorsFree (dwStartSector,dwNumSectors)函数判断参数提供的起始Sector和个数有没有超出来NAND的界限,或者逻辑分区的界限。   

重头戏开始了。通过AddPartitionTableEntry (dwPartIndex, dwStartSector,dwNumSectors, (BYTE)dwPartType, (BYTE)dwBootInd); 准备分区信息写入分区表。

 

static void AddPartitionTableEntry(DWORD entry, DWORDstartSector, DWORD totalSectors, BYTE fileSystem, BYTE bootInd)

{

    PARTENTRYpartentry = {0};

    AddrstartAddr;

    AddrendAddr;

 

   ASSERT(entry < 4);

 

    // nochecking with disk info and start/total sectors because weallow

    // boguspartitions 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 onthe 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);

    // lower6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bitcylinder #

   partentry.Part_FirstSector = (BYTE)((startAddr.chs.sector& 0x3F) | ((startAddr.chs.cylinder& 0x0300) >> 2));

 

    // endingaddress:

   partentry.Part_LastTrack = (BYTE)(endAddr.chs.cylinder& 0xFF);

   partentry.Part_LastHead = (BYTE)(endAddr.chs.head &0xFF);

    // lower6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bitcylinder #

   partentry.Part_LastSector = (BYTE)((endAddr.chs.sector& 0x3F) | ((endAddr.chs.cylinder &0x0300) >> 2));

 

   memcpy(g_pbMBRSector+PARTTABLE_OFFSET+(sizeof(PARTENTRY)*entry),&partentry, sizeof(PARTENTRY));

}

这里面的地址信息是一种叫CHS(Cyinder/Head/Sector)的地址。eboot中有将逻辑地址LBS(LogicalBlock Addr)与这种地址互相转换的函数LBAtoCHS,CHSToLBA。
Addr LBAtoCHS(FlashInfo *pFlashInfo, Addr lba)
{
    Addrchs;
    DWORD tmp =pFlashInfo->dwNumBlocks *pFlashInfo->wSectorsPerBlock;

    chs.type= CHS;
   chs.chs.cylinder = (WORD)(lba.lba /tmp);                                     // 柱面,应该始终是0
    tmp =lba.lba % tmp;
    chs.chs.head= (WORD)(tmp /pFlashInfo->wSectorsPerBlock);                    // 块地址
   chs.chs.sector = (WORD)((tmp %pFlashInfo->wSectorsPerBlock) +1);    // 扇区+1

    returnchs;
}

Addr CHStoLBA(FlashInfo *pFlashInfo, Addr chs)
{
    Addrlba;

    lba.type= LBA;
    lba.lba =((chs.chs.cylinder * pFlashInfo->dwNumBlocks +chs.chs.head)
       * pFlashInfo->wSectorsPerBlock)+ chs.chs.sector -1;

return lba;
}

如果分区的格式有只读属性,则通过WriteLogicalNumbers()函数写分区的Sectorinfo,把这部分空间保护起来。

static BOOL WriteLogicalNumbers (DWORD dwStartSector, DWORDdwNumSectors, BOOL fReadOnly)

{

    DWORDdwNumSectorsWritten = 0;

 

    DWORDdwPhysSector = Log2Phys (dwStartSector);

    DWORDdwBlockNum = dwPhysSector / g_FlashInfo.wSectorsPerBlock;

    DWORDdwOffset = dwPhysSector % g_FlashInfo.wSectorsPerBlock;

   

    while(dwNumSectorsWritten < dwNumSectors) {

 

       // If bad block, move to the next block

       if (IS_BLOCK_UNUSABLE (dwBlockNum)) {

           dwBlockNum++;

           continue;

       }

 

       memset (g_pbBlock, 0xff, g_dwDataBytesPerBlock);

       memset (g_pSectorInfoBuf, 0xff, sizeof(SectorInfo) *g_FlashInfo.wSectorsPerBlock);

       // No need to check return, since a failed read means data hasn'tbeen written yet.

       ReadBlock (dwBlockNum, g_pbBlock, g_pSectorInfoBuf);

       if (!FMD_EraseBlock (dwBlockNum)) {

           return FALSE;

       }

 

       DWORD dwSectorsToWrite = g_FlashInfo.wSectorsPerBlock -dwOffset;

       PSectorInfo pSectorInfo = g_pSectorInfoBuf + dwOffset;

 

       // If this is the last block, then calculate sectors to write ifthere isn't a full block to update

       if ((dwSectorsToWrite + dwNumSectorsWritten) >dwNumSectors)

           dwSectorsToWrite = dwNumSectors - dwNumSectorsWritten;

       

       for (DWORD iSector = 0; iSector < dwSectorsToWrite;iSector++, pSectorInfo++, dwNumSectorsWritten++) {

           // Assert read only by setting bit to 0 to prevent wear-leveling byFAL

           if (fReadOnly)

               pSectorInfo->bOEMReserved &=~OEM_BLOCK_READONLY;

           // Set to write completed so FAL can map thesector 

           pSectorInfo->wReserved2 &=~SECTOR_WRITE_COMPLETED;       

           // Write the logical sector number

           pSectorInfo->dwReserved1 = dwStartSector +dwNumSectorsWritten;           

       }

       if (!WriteBlock (dwBlockNum, g_pbBlock, g_pSectorInfoBuf))

           return FALSE;

       

       dwOffset = 0;

       dwBlockNum++;

    }

    returnTRUE;

}

这就是为什么系统启动后,我们无法写入文件的BINFS文件系统格式分区的原因了。而FAT格式就可以。最后调用WriteMBR()完全MBR的写入,分区完毕。

让我们继续回到BP_OpenPartition函数中,如果从一开始IsValidMBR()就检测到有效的MBR,GetPartitionTableIndex(dwPartType,fActive,&dwPartIndex);获得分区表。和dwPartIndex分区表的索引号。

static BOOL GetPartitionTableIndex (DWORD dwPartType, BOOLfActive, PDWORD pdwIndex)

{

   PPARTENTRY pPartEntry = (PPARTENTRY)(g_pbMBRSector +PARTTABLE_OFFSET);

    DWORDiEntry = 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;

       }

    }

 

    returnFALSE;

}

 

重要结构:PARTENTRY

// end of master boot record contains 4 partition entries

typedef struct _PARTENTRY {

       BYTE           Part_BootInd;          // If 80h means this is boot partition

       BYTE           Part_FirstHead;        // Partition starting head based 0

       BYTE           Part_FirstSector;      // Partition starting sector based 1

       BYTE           Part_FirstTrack;       // Partition starting track based 0

       BYTE           Part_FileSystem;       // Partition type signature field

       BYTE           Part_LastHead;         // Partition ending head based 0

       BYTE           Part_LastSector;       // Partition ending sector based 1

       BYTE           Part_LastTrack;        // Partition ending track based 0

       DWORD          Part_StartSector;      // Logical starting sector based 0

       DWORD          Part_TotalSectors;     // Total logical sectors in partition

} PARTENTRY;

分区表就是通过这个结构写入MBR,起始地址,分区大小,分区格式,对应结构写入MBR所在的Sector就可以了。在检测有效分区时staticBOOL IsValidPart (PPARTENTRY pPartEntry)

{

    return(pPartEntry->Part_FileSystem != 0xff)&&(pPartEntry->Part_FileSystem != 0);

}

就是通过对分区表文件系统格式的判断了。

 

 

把NAND后面的空间,全部分为一个FAT格式的分区。

    //

    // createextended partition in whatever is left

    //

    hPartEx =BP_OpenPartition( (NK_START_BLOCK+1+BINFS_BLOCK) *PAGES_PER_BLOCK,

                               NEXT_FREE_LOC,   // (1024 -(NK_START_BLOCK+1+SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))))* PAGES_PER_BLOCK,

                               PART_DOS32,

                               TRUE,

                               PART_OPEN_ALWAYS);

 

    if(hPartEx == INVALID_HANDLE_VALUE )

    {

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

    }

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hugohong/archive/2009/05/20/4204700.aspx

0 0