Eboot 中给nandflash分区实现.docx
- 文档编号:5496195
- 上传时间:2022-12-17
- 格式:DOCX
- 页数:20
- 大小:56.16KB
Eboot 中给nandflash分区实现.docx
《Eboot 中给nandflash分区实现.docx》由会员分享,可在线阅读,更多相关《Eboot 中给nandflash分区实现.docx(20页珍藏版)》请在冰豆网上搜索。
Eboot中给nandflash分区实现
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,如果该标志错误系统就不能启动。
图6-15MBR的组成结构图
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,也是今天主要的分析对象。
主要函数。
/*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,//nextblockofMBRBINFS_BLOCK*PAGES_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_BLOCK*PAGES_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=dwBlockNum*g_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=dwStartBlock*g_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: errorerasin
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Eboot 中给nandflash分区实现 nandflash 分区 实现
![提示](https://static.bdocx.com/images/bang_tan.gif)