观's profileTo the world,you may jus...PhotosBlogListsMore ![]() | Help |
|
04/11/2009 NandFlash的分区实现提到分区就需要知道MBR,了解分区表。什么是MBR硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASH由BLOCK和Sector组成,所以NANDFLASH的第0 BLOCK,第1 Sector为主引导扇区,FDISK程序写到该扇区的内容称为主引导记录(MBR)。该记录占用512个字节,它用于硬盘启动时将系统控制权交给用户指定的,并在分区表中登记了的某个操作系统区。 MBR的组成 一个扇区的硬盘主引导记录MBR由如图6-15所示的4个部分组成。
MBR中的分区信息结构 占用512个字节的MBR中,偏移地址01BEH--01FDH的64个字节,为4个分区项内容(分区信息表)。它是由磁盘介质类型及用户在使用 FDISK定义分区说确定的。在实际应用中,FDISK对一个磁盘划分的主分区可少于4个,但最多不超过4个。每个分区表的项目是16个字节,其内容含义 如表6-19所示。
EBOOT中对NAND分区主要代码,eboot目录下的fmd.cpp文件,与NAND驱动基本相同,所以,要对NAND进行分区,就得对NAND驱动非常熟悉。透彻了解。然后就是E:\WINCE500\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BOOTPART\bootpart.cpp文件了。该文件主要通过调用NANDFLASH的读写操作来写入MBR,也是今天主要的分析对象。
主要函数。/* 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 blockPART_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该分区,返回分区句柄。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;//flyRETAILMSG(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;}//flyRETAILMSG(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 MBRg_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);elsereturn (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 partitionreturn 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 0g_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的那个Sectorstatic 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 0if (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), SECTOR_TO_BLOCK(dwNumSectors), dwFlags);再创建分区,CreatePartition (dwStartSector, dwNumSectors, dwPartType, fActive, 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 blockwhile (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, dwNumBlocks, 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, 0, 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, 0xff, g_dwDataBytesPerBlock);memset (g_pSectorInfoBuf, 0xff, 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_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: MBR block = 0x%x.\r\n"), dwMBRBlockNum));if (!WriteBlock (dwMBRBlockNum, g_pbBlock, 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 dwNumSectors, DWORD dwPartType, BOOL fActive, 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 sectorif (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 boundaryif ((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 upif (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"), dwStartSector, dwNumSectors));return INVALID_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'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, dwStartSector, dwNumSectors, (BYTE)dwPartType, (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 entrypartentry.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 addressesstartAddr = LBAtoCHS(&g_FlashInfo, startAddr);endAddr = LBAtoCHS(&g_FlashInfo, endAddr);// starting addresspartentry.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。Addr LBAtoCHS(FlashInfo *pFlashInfo, Addr lba){Addr chs;DWORD tmp = pFlashInfo->dwNumBlocks * pFlashInfo->wSectorsPerBlock;chs.type = CHS;chs.chs.cylinder = (WORD)(lba.lba / tmp); // 柱面,应该始终是0tmp = lba.lba % tmp;chs.chs.head = (WORD)(tmp / pFlashInfo->wSectorsPerBlock); // 块地址chs.chs.sector = (WORD)((tmp % pFlashInfo->wSectorsPerBlock) + 1); // 扇区+1return chs;}Addr CHStoLBA(FlashInfo *pFlashInfo, Addr chs){Addr lba;lba.type = LBA;lba.lba = ((chs.chs.cylinder * pFlashInfo->dwNumBlocks + chs.chs.head)* pFlashInfo->wSectorsPerBlock)+ chs.chs.sector - 1;return lba;}如果分区的格式有只读属性,则通过WriteLogicalNumbers()函数写分区的Sectorinfo,把这部分空间保护起来。static BOOL WriteLogicalNumbers (DWORD dwStartSector, DWORD dwNumSectors, 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 blockif (IS_BLOCK_UNUSABLE (dwBlockNum)) {dwBlockNum++;continue;}memset (g_pbBlock, 0xff, g_dwDataBytesPerBlock);memset (g_pSectorInfoBuf, 0xff, sizeof(SectorInfo) * g_FlashInfo.wSectorsPerBlock);// No need to check return, since a failed read means data hasn't been written yet.ReadBlock (dwBlockNum, g_pbBlock, 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 updateif ((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 FALif (fReadOnly)pSectorInfo->bOEMReserved &= ~OEM_BLOCK_READONLY;// Set to write completed so FAL can map the sectorpSectorInfo->wReserved2 &= ~SECTOR_WRITE_COMPLETED;// Write the logical sector numberpSectorInfo->dwReserved1 = dwStartSector + dwNumSectorsWritten;}if (!WriteBlock (dwBlockNum, g_pbBlock, g_pSectorInfoBuf))return FALSE;dwOffset = 0;dwBlockNum++;}return TRUE;}这就是为什么系统启动后,我们无法写入文件的BINFS文件系统格式分区的原因了。而FAT格式就可以。最后调用WriteMBR()完全MBR的写入,分区完毕。让我们继续回到BP_OpenPartition函数中,如果从一开始IsValidMBR()就检测到有效的MBR,GetPartitionTableIndex(dwPartType, fActive, &dwPartIndex);获得分区表。和dwPartIndex分区表的索引号。static BOOL GetPartitionTableIndex (DWORD dwPartType, BOOL fActive, 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 entriestypedef struct _PARTENTRY {BYTE Part_BootInd; // If 80h means this is boot partitionBYTE Part_FirstHead; // Partition starting head based 0BYTE Part_FirstSector; // Partition starting sector based 1BYTE Part_FirstTrack; // Partition starting track based 0BYTE Part_FileSystem; // Partition type signature fieldBYTE Part_LastHead; // Partition ending head based 0BYTE Part_LastSector; // Partition ending sector based 1BYTE Part_LastTrack; // Partition ending track based 0DWORD Part_StartSector; // Logical starting sector based 0DWORD 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");}TrackbacksThe trackback URL for this entry is: http://giwawe.spaces.live.com/blog/cns!92AFEF096943066B!260.trak Weblogs that reference this entry
|
|
|