LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2116|回复: 7

分析mbr中的分区表,手工计算每个分区大小

[复制链接]
发表于 2006-11-7 06:28:27 | 显示全部楼层 |阅读模式
这个帖子源于我发的另一篇询问“怎样把知道把grub安装到mbr还是boot sector上”的文章,结论是我还没有什么快捷办法来得知grub的安装信息,只好用dd导出mbr进行分析了,顺便照着网上介绍的计算了一下其中的分区表(DPT)部分,最后用win下的winhex验证了一下。这里把计算方法和大家分享一下,如果有错误请帮忙告诉我。
先说说我前一个帖子的问题:
用dd导出mbr后如果是grub则里面应该有“GRUB Geom Hard Disk Read Error”字符串,如果是ntldr则里面没有,取而代之的可能是“Missing operating system”字符串(ntldr的我没试验)。

下面看看我分析DPT的过程。

我的分区结构:
hda   标称为60G的硬盘
+
|--- hda1   linux /boot  ext3
|--- hda2   winxp c:     ntfs
|--- hda3   extension
  +
  |--- hda5   linux swap    swap
  |--- hda6   linux /       ext3
  |--- hda7   winxp d:      ntfs

我的mbr中的DPT(disk partition table)部分,也就是从hda的第1个sector后偏移为0x01BE开始,到0x01FD结束的区域,大小为 0x01FD - 0x01BE + 0x1 = 0x40 = 64(dec) Byte。
这64B分为4个16B,每一个16B保存一个主分区的信息,所以最多可以有4个主分区,而我的hda只划出了3个主分区:hda1, hda2, hda3
每个16B都包含它描述的分区的8个信息,下面分别用(1)~(8)讲解。下面用(dec)标注的是10进制数,其余的大多为16进制或2进制,看情况自己判断。


1. 先看我的DPT中第1个16B,它描述的是我的 hda1 - linux /boot 分区:
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01B0   hh hh hh hh hh hh hh hh hh hh hh hh hh hh 00 01
01C0   01 00 83 FE 3F 0C 3F 00 00 00 8E 2F 03 00

(1)
offset from 01BE: 00
offset: 01BE
80表示该分区为active,而我的是00,表示我的hda1不为active。

(2)
offset from 01BE: 01
offset: 01BF
表示开始磁头,我的为 01

(3)
offset from 01BE: 02,03
offset: 01C0,01C1
表示开始扇区和开始柱面,我的为01 00,具体这么算:
把 01 00 化为二进制,
0000 0001,0000 0000
其中第一个字节的低6位是开始扇区,这里就是 000001
在第二个字节高位前再添加第一个字节的最高两位构成开始柱面,这里是 00 0000 0000
开始柱面是个10位二进制数,最大能表示2^10-1 = 1023(dec)

(4)
offset from 01BE: 04
offset: 01C2
指定系统ID(System ID) 定义了分区的类型,一般的有:
07: HPFS/NTFS
83: linux
82: linux swap
01: FAT32
06: FAT16
...
这里我的为83,表示我的hda1 - ext3

(5)
offset from 01BE: 05
offset: 0x01C3
结束磁头,我的为 FE = 254(dec)

(6)
offset from 01BE: 06,07
offset: 01C4,01C5
表示结束扇区和结束柱面,我的为3F 0C,算法和计算开始扇区、柱面一样,
把 3F 0C 化为二进制,
0011 1111,0000 1100
其中第一个字节的低6位是结束扇区,这里就是 111111 = 63(dec)
在第二个字节高位前再添加第一个字节的最高两位构成结束柱面,这里是 00 00001100 = 12(dec)

(7)
offset from 01BE: 08,09,0A,0B
offset: 01C6,01C7,01C8,01C9
这4个字节构成一个双字(DWORD)整数,表示相对扇区数(Relative Sectors),即从该磁盘的开始到该分区的开始的位移量(以扇区为单位)。注意,这里的数据采用little-edian的方式存贮DWORD数(数学上的低位放在低字节),所以这里的3F 00 00 00 就表示数学上的0x0000003F = 63(dec)

(8)
offset from 01BE: 0C,0D,0E,0F
offset: 01CA,01CB,01CC,01CD
这4个字节构成一个DWORD整数,表示总扇区数(Total Sectors),即该分区中的扇区总数,这里为 8E 2F 03 00,表示数学上的0x00032F8E = 208782(dec),一个扇区为512B,则这个分区的大小为: 208782 * 512B = 106896384 B = 104391 KB = 101.944 MB,这就是我的hda1 - linux /boot的大小。

2. 再看看我的第2个16B,它描述的是我的 hda2 - winxp c: 分区
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01C0   HH HH HH HH HH HH HH HH HH HH HH HH HH HH 80 00
01D0   01 0D 07 FE BF DC CD 2F 03 00 D0 7E B0 00

(1)
offset from 01CE: 00
offset: 01CE
80表示该分区为active,这就是有人说的grub把win盘置为active的结果,也就是grub引导项中makeactive指令起作用的地方。

(2)
offset from 01CE: 01
offset: 01CF
表示开始磁头,这里为00,不要为hda2的磁头号排在hda1之前感到奇怪,我开始也感觉到奇怪,可是仔细想想就明白了,应该是这么一个3维量<柱面号, 磁头号, 扇区>,柱面号才是主序(可以联系2维数组来考虑),所以柱面号才是递增的,而不是磁头号。

(3)
offset from 01CE: 02,03
offset: 01D0,01D1
开始扇区和开始柱面,这里为 01 0D,化为二进制,
0000 0001,0000 1101
第一个字节的低6位是开始扇区,这里就是 000001
在第二个字节高位前再添加第一个字节的最高两位构成开始柱面,这里是 00 0000 1101 = 13

(4)
offset from 01CE: 04
offset: 01D2
指定系统ID(System ID)
这里我的为07,表示我的hda2 - ntfs

(5)
offset from 01CE: 05
offset: 0x01D3
结束磁头,我的为 FE = 254(dec)

(6)
offset from 01CE: 06,07
offset: 01D4,01D5
结束扇区和结束柱面,我的为BF DC,化为二进制,
1011 1111,1101 1100
其中第一个字节的低6位是结束扇区,这里就是 111111 = 63(dec)
在第二个字节高位前再添加第一个字节的最高两位构成结束柱面,这里是 10 11011100 = 732(dec)

(7)
offset from 01CE: 08,09,0A,0B
offset: 01D6,01D7,01D8,01D9
相对扇区数(Relative Sectors),这里的CD 2F 03 00 就表示数学上的0x00032FCD = 208845(dec)

(8)
offset from 01CE: 0C,0D,0E,0F
offset: 01DA,01DB,01DC,01DD
总扇区数(Total Sectors),这里为 D0 7E B0 00,表示数学上的0x00B07ED0 = 11566800(dec),则这个分区的大小为: 11566800 * 512B = 5922201600 B = 5.515 GB,这就是我的hda2 - winxp c:的大小。

还有一个hda3 - extension的主分区,就是能包含若干个逻辑分区的家伙,这里就不贴出来了,大家回去自己试试吧。
(上面的计算结果均在winhex下验证过,不过原理上哪里有错误的还请高人指教)
 楼主| 发表于 2006-11-7 06:41:13 | 显示全部楼层
怎么搞的,我打上去的连续的空格字符都没有了,没有缩进了,而且在offset中写的16进制还错位了呢,trim()还真厉害-_-||
重打一下,用hh补空格,错位就没办法了

1. 先看我的DPT中第1个16B,它描述的是我的 hda1 - linux /boot 分区:
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01B0  hh hh hh hh hh hh hh hh hh hh hh hh hh hh 00 01
01C0 01 00 83 FE 3F 0C 3F 00 00 00 8E 2F 03 00

2. 再看看我的第2个16B,它描述的是我的 hda2 - winxp c: 分区
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01C0  hh hh hh hh hh hh hh hh hh hh hh hh hh hh 80 00
01D0  01 0D 07 FE BF DC CD 2F 03 00 D0 7E B0 00
回复 支持 反对

使用道具 举报

发表于 2006-11-7 14:46:30 | 显示全部楼层
check_partition in linux-0.95/kernel/blk_drv/hd.c
回复 支持 反对

使用道具 举报

发表于 2006-11-7 22:07:30 | 显示全部楼层
先收藏了,回头再学习。
-----------------------------
原来只会算几个G的小硬盘,后来出了大硬盘就再没研究过。
回复 支持 反对

使用道具 举报

发表于 2006-11-7 22:27:42 | 显示全部楼层
同意楼上,先收藏。我刚从/boot把backup_mbr这个文件拷出来。
回复 支持 反对

使用道具 举报

发表于 2006-11-7 22:29:59 | 显示全部楼层
蛮专业的,路过的都要看看啊。
回复 支持 反对

使用道具 举报

发表于 2006-11-8 04:54:19 | 显示全部楼层
Post by silon212
怎么搞的,我打上去的连续的空格字符都没有了,没有缩进了,而且在offset中写的16进制还错位了呢,trim()还真厉害-_-||
重打一下,用hh补空格,错位就没办法了

1. 先看我的DPT中第1个16B,它描述的是我的 hda1 - linux /boot 分区:
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01B0  hh hh hh hh hh hh hh hh hh hh hh hh hh hh 00 01
01C0 01 00 83 FE 3F 0C 3F 00 00 00 8E 2F 03 00

2. 再看看我的第2个16B,它描述的是我的 hda2 - winxp c: 分区
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01C0  hh hh hh hh hh hh hh hh hh hh hh hh hh hh 80 00
01D0  01 0D 07 FE BF DC CD 2F 03 00 D0 7E B0 00
归究 sir 里的文字分析器,用全角打的空格才能正常。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-8 13:35:37 | 显示全部楼层
感谢d00m3d的提示,现在空格对齐问题改好了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表