引导扇区概念设计
一、打印信息设计
DX=XXXX 最关键的寄存器,含有接管控制时的盘号 DL。
boot=XXXX 表示接管控制的引导扇区的物理扇区号。
mbr0=XXXX 表示 MBR 所在的 BIOS 第 0 扇区的物理扇区号,它表示有多少个扇区被隐藏了。
boot 和 mbr0 应该是相等的,如果不相等,那就暴露出了变态的主板行为。
LBA 表示支持 LBA,如果不支持,则不显示。
S=XX 每道扇区数,它比较容易获得,只需要从 mbr0 开始有连续 64 个扇区的物理扇区号记录便可计算出来。
H=XX 磁头数,获得它要比获得 S 稍稍困难一些。
如果全部都用记录扇区号的方法,则确定 H 需要 8M 的扇区,这就与 S 一样容易获得了。但我们可以稍加改进。我们留出 1024 个扇区不记录物理扇区号(叫做 “自由扇区” 或 “空白扇区”),这样可以方便大家手动嵌入外部引导代码(grldr 或 ntldr)。
二、磁盘数据结构设计
扇区 0 的分区表指向扇区 63(作为分区的起始扇区,下同),而扇区 63 的分区表指向扇区 126,为了保险起见,扇区 126 也设置一个分区表,指向扇区 189。分区表与其对应的第一分区的距离总是 63 个扇区。这样,即使被两次隐藏,扇区 126 也能获得控制。第一次隐藏时,有可能扇区 0 至 63 中的某个扇区被当作 mbr0。但经过第二次隐藏,则有可能扇区 63 至 126 中的某个扇区被当作 mbr0。两次隐藏的总效果是,有可能扇区 0 - 126 中的某个扇区被当作 mbr0 了。我们在扇区 0 至 126 上都设置分区表,其第一分区都是指向其后的 63 扇区偏移。而扇区 127 至 189 的分区表则指向 8M 附近的实际分区数据。扇区 0 至 189 都记录着自己的物理扇区号。从扇区 190 至 1213,总共 1024 个扇区,不记录物理扇区号(即 “空白扇区”)。这个空间是 512K,用来放置外部引导代码(GRLDR 或 NTLDR)。接下来的连续扇区空间,一直延伸到 8M 附近的扇区 126 + 255×63,都记录物理扇区号。
总起来说,头部有 190 个扇区记录着扇区号,接着是 1024 个空白扇区,再往后又是连续记录扇区号的 (126+255×63 - 1213) 个扇区,其后又全都是空白扇区。
如果扇区号 0 - 126 之一获得控制,那么首先读柱面 0 的起始扇区 mbr0(即 C/H/S=0/0/1),这样可以得到 mbr0 的物理扇区号。
接着读柱面 1 的起始扇区 C/H/S=1/0/1。读之前显示信息 3 秒,防止死机或重启。有三种情况,分别讨论如下。
【情况一】
如果读柱面 1 的起始扇区时发生死机、重启,那就证明机器很变态,重启时用户按空格键来强制设定 C=1,这样就认为只有柱面 0,而避免去读柱面 1。如果没有死机但读出的数据无效,或者读取失败(CF=1),这都表明 C=1,即只有一个柱面。在这样的情况下,最大访问能力是 255×63=8M。还需要进一步确定 H 和 S 的值。
读扇区 C/H/S=0/1/1 可以确定 S 的值。如果死机、重启或出错、失败,则表明 H=1,即只有一个磁头。那么最大访问能力只有 63 个扇区了。因此,这种情况没有意义,什么事也干不成,直接放弃得了,就当成 “电脑根本不支持 U 盘启动” 来对待。用户明白这一情况后就有理由淘汰这样的机器了。
S 确定之后,怎么确定 H 的值?只有一个一个试验。读 C/H/S=0/n/1,成功后 H 就等于 (n+1)。其实,没必要确定 H 了,这是因为 C=1,因此 H 直接取最大值 255 就可以了。也就是说,在只有一个柱面的情况下,只要 S 是正确的,几何参数方面就没问题了,H 可以不管了。这一点正如在多柱面情况下 C 值不重要,只要知道 H 和 S 就 OK 了。用户对磁盘的使用,肯定只能尽量使用开头的扇区,否则总是危险的,即,当超出主板 BIOS 访问能力时,总是有死机、重启或出现其他异常情况的危险。因此,不用确定 H 了(取最大值 255),用户自己会尽量使用靠近开头的那些扇区,其 H 值当然也就比较小了。
【情况二】
如果柱面 1 最开头的那个扇区的物理扇区号是有记录的,则可以计算出柱面的长度(即,柱面长度=该扇区号 - mbr0)。
如果柱面长度大于 63,则每个柱面至少有 2 个磁道。于是可以读下一个磁道。现在可以放心地读柱面 0 的扇区 C/H/S=0/1/1,它肯定是有物理扇区号记录的。这样就知道了 S 的值了(S=该扇区号 - mbr0)。
如果柱面长度为 63 或更小,则有可能只有 1 个磁头。当 H=1 时,S=柱面长度,能确定 S。但问题是无法确定 H 是否为 1。
因此,我们冒险假定 H 大于 1,而去读 C/H/S=0/1/1。读之前显示信息 3 秒,如果发生死机或重启,就知道机器很变态了。于是就知道这个机器的 H=1 了。重启时按空格键即可强制以 H=1 来处理,而不再去读柱面 0 磁道 1 的起始扇区了。如果读取成功,可以计算出 S。因而 H 也可以算出来了。
我们还有一个(候选的)冒险方法,就是假定 H=1,S=(柱面长度)。这时,我们冒险读柱面 0 上的 S 个扇区。如果读取成功,并且每个扇区的物理扇区号都正确,那么就 OK 了。否则,一定是相反的情况,即 H 大于 1,此时又可以用前面的方法确定 S 的值了。如果读取时失败、死机、重启,那都证明 H 大于 1,因而重启时注意用键盘按键来控制。
【情况三】
如果柱面 1 上最开头的扇区没有记录物理扇区号,那么就知道柱面长度一定大于 63,因此和刚才的情况一样,可以确定 S 的值。由于柱面长度未知,因此,还需要一个步骤来确定 H 的值。我们先前已经知道,未记录扇区号的那些扇区号范围是从扇区 190 到扇区 1213。柱面 1 的起始扇区一定落在其中。那么柱面的长度的变化范围就是
最小值 = 190 - 126 = 64
最大值 = 1213 - 0 = 1213
柱面长度如果取最小值 64,那么柱面 20 的起始扇区的物理扇区号就是
20×64 + mbr0 = 1280 + mbr0
这一定落在我们事先已经记录扇区号的区域了。
柱面长度如果取最大值 1213,那么柱面 2 的起始扇区的物理扇区号就是
2×1213 + mbr0 = 2426 + mbr0
这也落在了已经记录扇区号的区域。
因此,无论如何,只要从柱面 2 到柱面 20 逐个读取柱面的起始扇区(最多读 19 次),一定可以碰到一个记录了物理扇区号的扇区。这样,就可以算出 H 的值了。如果读取失败或死机,则表明 BIOS 的访问能力不足 1.44M(仅有 1.213M)。读取时,屏幕有信息显示,让用户能够看到。如果发生死机或重启,用户记住最后一行信息,就可以知道 BIOS 的访问能力太差了。用户甚至有理由淘汰这样的机器了。
这样,H 和 S 都得到了。在屏幕上打印出 H 和 S 的值,圆满完成第一阶段的任务。
第二阶段,其实简单得很,直接加载位于物理扇区号 190 开始的外部引导器代码(grldr 或 ntldr)即可。
|