Eboot 中给nandflash分区实现
作者:SUKHOI27SMK 转自:http://www.voidcn.com/article/p-zkbanita-kt.html 提到分区就不得不提到MBR,不得不提到分区表。 什么是MBR 硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASH由BLOCK和Sector组成,所以NANDFLASH的第0 BLOCK,第1 Sector为主引导扇区,FDISK程序写到该扇区的内容称为主引导记录(MBR)。该记录占用512个字节,它用于硬盘启动时将系统控制权交给用户指定的,并在分区表中登记了的某个操作系统区。 ? MBR的组成
MBR中的分区信息结构
?
? 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 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,dwPartType,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,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,&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。 ? 如果没有检测到MBR,则先对NANDFLASH进行低级格式化。BP_LowLevelFormat (SECTOR_TO_BLOCK(dwStartSector),dwFlags);再创建分区,CreatePartition (dwStartSector,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)); ? ??? // Erase all 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 good blocks/r/n")));??????? ??????? return FALSE; ??? } ? ??? // MBR goes 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)); ? ??? // Create an MBR. ??? CreateMBR(); ??? return(TRUE); } 在对NANDFLASH进行低格时,主要对坏块的处理。if (!EraseBlocks(dwStartBlock,dwFlags))检测每一个Sector,每个BLOCK只要有一个Sector不能读写这个块都会被处理成坏块,这样才能保证系统的稳定性。在函数的最后调用了??? CreateMBR();来创建一个MBR。static BOOL CreateMBR() { ??? // This,plus a valid partition table,is all the CE partition manager needs to recognize ??? // the MBR 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; ? ??? // Zero out partition table so that mspart treats entries as empty. ??? memset (g_pbMBRSector+PARTTABLE_OFFSET,sizeof(PARTENTRY) * NUM_PARTS); ? ??? return WriteMBR(); ? }??当然。因为还没有进行分区,这里写入的MBR分区表部分是空的。static BOOL WriteMBR() { ??? DWORD dwMBRBlockNum = 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,g_dwDataBytesPerBlock); ??? memset (g_pSectorInfoBuf,sizeof(SectorInfo) * g_FlashInfo.wSectorsPerBlock); ??????? ??? // No need to check return,since a failed read means data hasn't been written yet. ??? ReadBlock (dwMBRBlockNum,g_pbBlock,g_pSectorInfoBuf); ? ??? if (!FMD_EraseBlock (dwMBRBlockNum)) { ??????? RETAILMSG (1,(TEXT("CreatePartition: error erasing block 0x%x/r/n"),dwMBRBlockNum)); ??????? return FALSE; ??? } ? ??? memcpy (g_pbBlock + (g_dwMBRSectorNum % g_FlashInfo.wSectorsPerBlock) * g_FlashInfo.wDataBytesPerSector,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_pSectorInfoBuf)) { ??????? RETAILMSG (1,(TEXT("CreatePartition: could not write to block 0x%x/r/n"),dwMBRBlockNum)); ??????? return FALSE; ??? } ? ??? return TRUE; ??? } 在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 ?* ?*? Creates a new partition.? If it is a boot section partition,then it formats ?*? flash. ?* ?*? ENTRY ?*????? dwStartSector - Logical sector to start the partition.? NEXT_FREE_LOC if? ?*????????? none specified.? ?*????? 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. ?*????? dwPartType - Type of partition to create. ?*????? fActive - TRUE indicates to create the active partition.? FALSE for ?*????????? inactive. ?*????? dwPartIndex - Index of the partition entry on the MBR ?* ?*? EXIT ?*????? Handle to the partition on success.? INVALID_HANDLE_VALUE on error. ?*/ ? static HANDLE CreatePartition (DWORD dwStartSector,DWORD dwPartIndex) { ??? DWORD dwBootInd = 0; ? ??? RETAILMSG(1,(TEXT("CreatePartition: Enter CreatePartition for 0x%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 free sector./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 num sectors 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 compaction when 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"),dwNumSectors)); ??????? return INVALID_HANDLE_VALUE; ??? } ? ??? RETAILMSG(1,(TEXT("CreatePartition: Start = 0x%x,Num = 0x%x./r/n"),dwNumSectors)); ??? ??? AddPartitionTableEntry (dwPartIndex,(BYTE)dwPartType,(BYTE)dwBootInd); ? ??? if (dwBootInd & PART_IND_READ_ONLY) { ??????? if (!WriteLogicalNumbers (dwStartSector,TRUE)) { ??????????? RETAILMSG(1,(TEXT("CreatePartition: can't mark sector info./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。static DWORD LastLogSector() { ??? if (g_dwLastLogSector) { ?????? return g_dwLastLogSector; ??? } ? ??? DWORD dwMBRBlock = g_dwMBRSectorNum / g_FlashInfo.wSectorsPerBlock; ??? DWORD dwUnusableBlocks = 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)); ??? ??? return g_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,(BYTE)dwBootInd);准备分区信息写入分区表。 /*? AddPartitionTableEntry ?* ?*? Generates the partition entry for the partition table and copies the entry ?*? into the MBR that is stored in memory. ?*? ?* ?*? ENTRY ?*????? entry - index into partition table ?*????? startSector - starting logical sector ?*????? totalSectors - total logical sectors ?*????? fileSystem - type of partition ?*????? bootInd - byte in partition entry that stores various flags such as ?*????????? active and read-only status. ?* ?*? EXIT ?*/ ? static void AddPartitionTableEntry(DWORD entry,DWORD startSector,DWORD totalSectors,BYTE fileSystem,BYTE bootInd) { ?? ?PARTENTRY partentry = {0}; ??? Addr startAddr; ??? Addr endAddr; ? ??? ASSERT(entry < 4); ? ??? // no checking with disk info and start/total sectors because we allow ??? // bogus partitions 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 on the 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); ??? // lower 6-bits == sector,upper 2-bits = cylinder upper 2-bits of 10-bit cylinder # ??? partentry.Part_FirstSector = (BYTE)((startAddr.chs.sector & 0x3F) | ((startAddr.chs.cylinder & 0x0300) >> 2)); ? ??? // ending address: ??? partentry.Part_LastTrack = (BYTE)(endAddr.chs.cylinder & 0xFF); ??? partentry.Part_LastHead = (BYTE)(endAddr.chs.head & 0xFF); ??? // lower 6-bits == sector,upper 2-bits = cylinder upper 2-bits of 10-bit cylinder # ??? 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(Logical Block Addr)与这种地址互相转换的函数LBAtoCHS,CHSToLBA。 ??? chs.type = CHS; ??? return chs; Addr CHStoLBA(FlashInfo *pFlashInfo,Addr chs) ??? lba.type = LBA; return lba; 如果分区的格式有只读属性,则通过WriteLogicalNumbers()函数写分区的Sectorinfo,把这部分空间保护起来。 static BOOL WriteLogicalNumbers (DWORD dwStartSector,BOOL fReadOnly) { ??? DWORD dwNumSectorsWritten = 0; ? ??? DWORD dwPhysSector = Log2Phys (dwStartSector); ??? DWORD dwBlockNum = dwPhysSector / g_FlashInfo.wSectorsPerBlock; ??? DWORD dwOffset = 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,g_dwDataBytesPerBlock); ??????? memset (g_pSectorInfoBuf,sizeof(SectorInfo) * g_FlashInfo.wSectorsPerBlock); ??????? // No need to check return,since a failed read means data hasn't been written yet. ??????? ReadBlock (dwBlockNum,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 if there 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 by FAL ??????????? if (fReadOnly) ??????????????? pSectorInfo->bOEMReserved &= ~OEM_BLOCK_READONLY; ??????????? // Set to write completed so FAL can map the sector? ??????????? pSectorInfo->wReserved2 &= ~SECTOR_WRITE_COMPLETED;??????? ??????????? // Write the logical sector number ??????????? pSectorInfo->dwReserved1 = dwStartSector + dwNumSectorsWritten;??????????? ??????? } ??????? if (!WriteBlock (dwBlockNum,g_pSectorInfoBuf)) ??????????? return FALSE; ??????? ??????? dwOffset = 0; ??????? dwBlockNum++; ??? } ??? return TRUE; } 这就是为什么系统启动后,我们无法写入文件的BINFS文件系统格式分区的原因了。而FAT格式就可以。最后调用WriteMBR()完全MBR的写入,分区完毕。 让我们继续回到BP_OpenPartition函数中,如果从一开始IsValidMBR()就检测到有效的MBR,GetPartitionTableIndex(dwPartType,&dwPartIndex);获得分区表。和dwPartIndex分区表的索引号。 static BOOL GetPartitionTableIndex (DWORD dwPartType,PDWORD pdwIndex) { ??? PPARTENTRY pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET); ??? DWORD iEntry = 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; ??????? } ??? } ? ??? return FALSE; } ? 重要结构: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就可以了。在检测有效分区时static BOOL IsValidPart (PPARTENTRY pPartEntry) { ??? return (pPartEntry->Part_FileSystem != 0xff) && (pPartEntry->Part_FileSystem != 0); } 就是通过对分区表文件系统格式的判断了。 ? ? 把NAND后面的空间,全部分为一个FAT格式的分区。 ??? // ??? // create extended 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 to open/create Extended partition ***/r/n"); ??? } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |