Eboot 中给nandflash分区实现

提到分区就不得不提到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的组成
一个扇区的硬盘主引导记录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--01FF的2个字节值为结束标志55AA,如果该标志错误系统就不能启动。

0000-0088

 

Master Boot Record

主引导程序

主引导

程序

0089-01BD

出错信息数据区

数据区

01BE-01CD

分区项1(16字节)

 

分区表

 

01CE-01DD

分区项2(16字节)

01DE-01ED

分区项3(16字节)

01EE-01FD

分区项4(16字节)

01FE

55

结束标志

01FF

AA

图6-15 MBR的组成结构图

MBR中的分区信息结构

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

 

存贮字节位

内容及含义

第1字节

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

第2、3、4字节

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

    磁头号——第2字节;

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

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

第5字节

分区类型符。

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

    06H——FAT16基本分区;

    0BH——FAT32基本分区;

    05H——扩展分区;

    07H——NTFS分区;

    0FH——(LBA模式)扩展分区(83H为Linux分区等)。

第6、7、8字节

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

    磁头号——第6字节;

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

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

第9、10、11、12字节

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

第13、14、15、16字节

本分区的总扇区数。

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 block

                              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该分区,返回分区句柄。

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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值