Fdisk 输出看似荒谬的 CHS 值

Fdisk 输出看似荒谬的 CHS 值

采取以下 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 元组的值是0x200x210x00

0x20很简单:它相当于第32个头。

0x21包含起始扇区和起始柱面。0x21-> 0b00100001,给出33扇区,以及柱面的第 8 位和第 9 位,结果是00b00)。

将 的圆柱位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 告诉我的那样)。

相关内容