精华内容
下载资源
问答
  • MBR详解

    2013-03-21 09:25:52
    MBR详解
  • GPT与MBr详解与区别

    2016-03-01 10:34:24
    Windows系统下GPT与MBr详解,可查阅!
  • 硬盘知识,硬盘逻辑结构,硬盘MBR详解 硬盘知识,硬盘逻辑结构,硬盘MBR详解
  • 硬盘知识 硬盘逻辑结构 硬盘MBR详解 pdf 文档格式,很清晰的版本。
  • 在硬盘中,硬盘的0柱面0磁头第一个1扇区称为主引导扇区,也叫主引导记录-MBR(main boot record),其中MBR是以下三个部分组成 1、Bootloader,主引导程序(446个字节) 2、Dpt(Disk Partition table),硬盘分区表...

    简介

    在硬盘中,硬盘的0柱面0磁头第一个1扇区称为主引导扇区,也叫主引导记录-MBR(main boot record),其中MBR是以下三个部分组成
    1、Bootloader,主引导程序(446个字节)
    2、Dpt(Disk Partition table),硬盘分区表(64个字节)
    3、扇区结尾标志(55aa)(个字节)
    总共512字节,前446个字节是主引导记录,是bios加电自检后要运行的代码,中间64字节为分区表。
    简单的来说MBR=bootloader+dpt(64)+结尾标志(55aa)。其中dpt磁盘分区表(64字节,每16个字节为一组,一共4组),

    详解

    1、引导代码
    上图中黄色框内的部分即为引导程序,占扇区前446字节。计算机在上电完成BIOS自检后,会将该主引导扇区加载到内存中并执行前面446字节的引导程序,引导程序首先会在分区表中查找活动分区,若存在活动分区,则根据活动分区的偏移量找到该活动分区上的引导扇区的地址,并将该引导扇区加载到内存中,同时检查该引导扇区的有效性,然后根据该引导扇区的规则去引导操作系统。在一些非启动磁盘上,MBR引导代码可能都是0,这对磁盘使用没有任何影响。
    2、分区表
    上图中蓝色框内的部分即为分区表,占扇区中间64字节。分区表是磁盘管理最重要的部分,通过分区表信息来定位各个分区,访问用户数据。分区表包含4个分区项,每一个分区项通过位置偏移、分区大小来唯一确定一个主分区或者扩展分区。每个分区项占16字节,包括引导标识、起始和结束位置的CHS参数、分区类型、开始扇区、分区大小等,具体描述如下表所示:
    这里需要注意的是,分区项的第1个字节表示该分区是否是活动分区,即是否包含系统引导扇区,用来引导操作系统。每个磁盘只能同时有一个活动分区,活动分区的引导指示符是0x80,其他均为0x00;尽管我们可以通过一些工具来手动修改引导指示符,但是引导程序只会查找并使用第一个引导指示符为0x80的活动分区。
    3、结束标志
    下图中最后的"55 AA"即为结束标志,或者称魔数,占扇区最后2字节。每次执行系统引导代码时都会检查MBR主引导扇区最后2字节是否是"55 AA",若是,则继续执行后续的程序,否则,则认为这是一个无效的MBR引导扇区,停止引导系统。

    在这里插入图片描述补充:磁盘格式可对照下表进行查找
    在这里插入图片描述其他技术知识:

    Linux系统下dd命令详解

    MBR和GPT磁盘分区表类型对比详解

    展开全文
  • 一、MBR和主引导扇区 首先简要介绍MBR和主引导扇区的关系。 主引导扇区是硬盘0号柱面,0号磁头的第一个扇区,大小为512字节。(注:硬盘可以用柱面、磁头和扇区定位) MBR,占用主引导扇区的前446字节,紧随其...

     

    一、MBR和主引导扇区

    首先简要介绍MBR和主引导扇区的关系。

               主引导扇区是硬盘0号柱面,0号磁头的第一个扇区,大小为512字节。(注:硬盘可以用柱面、磁头和扇区定位)

               MBR,占用主引导扇区的前446字节,紧随其后的64字节是分区表DPT,最后还剩两个字节则恒为55AA,表示结束符号。(下图,演示了它们的位置关系)

     

     

    然后,具体说一说MBR和分区表。

               MBR,全称为Master Boot Record,即硬盘的主引导记录。MBR,共446字节,一般在操作系统安装时写入,但它并不属于操作系统。MBR就是一段引导程序,用于检测磁盘的分区合法性和加载操作系统,它的重要作用就是识别活动分区,并引导操作系统。

     

              分区表DPT,共64字节,记录了硬盘有多少分区以及分区的各种属性。由于一个分区的信息要占用16字节,所以分区表只能定义4个分区,这就是为什么我们说硬盘一般最多只能分为4个主分区(这里说“一般”是对基本磁盘而言,而对于动态磁盘则无此限制,但大部分都在使用基本磁盘,可以暂不考虑 )。

     

              计算机开机后BIOS加电自检,一切正常后,找到第一个启动设备(一般就是硬盘),然后从这个启动设备的主引导扇区读取MBR。MBR这段引导程序识别活动分区,引导操作系统。

     

     

    二、主分区、扩展分区、逻辑分区

     

              正如前面所讲,主分区是由主引导扇区中64字节的分区表所定义的,最多只能有4个。但为了满足更多分区的需求,变产生了扩展分区。形式上,如果拥有扩展分区,就必须牺牲一个主分区,而且最多有一个扩展分区,也就是说:主分区+扩展分区<=4 and 扩展分区<=1。因此扩展分区也可以看成一种特殊的主分区。

     

              但扩展分区并不可以直接使用,扩展分区又必须以逻辑分区的形式出现,可以这样认为:扩展分区包含着若干逻辑分区,而且至少包含一个。

     

              扩展分区中的逻辑分区是以链式存在的。即每一个逻辑分区都记录着下一个逻辑分区的位置信息,依次串联。事实上每一个逻辑分区都有一个和主引导扇区类似的引导扇区,引导扇区里有类似的分区表。该分区表记录了该分区的信息和一个指针,指向下一个逻辑分区的引导扇区。

     

              因此,逻辑分区是借鉴了主分区的方法,相当于在一个主分区下面建立了若干级“主分区”。从上面的描述,猫猫推测,逻辑分区是建立在操作系统级别,由操作系统识别的。另一个可以预测的现象是:一旦某一个逻辑分区损害,跟在它后面的所有逻辑分区都将丢失,而前面的逻辑分区去可以保留。这也是链式结果的特点。

     

     

    三、活动分区、系统分区、启动分区、引导分区

     

                这四个术语和前面三个不同,前面三个是讲述分区的“物理”形成。而这四个术语描述了分区的功能,并且更易混淆。

     

               首先,根据Windows XP随机帮助文档看,引导分区就是启动分区,两者是同一概念,所以下面就只讨论活动分区、系统分区和启动分区。

     

     系统分区和启动分区比较。

                这是两个极易混淆的概念,因为两者的含义似乎和它们的名字正好颠倒了。Windows帮助文件的术语表里是这样解释他们的:”系统分区,包含加载 Windows(例如,Ntldr、Osloader、Boot.ini、Ntdetect.com)所需的硬件特定文件的分区。系统分区可以(但不是必须)与启动分区相同。启动分区,包含 Windows 操作系统及其支持文件的分区。启动分区可以(但不是必须)与系统分区相同。

              “ 看起来是很糊涂,但说的简单些就是:系统分区包含Ntldr、Osloader、Boot.ini、Ntdetect.com等文件,而启动分区包含Windows和system32文件。所以,真正包含操作系统内核文件的分区是启动分区,包含操作系统引导文件的确实系统分区,这是要特别注意的一点。 有些人就疑问了,我的Ntldr、Osloader、Boot.ini、Ntdetect.com和Windows、system32文件都在C盘,那是怎么回事?这很容易解释,你的C盘既是系统分区也是启动分区,只安装一个操作系统的计算机大都属于这种情况 ,所以微软在括号里说“但不是必须”。

    展开全文
  • 主引导记录MBR详解

    2015-08-11 17:31:00
    2019独角兽企业重金招聘Python工程师标准>>> ...

    http://blog.csdn.net/htf15/article/details/7219126

    转载于:https://my.oschina.net/goopand/blog/490849

    展开全文
  • 主引导分区MBR 详解

    千次阅读 2012-12-04 11:53:46
    什么是MBR 硬盘的0柱面、0磁头、1扇区称为主引导扇区,NANDFLASH由BLOCK和Sector组成,所以NANDFLASH的第0 BLOCK,第1 Sector为主引导扇区,FDISK程序写到该扇区的内容称为主引导记录(MBR)。该记录占用512个字节...

    什么是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。

     

    如果没有检测到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 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, 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 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"), 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 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。
    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 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 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_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 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");

        }

    展开全文
  • wowocock哥哥的98 MBR详解

    千次阅读 2012-08-09 17:57:57
    虽然MBR的反汇编代码是16位程序,而16位程序已经没有任何研究价值了,但是研究过MBR后可以让你对系统的引导过程和操作系统是如何启动的有一个更深的认识,这里是98 MBR的反汇编代码,其中wowocock哥哥已经加了注释:...
  • 详细讲解了硬盘的基础知识和结构 这是个不错的资料 很有帮助
  • mbr详解(转)

    千次阅读 2008-06-25 21:00:00
    在分析MBR的结构之前,先有来看看计算机的引导顺序(System Boot Sequence) Step 1. 内部电源打开,初始化,等待一小段时间用来产生稳定的电流。如果主板芯片和CPU收到了不符合规定的电流,将自动产生一个RESET信号。...
  • 因为最近要做数据恢复一类的项目,所以想好好研究一下硬盘这样的外存介质的存储结构,结果第一次就看到了MBR。发现一篇博客,写的特别好,特来和大家共享。  原文:...
  • 详解MBR

    2010-11-09 22:27:00
    首先要明确,MBR是“DOS分区体系”下的概念,“DOS分区体系”是最常见的分区体系,Microsoft DOS、XP、Linux以及基于IA32平台的FreeBSD和OpenBSD等操作系统都使用DOS分区体系。  MBR,全称为Master Boot...
  • Windows磁盘MBR结构详解

    2017-04-14 15:20:04
    在之前的文章Windows存储管理之磁盘结构详解中介绍了Windows的磁盘结构和MBR。本文将对Windows Basic Disk中的MBR的结构进行介绍,帮助读者更好的了解Windows系统中的磁盘存储。Windows Basic Disk中的MBR:Master ...
  • MBR分区表详解

    万次阅读 2018-09-27 17:16:39
    1.MBR分区 MBR(Main Boot Record 主引导记录区)位于整个硬盘的0磁道0柱面1扇区。在512字节的主引导扇区中,MBR只占用了其中的446个字节,另外的64个字节...硬盘分区DPT详解 分区表由4项组成,每项16个字节(B...
  • Windows磁盘MBR结构详解 – Basic Disk篇

    千次阅读 2013-02-15 16:07:25
    Windows磁盘MBR结构详解 – Basic Disk篇   ##转载请在文首保留原文出处:EMC中文支持论坛 - https://community.emc.com/go/chinese 介绍    在之前的文章Windows存储管理之磁盘结构详解中介绍了...
  • 详解硬盘MBR

    2014-03-31 10:47:27
    硬盘是现在计算机上最常用的存储器之一。我们都知道,计算机之所以神奇,是因为它具有高速分析...当我们创建分区时,就已经设置好了硬盘的各项物理参数,指定了硬盘主引导记录(即Master Boot Record,一般简称为MBR
  • MBR和GPT分区详解

    千次阅读 2017-07-25 08:35:59
    MBR 方案的局限:  主引导记录 (MBR) 分区方案是多数操作系统采用的传统分区方案。MBR 本身完全保存在硬盘的第一个扇区(512 字节)。在该空间中,MBR 的前 440 字节用于引导程序。BIOS 在计算机启动时读取并...
  • linux中的MBR记录详解

    千次阅读 2013-03-14 11:15:53
    大家是不是经常会谈论到MBR(main boot record)。MBR是由bootloader、dpt、结尾标志组成的。简单的来说MBR=bootloader+dpt+结尾标志(55 aa)。其中bootloader即引导记录(446字节),dpt磁盘分区表(64字节) 结尾标志...
  • MBR分区结构 0号扇区内容 扩展分区 GPT分区结构 文件系统 文件系统的定义 文件系统的结构 raid磁盘阵列技术 raid -0 raid -1 raid -5 raid -10 和raid -01 思维导图 本篇只涉及到导图的右侧,只...
  • 目前磁盘分区有两种形式:GPT分区和MBR分区。MBR相比而言比较常见,大多数磁盘都是采用这种分区形式。MBR分区和GPT分区的区别在于:MBR最多只支持4个主分区,GPT能够支持128个主分区。然而GPT分区形式在重装系统需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,136
精华内容 2,054
热门标签
关键字:

mbr详解