采取以下 fdisk 输入:
o # Create DOS/MBR partition table.
n # Create new partition.
p # Partition type
1 # Partition ID
2048 # Starting sector
+4M # Ending sector
t # Assign said partition to a FAT12 filesystem.
1 # FAT12 filesystem.
a # Mark said partition as bootable.
w # Write partition table.
现在,让我们看一下 MBR,特别是分区项(分区项从0x80
第一行末尾附近开始)。
000001b0: 0000 0000 0000 0000 4a2f 9087 0000 8020 ........J/.....
000001c0: 2100 01a2 2200 0008 0000 0020 0000 0000 !..."...... ....
000001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
根据 MBR 部分条目的布局(给定这里和这里),我们可以从中获取 CHS 元组的值是0x20
、0x21
、0x00
。
0x20
很简单:它相当于第32个头。
0x21
包含起始扇区和起始柱面。0x21
-> 0b00100001
,给出33
扇区,以及柱面的第 8 位和第 9 位,结果是0
(0b00
)。
将 的圆柱位0b00
(来自0x21
)和结合起来0b00000000
,我们得到0b0000000000
圆柱体。总而言之,我们最终得到了 的起始头三十二,起始扇区为33,起始气缸0。
当我尝试通过 BIOS 中断加载此 CHS 时,系统会抱怨 CHS 无效(我可以正常读取其他扇区)。我猜想这是因为磁头是 32;毕竟,你为什么要有 16 盘硬盘呢?
总结
Fdisk 输出带有 CHS 值的 MBR。
我的问题是,我是否误解了 CHS 值是如何编码到分区条目中的,或者这是否是 fdisk 的一个怪癖。
答案1
根据 fdisk 本身,C/H/S 值确实应该是:
命令(m 获取帮助):x 专家命令(m 获取帮助):p 磁盘 test.disk:64 MiB,67108864 字节,131072 个扇区 单位:扇区 1 * 512 = 512 字节 扇区大小(逻辑/物理):512 字节 / 512 字节 I/O 大小(最小/最佳):512 字节 / 512 字节 磁盘标签类型:dos 磁盘标识符:0xd771f127 设备启动开始结束扇区ID类型 开始-C/H/S 结束-C/H/S属性 测试.磁盘1 * 2048 10239 8192 1 FAT12 0/32/33 0/162/34 80
fdisk 不会尝试匹配实际的磁盘几何形状——这在 C/H/S 限制内长期以来是不可能的,因此它所做的就是计算一些值,这些值在转换回 LBA 时会给出正确的结果。
来自 util-linux 的代码include/pt-mbr.h
:
static inline void
dos_partition_sync_chs(struct dos_partition *p,
unsigned long long int part_offset,
unsigned int geom_sectors,
unsigned int geom_heads)
{
unsigned long long int start = part_offset + dos_partition_get_start(p);
unsigned long long int stop = start + dos_partition_get_size(p) - 1;
unsigned int spc = geom_heads * geom_sectors;
if (start / spc > 1023)
start = spc * 1024 - 1;
if (stop / spc > 1023)
stop = spc * 1024 - 1;
p->bc = (start / spc) & 0xff;
p->bh = (start / geom_sectors) % geom_heads;
p->bs = ((start % geom_sectors + 1) & 0x3f) |
(((start / spc) >> 2) & 0xc0);
p->ec = (stop / spc) & 0xff;
p->eh = (stop / geom_sectors) % geom_heads;
p->es = ((stop % geom_sectors + 1) & 0x3f) |
(((stop / spc) >> 2) & 0xc0);
}
来自 util-linux 的评论libfdisk/src/dos.c
:
/*
* Conversion from C/H/S to LBA is defined by formula:
* LBA = (c * N_heads + h) * N_sectors + (s - 1)
* Let o to be:
* o = LBA - (s - 1)
* Then formula can be expressed as:
* o = (c * N_heads + h) * N_sectors
*/
为什么你需要 16 盘片的硬盘?
你假装拥有 16 盘片硬盘,以便表示比 C/H/S 系统通常可以表示的更多的磁盘空间。由于每个盘片只有 64ki 柱面 × 255 扇区 × 2 个磁头,因此您只能达到每个盘片约 8 GB,而显然磁盘现在已经略微超出了这一范围。
操作系统或固件并不单独控制每个磁头,它只是通过 ATA 命令将数字传递给磁盘并取回数据,因此它实际上并不关心无论磁盘是否有 255 个磁头。磁盘本身也不再有 255 个磁头——磁盘现在要做的第一件事是使用公式将 C/H/S 值转换为线性 LBA 地址(假设磁盘一开始就被赋予了 C/H/S 而不是 LBA)。
因此,甚至在 BIOS 和 OS 转而直接处理 LBA 之前,使用“荒谬的” C/H/S 值来访问比格式通常允许的更多的磁盘空间就已经很常见了。
目前所有的操作系统都忽略了 MBR 中的 C/H/S 字段,只处理 LBA,显然这就是“OnTrack 磁盘管理器”以前做在 MS-DOS 中。(另外,据我所知,SCSI 磁盘从一开始就不支持 C/H/S,它们始终是仅 LBA。)我有点确定,现在您能找到的几乎任何 BIOS 都通过“扩展 INT 13h”原生支持 LBA(正如 Google 告诉我的那样)。