配色: 字号:
eboot中nandflash分区实现
2013-01-08 | 阅:  转:  |  分享 
  
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");

???}



献花(0)
+1
(本文系狂神逛街首藏)