Eboot?中给nandflash分区实现
?
提到分区就不得不提到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,DiskPartitionTable)含4个分区项,偏移地址01BEH--01FDH,每个分区表项长16个字节,共64字节为分区项1、分区项2、分区项3、分区项4。·结束标志字,偏移地址01FE--01FF的2个字节值为结束标志55AA,如果该标志错误系统就不能启动。
0000-0088
MasterBootRecord
主引导程序 主引导
程序 0089-01BD 出错信息数据区 数据区 01BE-01CD 分区项1(16字节)
分区表
01CE-01DD 分区项2(16字节) 01DE-01ED 分区项3(16字节) 01EE-01FD 分区项4(16字节) 01FE 55 结束标志 01FF AA 图6-15MBR的组成结构图
MBR中的分区信息结构
????占用512个字节的MBR中,偏移地址01BEH--01FDH的64个字节,为4个分区项内容(分区信息表)。它是由磁盘介质类型及用户在使用?FDISK定义分区说确定的。在实际应用中,FDISK对一个磁盘划分的主分区可少于4个,但最多不超过4个。每个分区表的项目是16个字节,其内容含义如表6-19所示。表6-19?分区项表(16字节)内容及含义
?
存贮字节位 内容及含义 第1字节 引导标志。若值为80H表示活动分区,若值为00H表示非活动分区。 第2、3、4字节 本分区的起始磁头号、扇区号、柱面号。其中:
????磁头号——第2字节;
????扇区号——第3字节的低6位;
????柱面号——为第3字节高2位+第4字节8位。 第5字节 分区类型符。
???00H——表示该分区未用(即没有指定);
???06H——FAT16基本分区;
???0BH——FAT32基本分区;
???05H——扩展分区;
???07H——NTFS分区;
???0FH——(LBA模式)扩展分区(83H为Linux分区等)。 第6、7、8字节 本分区的结束磁头号、扇区号、柱面号。其中:
????磁头号——第6字节;
????扇区号——第7字节的低6位;
????柱面号——第7字节的高2位+第8字节。 第9、10、11、12字节 本分区之前已用了的扇区数。 第13、14、15、16字节 本分区的总扇区数。 ?
EBOOT中对NAND分区主要代码,eboot目录下的fmd.cpp文件,与NAND驱动基本相同,所以,要对NAND进行分区,就得对NAND驱动非常熟悉。透彻了解。然后就是E:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp文件了。该文件主要通过调用NANDFLASH的读写操作来写入MBR,也是今天主要的分析对象。
?
主要函数。
/??BP_OpenPartition
?
???Opens/createsapartitiondependingonthecreationflags.??Ifitisopening
???andthepartitionhasalreadybeenopened,thenitreturnsahandletothe
???openedpartition.??Otherwise,itloadsthestateinformationofthatpartition
???intomemoryandreturnsahandle.?
?
???ENTRY
???????dwStartSector-Logicalsectortostartthepartition.??NEXT_FREE_LOCifnone
???????????specified.??Ignoredifopeningexistingpartition.
???????dwNumSectors-Numberoflogicalsectorsofthepartition.??USE_REMAINING_SPACE
???????????toindicatetotakeuptherestofthespaceontheflashforthatpartition(should
???????????onlybeusedwhencreatingextendedpartitions).??Thisparameterisignored
???????????ifopeningexistingpartition.
???????dwPartType-Typeofpartitiontocreate/open.
???????fActive-TRUEindicatestocreate/opentheactivepartition.??FALSEfor
???????????inactive.
???????dwCreationFlags-PART_CREATE_NEWtocreateonly.??Failifitalready
???????????exists.??PART_OPEN_EXISTINGtoopenonly.??Failifitdoesn''texist.
???????????PART_OPEN_ALWAYScreatesifitdoesnotexistandopensifit
???????????doesexist.
?
???EXIT
???????Handletothepartitiononsuccess.??INVALID_HANDLE_VALUEonerror.
?/
HANDLEBP_OpenPartition(DWORDdwStartSector,DWORDdwNumSectors,DWORDdwPartType,BOOLfActive,DWORDdwCreationFlags)
注:示例代码为本人EBOOT中分区实现源码(WINCE5.0+S3C2440+128MNAND,MBR写在第4个BLOCK,分一个BINFS格式分区和一个FAT格式分区)。
?
BOOLWriteRegionsToBootMedia(DWORDdwImageStart,DWORDdwImageLength,DWORDdwLaunchAddr)
在把SDRAM中的NK烧写到NAND中去之前,先创建一个BINFS分区。
hPart=BP_OpenPartition((NK_START_BLOCK+1)PAGES_PER_BLOCK,?//nextblockofMBR????BINFS_BLOCKPAGES_PER_BLOCK,//SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))PAGES_PER_BLOCK,?//aligntoblock
?????????????????????????????PART_BINFS,
?????????????????????????????TRUE,
?????????????????????????????PART_OPEN_ALWAYS);
第一个参数分区的起始sector?为(NK_START_BLOCK+1)PAGES_PER_BLOCK,
第二个参数分区的结束?sector为BINFS_BLOCKPAGES_PER_BLOCK,
第三个参数分区的格式为PART_BINFS,即BINFS格式,
第四个参数指示该分区为活动分区,fActive=TURE,
第五个参数PART_OPEN_ALWAYS指示如果分区不存在就创建该分区,存在就OPEN该分区,返回分区句柄。
?
HANDLEBP_OpenPartition(DWORDdwStartSector,DWORDdwNumSectors,DWORDdwPartType,BOOLfActive,DWORDdwCreationFlags)
{
???????DWORDdwPartIndex;
???????BOOLfExists;
?
???????ASSERT(g_pbMBRSector);
???????
???????if(!IsValidMBR()){
???????????DWORDdwFlags=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:InvalidMBR.?Cannotopenexistingpartition0x%x./r/n"),dwPartType));
???????????????returnINVALID_HANDLE_VALUE;
???????????}
???????????
???????????RETAILMSG(1,(TEXT("OpenPartition:InvalidMBR.?Formattingflash./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:PartitionExists=0x%xforpart0x%x./r/n"),fExists,dwPartType));
???????if(fExists){
???????????//Partitionwasfound.?
???????????if(dwCreationFlags==PART_CREATE_NEW)
???????????????returnINVALID_HANDLE_VALUE;
???????????
???????????if(g_partStateTable[dwPartIndex].pPartEntry==NULL){
???????????????//Openpartition.?Ifthisisthebootsectionpartition,thenfilepointerstartsafterMBR
???????????????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)
????????????returnCreatePartition(dwStartSector,dwNumSectors,dwPartType,fActive,dwPartIndex);
?????????else????????
??????????????????return(HANDLE)&g_partStateTable[dwPartIndex];???????????
???????}
???????else{
?
???????????//Iftherearealready4partitions,orcreationflagspecifiedOPEN_EXISTING,fail.
???????????if((dwPartIndex==NUM_PARTS)||(dwCreationFlags==PART_OPEN_EXISTING))
???????????????returnINVALID_HANDLE_VALUE;
?
???????????//Createnewpartition
???????????returnCreatePartition(dwStartSector,dwNumSectors,dwPartType,fActive,dwPartIndex);
???????}
?
???????returnINVALID_HANDLE_VALUE;
???????
}
进入函数,首先做的事就是检测MBR的有效性。通过函数IsValidMBR()实现。
检测MBR的有效性,首先要知道MBR保存在哪里,前面说过NANDFLASH的第0BLOCK,第1Sector为主引导扇区,也就是MBR,但是NAND如果被当作启动芯片,○地址一般被BOOTLOADER代码占据,MBR只有放在后面的BLOCK中。所以我把第0?个BLOCK放NBOOT,第1个BLOCK放TOC,第2个BLOCK放EBOOT,第3个BLOCK保留,第4个BLOCK就放MBR。
staticBOOLIsValidMBR()
{
???//ChecktoseeiftheMBRisvalid
???//MBRblockisalwayslocatedatlogicalsector0
???g_dwMBRSectorNum=GetMBRSectorNum();???????
?
???RETAILMSG(1,(TEXT("IsValidMBR:MBRsector=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")));
???????returnFALSE;?
???}???
???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
staticDWORDGetMBRSectorNum()
{
???DWORDdwBlockNum=3,dwSector=0;
???SectorInfosi;
???????
???while(dwBlockNum ?
???????if(!IS_BLOCK_UNUSABLE(dwBlockNum)){
???????????dwSector=dwBlockNumg_FlashInfo.wSectorsPerBlock;
???????????
???????????if(!FMD_ReadSector(dwSector,NULL,&si,1)){
???????????????RETAILMSG(1,(TEXT("GetMBRSectorNum:Couldnotreadsector0x%x./r/n"),dwSector));
???????????????returnINVALID_ADDR;
???????????}
???????????//Checktoseeiflogicalsectornumberis0
???????????if(si.dwReserved1==0){
????????????//RETAILMSG(1,(TEXT("dwBlockNum=%d/r/n"),dwBlockNum));
???????????????returndwSector;
???????????}
???????}
?
???????dwBlockNum++;
?
???}
?
???returnINVALID_ADDR;
}
这里dwBlockNum直接给了个3,因为NBOOT,TOC,EBOOT已经把前三个BLOCK用了。所以MBR的选择直接排除了前三个BLOCK了。
#defineIS_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);。
?
BOOLBP_LowLevelFormat(DWORDdwStartBlock,DWORDdwNumBlocks,DWORDdwFlags)
{
???dwNumBlocks=min(dwNumBlocks,g_FlashInfo.dwNumBlocks);
?
???RETAILMSG(1,(TEXT("fly::EnterLowLevelFormat[0x%x,0x%x]./r/n"),dwStartBlock,dwNumBlocks));//dwStartBlock+dwNumBlocks-1));
?
???//Erasealltheflashblocks.
???if(!EraseBlocks(dwStartBlock,dwNumBlocks,dwFlags))
???????return(FALSE);
?
???//Determinefirstgoodstartingblock
???while(IS_BLOCK_UNUSABLE(dwStartBlock)&&dwStartBlock ???????dwStartBlock++;
???}
?
???if(dwStartBlock>=g_FlashInfo.dwNumBlocks){
???????RETAILMSG(1,(TEXT("BP_LowLevelFormat:nogoodblocks/r/n")));???????
???????returnFALSE;
???}
?
???//MBRgoesinthefirstsectorofthestartingblock.?Thiswillbelogicalsector0.
???g_dwMBRSectorNum=dwStartBlockg_FlashInfo.wSectorsPerBlock;
?
???RETAILMSG(1,(TEXT("fly:g_dwMBRSectorNum=%d/r/n"),g_dwMBRSectorNum));
?
???//CreateanMBR.
???CreateMBR();
???return(TRUE);
}
在对NANDFLASH进行低格时,主要对坏块的处理。if(!EraseBlocks(dwStartBlock,dwNumBlocks,dwFlags))检测每一个Sector,每个BLOCK只要有一个Sector不能读写这个块都会被处理成坏块,这样才能保证系统的稳定性。在函数的最后调用了???CreateMBR();来创建一个MBR。staticBOOLCreateMBR()
{
???//This,plusavalidpartitiontable,isalltheCEpartitionmanagerneedstorecognize
???//theMBRasvalid.Itdoesnotcontainbootcode.
?
???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;
?
???//Zerooutpartitiontablesothatmsparttreatsentriesasempty.
???memset(g_pbMBRSector+PARTTABLE_OFFSET,0,sizeof(PARTENTRY)NUM_PARTS);
?
???returnWriteMBR();
?
}??当然。因为还没有进行分区,这里写入的MBR分区表部分是空的。staticBOOLWriteMBR()
{
???DWORDdwMBRBlockNum=g_dwMBRSectorNum/g_FlashInfo.wSectorsPerBlock;
?
???//dwMBRBlockNum=1;
?
???RETAILMSG(1,(TEXT("WriteMBR:MBRblock=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);
???????
???//Noneedtocheckreturn,sinceafailedreadmeansdatahasn''tbeenwrittenyet.
???ReadBlock(dwMBRBlockNum,g_pbBlock,g_pSectorInfoBuf);
?
???if(!FMD_EraseBlock(dwMBRBlockNum)){
???????RETAILMSG(1,(TEXT("CreatePartition:errorerasingblock0x%x/r/n"),dwMBRBlockNum));
???????returnFALSE;
???}
?
???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:MBRblock=0x%x./r/n"),dwMBRBlockNum));
?
???if(!WriteBlock(dwMBRBlockNum,g_pbBlock,g_pSectorInfoBuf)){
???????RETAILMSG(1,(TEXT("CreatePartition:couldnotwritetoblock0x%x/r/n"),dwMBRBlockNum));
???????returnFALSE;
???}
?
???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也写入成功后就可以开始新建分区了。
/?CreatePartition
?
??Createsanewpartition.?Ifitisabootsectionpartition,thenitformats
??flash.
?
??ENTRY
??????dwStartSector-Logicalsectortostartthepartition.?NEXT_FREE_LOCif?
??????????nonespecified.?
??????dwNumSectors-Numberoflogicalsectorsofthepartition.?USE_REMAINING_SPACE
??????????toindicatetotakeuptherestofthespaceontheflashforthatpartition.
??????dwPartType-Typeofpartitiontocreate.
??????fActive-TRUEindicatestocreatetheactivepartition.?FALSEfor
??????????inactive.
??????dwPartIndex-IndexofthepartitionentryontheMBR
?
??EXIT
??????Handletothepartitiononsuccess.?INVALID_HANDLE_VALUEonerror.
?/
?
staticHANDLECreatePartition(DWORDdwStartSector,DWORDdwNumSectors,DWORDdwPartType,BOOLfActive,DWORDdwPartIndex)
{
???DWORDdwBootInd=0;
?
???RETAILMSG(1,(TEXT("CreatePartition:EnterCreatePartitionfor0x%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;???
?
????//Ifstartsectorisinvalid,itmeansfindnextfreesector
???if(dwStartSector==NEXT_FREE_LOC){???????
???????dwStartSector=FindFreeSector();
???????if(dwStartSector==INVALID_ADDR){
???????????RETAILMSG(1,(TEXT("CreatePartition:can''tfindfreesector./r/n")));
???????????returnINVALID_HANDLE_VALUE;
???????}
?
???????//Startextendedpartitiononablockboundary
???????if((dwPartType==PART_EXTENDED)&&(dwStartSector%g_FlashInfo.wSectorsPerBlock)){
???????????dwStartSector=(dwStartSector/g_FlashInfo.wSectorsPerBlock+1)g_FlashInfo.wSectorsPerBlock;
???????}
???}
?
???//Ifnumsectorsisinvalid,filltherestofthespaceup
???if(dwNumSectors==USE_REMAINING_SPACE){
?
???????DWORDdwLastLogSector=LastLogSector();
???????if(dwLastLogSector==INVALID_ADDR)
???????????returnINVALID_HANDLE_VALUE;
?
???????//DeterminethenumberofblockstoreservefortheFALcompactionwhencreatinganextendedpartition.
???????DWORDdwReservedBlocks=g_FlashInfo.dwNumBlocks/PERCENTAGE_OF_MEDIA_TO_RESERVE;
???????if((dwReservedBlocks=g_FlashInfo.dwNumBlocks/PERCENTAGE_OF_MEDIA_TO_RESERVE) ???????????dwReservedBlocks=MINIMUM_FLASH_BLOCKS_TO_RESERVE;
???????}
???????
???????dwNumSectors=dwLastLogSector-dwStartSector+1-dwReservedBlocksg_FlashInfo.wSectorsPerBlock;
???}
??
???if(!AreSectorsFree(dwStartSector,dwNumSectors)){
???????RETAILMSG(1,(TEXT("fly:::::CreatePartition:sectors[0x%x,0x%x]requestedareoutofrangeortakenbyanotherpartition/r/n"),dwStartSector,dwNumSectors));
???????returnINVALID_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''tmarksectorinfo./r/n")));
???????????returnINVALID_HANDLE_VALUE;
???????}
???}
?
???if(!WriteMBR())
???????returnINVALID_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。staticDWORDLastLogSector()
{
???if(g_dwLastLogSector){
??????returng_dwLastLogSector;
???}
?
???DWORDdwMBRBlock=g_dwMBRSectorNum/g_FlashInfo.wSectorsPerBlock;
???DWORDdwUnusableBlocks=dwMBRBlock;
?
???for(DWORDi=dwMBRBlock;i ???????if(IS_BLOCK_UNUSABLE(i))
???????????dwUnusableBlocks++;
???}
???
???g_dwLastLogSector=(g_FlashInfo.dwNumBlocks-dwUnusableBlocks)g_FlashInfo.wSectorsPerBlock-1;
?
???RETAILMSG(1,(TEXT("fly:::LastLogSector:Lastlogsectoris: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);?准备分区信息写入分区表。
/?AddPartitionTableEntry
?
??Generatesthepartitionentryforthepartitiontableandcopiestheentry
??intotheMBRthatisstoredinmemory.
??
?
??ENTRY
??????entry-indexintopartitiontable
??????startSector-startinglogicalsector
??????totalSectors-totallogicalsectors
??????fileSystem-typeofpartition
??????bootInd-byteinpartitionentrythatstoresvariousflagssuchas
??????????activeandread-onlystatus.
?
??EXIT
?/
?
staticvoidAddPartitionTableEntry(DWORDentry,DWORDstartSector,DWORDtotalSectors,BYTEfileSystem,BYTEbootInd)
{
???PARTENTRYpartentry={0};
???AddrstartAddr;
???AddrendAddr;
?
???ASSERT(entry<4);
?
???//nocheckingwithdiskinfoandstart/totalsectorsbecauseweallow
???//boguspartitionsfortestingpurposes
?
???//initiallyknownpartitiontableentry
???partentry.Part_BootInd=bootInd;
???partentry.Part_FileSystem=fileSystem;
???partentry.Part_StartSector=startSector;
???partentry.Part_TotalSectors=totalSectors;
?
???//logicalblockaddressesforthefirstandfinalsector(startonthesecondhead)
???startAddr.type=LBA;
???startAddr.lba=partentry.Part_StartSector;
???endAddr.type=LBA;
???endAddr.lba=partentry.Part_StartSector+partentry.Part_TotalSectors-1;
?
???//translatetheLBAaddressestoCHSaddresses
???startAddr=LBAtoCHS(&g_FlashInfo,startAddr);
???endAddr=LBAtoCHS(&g_FlashInfo,endAddr);
?
???//startingaddress
???partentry.Part_FirstTrack=(BYTE)(startAddr.chs.cylinder&0xFF);
???partentry.Part_FirstHead=(BYTE)(startAddr.chs.head&0xFF);
???//lower6-bits==sector,upper2-bits=cylinderupper2-bitsof10-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,upper2-bits=cylinderupper2-bitsof10-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(LogicalBlockAddr)与这种地址互相转换的函数LBAtoCHS,CHSToLBA。AddrLBAtoCHS(FlashInfopFlashInfo,Addrlba){???Addrchs;???DWORDtmp=pFlashInfo->dwNumBlockspFlashInfo->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;}
AddrCHStoLBA(FlashInfopFlashInfo,Addrchs){???Addrlba;
???lba.type=LBA;???lba.lba=((chs.chs.cylinderpFlashInfo->dwNumBlocks+chs.chs.head)???????pFlashInfo->wSectorsPerBlock)+chs.chs.sector-1;
returnlba;}
如果分区的格式有只读属性,则通过WriteLogicalNumbers()函数写分区的Sectorinfo,把这部分空间保护起来。
staticBOOLWriteLogicalNumbers(DWORDdwStartSector,DWORDdwNumSectors,BOOLfReadOnly)
{
???DWORDdwNumSectorsWritten=0;
?
???DWORDdwPhysSector=Log2Phys(dwStartSector);
???DWORDdwBlockNum=dwPhysSector/g_FlashInfo.wSectorsPerBlock;
???DWORDdwOffset=dwPhysSector%g_FlashInfo.wSectorsPerBlock;
???
???while(dwNumSectorsWritten ?
???????//Ifbadblock,movetothenextblock
???????if(IS_BLOCK_UNUSABLE(dwBlockNum)){
???????????dwBlockNum++;
???????????continue;
???????}
?
???????memset(g_pbBlock,0xff,g_dwDataBytesPerBlock);
???????memset(g_pSectorInfoBuf,0xff,sizeof(SectorInfo)g_FlashInfo.wSectorsPerBlock);
???????//Noneedtocheckreturn,sinceafailedreadmeansdatahasn''tbeenwrittenyet.
???????ReadBlock(dwBlockNum,g_pbBlock,g_pSectorInfoBuf);
???????if(!FMD_EraseBlock(dwBlockNum)){
???????????returnFALSE;
???????}
?
???????DWORDdwSectorsToWrite=g_FlashInfo.wSectorsPerBlock-dwOffset;
???????PSectorInfopSectorInfo=g_pSectorInfoBuf+dwOffset;
?
???????//Ifthisisthelastblock,thencalculatesectorstowriteifthereisn''tafullblocktoupdate
???????if((dwSectorsToWrite+dwNumSectorsWritten)>dwNumSectors)
???????????dwSectorsToWrite=dwNumSectors-dwNumSectorsWritten;
???????
???????for(DWORDiSector=0;iSector ???????????//Assertreadonlybysettingbitto0topreventwear-levelingbyFAL
???????????if(fReadOnly)
???????????????pSectorInfo->bOEMReserved&=~OEM_BLOCK_READONLY;
???????????//SettowritecompletedsoFALcanmapthesector?
???????????pSectorInfo->wReserved2&=~SECTOR_WRITE_COMPLETED;???????
???????????//Writethelogicalsectornumber
???????????pSectorInfo->dwReserved1=dwStartSector+dwNumSectorsWritten;???????????
???????}
???????if(!WriteBlock(dwBlockNum,g_pbBlock,g_pSectorInfoBuf))
???????????returnFALSE;
???????
???????dwOffset=0;
???????dwBlockNum++;
???}
???returnTRUE;
}
这就是为什么系统启动后,我们无法写入文件的BINFS文件系统格式分区的原因了。而FAT格式就可以。最后调用WriteMBR()完全MBR的写入,分区完毕。
让我们继续回到BP_OpenPartition函数中,如果从一开始IsValidMBR()就检测到有效的MBR,GetPartitionTableIndex(dwPartType,fActive,&dwPartIndex);获得分区表。和dwPartIndex分区表的索引号。
staticBOOLGetPartitionTableIndex(DWORDdwPartType,BOOLfActive,PDWORDpdwIndex)
{
???PPARTENTRYpPartEntry=(PPARTENTRY)(g_pbMBRSector+PARTTABLE_OFFSET);
???DWORDiEntry=0;
???
???for(iEntry=0;iEntry ???????if((pPartEntry->Part_FileSystem==dwPartType)&&(((pPartEntry->Part_BootInd&PART_IND_ACTIVE)!=0)==fActive)){
???????????pdwIndex=iEntry;
???????????returnTRUE;
???????}
???????if(!IsValidPart(pPartEntry)){
???????????pdwIndex=iEntry;
???????????returnFALSE;
???????}
???}
?
???returnFALSE;
}
?
重要结构:PARTENTRY
//endofmasterbootrecordcontains4partitionentries
typedefstruct_PARTENTRY{
???????BYTE???????????Part_BootInd;??????????//If80hmeansthisisbootpartition
???????BYTE???????????Part_FirstHead;????????//Partitionstartingheadbased0
???????BYTE???????????Part_FirstSector;??????//Partitionstartingsectorbased1
???????BYTE???????????Part_FirstTrack;???????//Partitionstartingtrackbased0
???????BYTE???????????Part_FileSystem;???????//Partitiontypesignaturefield
???????BYTE???????????Part_LastHead;?????????//Partitionendingheadbased0
???????BYTE???????????Part_LastSector;???????//Partitionendingsectorbased1
???????BYTE???????????Part_LastTrack;????????//Partitionendingtrackbased0
???????DWORD??????????Part_StartSector;??????//Logicalstartingsectorbased0
???????DWORD??????????Part_TotalSectors;?????//Totallogicalsectorsinpartition
}PARTENTRY;
分区表就是通过这个结构写入MBR,起始地址,分区大小,分区格式,对应结构写入MBR所在的Sector就可以了。在检测有效分区时staticBOOLIsValidPart(PPARTENTRYpPartEntry)
{
???return(pPartEntry->Part_FileSystem!=0xff)&&(pPartEntry->Part_FileSystem!=0);
}
就是通过对分区表文件系统格式的判断了。
?
?
把NAND后面的空间,全部分为一个FAT格式的分区。
???//
???//createextendedpartitioninwhateverisleft
???//
???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:Failedtoopen/createExtendedpartition/r/n");
???}
|
|