Eboot 中给nandflash分区实现

来源:互联网 发布:淘宝自己的店铺在哪里 编辑:程序博客网 时间:2024/05/19 19:13

提到分区就不得不提到MBR,不得不提到分区表。

什么是MBR

硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASHBLOCKSector组成,所以NANDFLASH的第0 BLOCK,第1 Sector为主引导扇区,FDISK程序写到该扇区的内容称为主引导记录(MBR)。该记录占用512个字节,它用于硬盘启动时将系统控制权交给用户指定的,并在分区表中登记了的某个操作系统区。

 

MBR的组成
一个扇区的硬盘主引导记录MBR由如图6-15所示的4个部分组成。
·
主引导程序(偏移地址0000H--0088H),它负责从活动分区中装载,并运行系统引导程序。
·
出错信息数据区,偏移地址0089H--00E1H为出错信息,00E2H--01BDH全为0字节。
·
分区表(DPT,Disk Partition Table)含4个分区项,偏移地址01BEH--01FDH,每个分区表项长16个字节,共64字节为分区项1、分区项2、分区项3、分区项4
·
结束标志字,偏移地址01FE--01FF2个字节值为结束标志55AA,如果该标志错误系统就不能启动。

0000-0088

 

Master Boot Record

主引导程序

主引导

程序

0089-01BD

出错信息数据区

数据区

01BE-01CD

分区项116字节)

 

分区表

 

01CE-01DD

分区项216字节)

01DE-01ED

分区项316字节)

01EE-01FD

分区项416字节)

01FE

55

结束标志

01FF

AA


6-15 MBR的组成结构图

MBR中的分区信息结构


   
占用512个字节的MBR中,偏移地址01BEH--01FDH64个字节,为4个分区项内容(分区信息表)。它是由磁盘介质类型及用户在使用 FDISK定义分区说确定的。在实际应用中,FDISK对一个磁盘划分的主分区可少于4个,但最多不超过4个。每个分区表的项目是16个字节,其内容含义 如表6-19所示。
6-19 分区项表(16字节)内容及含义

 

存贮字节位

内容及含义

1字节

引导标志。若值为80H表示活动分区,若值为00H表示非活动分区。

234字节

本分区的起始磁头号、扇区号、柱面号。其中:

    磁头号——2字节;

    扇区号——3字节的低6位;

    柱面号——为第3字节高2+4字节8位。

5字节

分区类型符。

    00H——表示该分区未用(即没有指定);

    06H——FAT16基本分区;

    0BH——FAT32基本分区;

    05H——扩展分区;

    07H——NTFS分区;

    0FH——LBA模式)扩展分区(83HLinux分区等)。

678字节

本分区的结束磁头号、扇区号、柱面号。其中:

    磁头号——6字节;

    扇区号——7字节的低6位;

    柱面号——7字节的高2+8字节。

9101112字节

本分区之前已用了的扇区数。

13141516字节

本分区的总扇区数。

 

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格式分区)。

 

BOOLWriteRegionsToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORDdwLaunchAddr)

在把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 (NK_START_BLOCK+1)*PAGES_PER_BLOCK

第二个参数分区的结束 sectorBINFS_BLOCK*PAGES_PER_BLOCK

第三个参数分区的格式为PART_BINFS,即BINFS格式,

第四个参数指示该分区为活动分区,fActive = TURE

第五个参数PART_OPEN_ALWAYS指示如果分区不存在就创建该分区,存在就OPEN该分区,返回分区句柄。

 

HANDLEBP_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, thenfile 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 )

              returnCreatePartition (dwStartSector, dwNumSectors, dwPartType, fActive,dwPartIndex);

           else         

                   return(HANDLE)&g_partStateTable[dwPartIndex];           

        }

        else {

 

            // If there are already 4partitions, 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 BLOCKNBOOT,第1BLOCKTOC,第2BLOCKEBOOT,第3BLOCK保留,第4BLOCK就放MBR

staticBOOL IsValidMBR()

{

    // Check to see if the MBR is valid

    // MBR block is always located at logicalsector 0

    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-----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

staticDWORD 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 sectornumber is 0

            if (si.dwReserved1 == 0) {

              //RETAILMSG(1,(TEXT("dwBlockNum=%d/r/n"),dwBlockNum));

                return dwSector;

            }

        }

 

        dwBlockNum++;

 

    }

 

    return INVALID_ADDR;

}

这里dwBlockNum直接给了个3,因为NBOOTTOCEBOOT已经把前三个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(DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)

{

    dwNumBlocks = min (dwNumBlocks,g_FlashInfo.dwNumBlocks);

 

    RETAILMSG(1,(TEXT("fly::EnterLowLevelFormat [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 goodblocks/r/n")));       

        return FALSE;

    }

 

    // MBR goes in the first sector of thestarting block.  This will be logicalsector 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();来创建一个MBRstatic BOOL CreateMBR()

{

    // This, plus a valid partition table, isall the CE partition manager needs to recognize

    // the MBR as valid. It does not containboot 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 msparttreats 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: 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);

       

    // No need to check return, since a failedread 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: MBRblock = 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 isa 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 thespace 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.

 */

 

staticHANDLE CreatePartition (DWORD dwStartSector, DWORD dwNumSectors, DWORDdwPartType, 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 meansfind 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 blockboundary

        if ((dwPartType == PART_EXTENDED)&& (dwStartSector % g_FlashInfo.wSectorsPerBlock)) {

            dwStartSector = (dwStartSector /g_FlashInfo.wSectorsPerBlock + 1) * g_FlashInfo.wSectorsPerBlock;

        }

    }

 

    // If num sectors is invalid, fill the restof the space up

    if (dwNumSectors == USE_REMAINING_SPACE) {

 

        DWORD dwLastLogSector =LastLogSector();

        if (dwLastLogSector == INVALID_ADDR)

            return INVALID_HANDLE_VALUE;

 

        // Determine the number of blocks toreserve 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 ofrange 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();函数获得最后一个逻辑Sectorstatic 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* 每个BLOCKSector保存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 theentry

 *  intothe 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

 */

 

staticvoid 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 andstart/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 firstand 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 CHSaddresses

    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
Addr LBAtoCHS(FlashInfo *pFlashInfo, Addr lba)
{
    Addr chs;
    DWORD tmp = pFlashInfo->dwNumBlocks *pFlashInfo->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

    return 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 block

        if (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 afailed 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, thencalculate 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 bitto 0 to prevent wear-leveling by FAL

            if (fReadOnly)

                pSectorInfo->bOEMReserved&= ~OEM_BLOCK_READONLY;

            // Set to write completed so FALcan map the sector 

            pSectorInfo->wReserved2 &=~SECTOR_WRITE_COMPLETED;       

            // Write the logical sector number

            pSectorInfo->dwReserved1 =dwStartSector + dwNumSectorsWritten;           

        }

        if (!WriteBlock (dwBlockNum, g_pbBlock,g_pSectorInfoBuf))

            return FALSE;

       

        dwOffset = 0;

        dwBlockNum++;

    }

    return TRUE;

}

这就是为什么系统启动后,我们无法写入文件的BINFS文件系统格式分区的原因了。而FAT格式就可以。最后调用WriteMBR()完全MBR的写入,分区完毕。

让我们继续回到BP_OpenPartition函数中,如果从一开始IsValidMBR()就检测到有效的MBRGetPartitionTableIndex(dwPartType,fActive, &dwPartIndex);获得分区表。和dwPartIndex分区表的索引号。

staticBOOL 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 entries

typedefstruct _PARTENTRY {

        BYTE            Part_BootInd;           // If 80h means this is bootpartition

        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 isleft

    //

    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");

    }

原创粉丝点击