提到分区就不得不提到MBR,不得不提到分区表。 http://blog.csdn.net/shuiii/archive/2009/02/17/3901692.aspx 什么是MBR 硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASH由BLOCK和Sector组成,所以NANDFLASH的第0 BLOCK,第1 Sector为主引导扇区,FDISK程序写到该扇区的内容称为主引导记录(MBR)。该记录占用512个字节,它用于硬盘启动时将系统控制权交给用户指定的,并在分区表中登记了的某个操作系统区。 MBR的组成
图6-15 MBR的组成结构图 MBR中的分区信息结构 占用512个字节的MBR中,偏移地址01BEH--01FDH的64个字节,为4个分区项内容(分区信息表)。它是由磁盘介质类型及用户在使用 FDISK定义分区说确定的。在实际应用中,FDISK对一个磁盘划分的主分区可少于4个,但最多不超过4个。每个分区表的项目是16个字节,其内容含义 如表6-19所示。
EBOOT中对NAND分区主要代码,eboot目录下的fmd.cpp文件,与NAND驱动基本相同,所以,要对NAND进行分区,就得对NAND驱动非常熟悉。透彻了解。然后就是
主要函数。 /* BP_OpenPartition * * Opens/creates a partition depending on the creation flags. If it is opening * and the partition has already been opened, then it returns a handle to the * opened partition. Otherwise, it loads the state information of that partition * into memory and returns a handle. * * ENTRY * dwStartSector - Logical sector to start the partition. NEXT_FREE_LOC if none * specified. Ignored if opening existing partition. * dwNumSectors - Number of logical sectors of the partition. USE_REMAINING_SPACE * to indicate to take up the rest of the space on the flash for that partition (should * only be used when creating extended partitions). This parameter is ignored * if opening existing partition. * dwPartType - Type of partition to create/open. * fActive - TRUE indicates to create/open the active partition. FALSE for * inactive. * dwCreationFlags - PART_CREATE_NEW to create only. Fail if it already * exists. PART_OPEN_EXISTING to open only. Fail if it doesn't exist. * PART_OPEN_ALWAYS creates if it does not exist and opens if it * does exist. * * EXIT * Handle to the partition on success. INVALID_HANDLE_VALUE on error. */ 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, DWORD dwImageLength, DWORD dwLaunchAddr) 在把SDRAM中的NK烧写到NAND中去之前,先创建一个BINFS分区。 hPart = BP_OpenPartition( (NK_START_BLOCK+1)*PAGES_PER_BLOCK, // next block of MBR 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为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 part 0x%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 section partition, 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 specified OPEN_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,第1 Sector为主引导扇区,也就是MBR,但是NAND如果被当作启动芯片,○地址一般被BOOTLOADER代码占据,MBR只有放在后面的BLOCK中。所以我把第0 个BLOCK放NBOOT,第1个BLOCK放TOC,第2个BLOCK放EBOOT,第3个BLOCK保留,第4个BLOCK就放MBR。 static BOOL IsValidMBR() { // Check to see if the MBR is valid // MBR block 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-----return FALSE-------------------/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 () { DWORD dwBlockNum = 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 sector 0x%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++;
}
return INVALID_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。 |
Eboot 中给nandflash分区实现
最新推荐文章于 2018-11-15 10:18:01 发布