不点所言极是。 |
前面提到,grub4dos 在内部代码以及公开的菜单中,不该访问设备上靠后的扇区。下面接着就相关问题谈一些个人管见。 比如说,从分区表上可以(粗略地)知道盘的大小。此时仅仅访问了分区表,也即,扇区 0。因此,这没问题。但接下来,不可以直接就去访问靠后的扇区。 同理,在访问某个分区时,从分区的 BPB 就可以了解到分区的最后一个扇区的扇区号。但不可以直接就去访问分区的最后扇区。换句话说,除非必须访问靠后的那些扇区(比如说要访问的文件正好位于靠后的扇区),否则,就永远不要去碰它们。 既然我们连分区表上指明存在的扇区,都不敢(也不会)去随便访问,那么,我们的代码就是非常非常可靠的,或者换个词强调一下,叫做“绝对可靠”。世上没有绝对,这只是相对中的绝对而已,只是一个说法罢了。 谁要是把分区表弄得比实际磁盘还要大,那不是故意找事吗? 你只要不是故意找事,grub4dos 的代码就不会访问到磁盘介质之外的扇区。 如果正常访问磁盘文件的话,不可能跑去访问磁盘以外的扇区。因为磁盘文件本身也不会占据磁盘以外的某个扇区。 换句话说,只要 grub4dos 的开发者不去访问磁盘尾部的扇区,那就不会有问题。如果有问题,那必然是 BIOS 的问题,它在磁盘中部就不让我们访问了(失败或死机),而这是根本没法处理的,用户只能自认倒霉。比如,著名的 137G 极限,用户都会自己处理(可以认为,用户都已经自认倒霉、接受现实了)。而 grub4dos 的开发者对此并无任何对策。没听说有哪位使用者,仅仅因为他的电脑有 137G 极限就把位于 137G 之后的分区全删除(或隐藏)的。 应该分清哪些事情是该由 grub4dos 开发者去做的,而哪些事情是不该由开发者去做的。不该做的事情,如果去做,只能做坏,而不能做好。反之,那些只能做坏、不能做好的事情,也正是不该做的事情。 不同的人有不同的思路,以上是个人的思维方式,无所谓对和错。错误之处,请鉴别指正。 |
本帖最后由 不点 于 2019-6-18 07:25 编辑 2011yaya2007777 发表于 2019-6-17 10:37 关于“越界读盘死机”,谈谈个人的分析和看法。 此问题属于 BIOS 的问题,从根本上讲是无解的。要想解,就得找 BIOS 厂家去解,否则就是无解。尤其是,当 BIOS 厂家本来就是故意那么做的时候,那就更是无解了。 BIOS 怎么样的行为,与分区表完全无关,至少目前没有发现 BIOS 读盘时还得去看分区表的设置。所以,粗略地讲,(对于读硬盘来说)无论要读很大的盘还是很小的盘,BIOS 都是一样的行为,就是说,它能读多少个扇区,那就是多少个扇区:它该在哪个扇区处失败,就在哪个扇区处失败;它该在哪个扇区处死机,就在哪个扇区处死机。跟你费心把苦地去调整分区表参数,是一点关系都没有。无论 grub4dos 的开发者还是用户,都没有任何可以参考的对策。只有一个办法,那就是尽量只使用靠前的扇区,避免使用靠后的扇区。而什么叫做“靠前”和“靠后”,这也是模糊的。一个不作恶的 BIOS,无论你是使用哪个扇区,它都不会有问题。一个存心作恶的 BIOS,它只支持很小的扇区号。在 USB 的情况,曾经碰到只支持 720KB(连 1M 都没有)的 BIOS。对于硬盘的情况,一般来说,硬盘通常是支持 LBA 的,所以,情况比 USB 要好。但很多硬盘都会有 137G 的极限,这个是常识了,姑且不算是作恶。而对于访问不到的那些较大的扇区号码,有些 BIOS 是失败退出,给出出错信息,这很好。但有些 BIOS 是直接死机,或者长时间无响应(假死),个人认为,这就属于作恶范畴了。 有些 grub4dos 的应用者,喜欢让 grub4dos 去访问磁盘尾部的扇区。这是一个错误的使用方法,极力不推荐。这属于对 grub4dos 进行 “压力测试”,而在实际情况中毫无应用价值。 总结一句话:grub4dos 的开发者无需采取任何行动,即使想采取行动,也没有良方。 哦,顺便和 grub4dos 的开发者们说一下,grub4dos 内部的代码或公开发布的菜单,不可以去 “遍历”某个设备上的各个分区,更不可以去试图“探测”这个盘最大能够访问的扇区号码。因为这些动作,都可能碰上作恶的 BIOS,在某个大扇区号的地方引起死机。此时,不知情的用户会认为 grub4dos 很垃圾。事先根本无法预测 BIOS 会在访问哪个扇区时死机。 find 命令会遍历分区。但最好是让 find 尽早找到某个文件,避免让 find 找不到文件从而会遍历所有分区(位置越是靠后的分区,引起死机的概率是逐步增大的)。 有些奇葩情况,可供 grub4dos 开发者参考。有一台很老的 Dell 机器,它的 BIOS 支持 LBA,但是,只支持 LBA 的读操作,而不支持写操作。它在进行 LBA 写的时候,返回 Carry 出错标志。这还算是不错的了。如果它给你胡乱写盘,写到你不希望写的地方去了,那你哭爹叫娘也挽回不了。像这台 Dell 机的情况,可以判定为 BIOS 的 bug,它不是故意作恶。 还有读大扇区号时返回成功的(清除了 Carry 标志)而实际上根本没有读到有效数据,这造成的混乱更严重。好在 grub4dos 已经处理好了这个问题。 |
2011yaya2007777 发表于 2019-6-15 22:23 感觉这个问题与 map 命令无关。 是 disk read 限制了 bios 的访问能力。就是说,强制 bios 只访问分区表上呈现出的最大扇区,而拒绝分区表上没有呈现的扇区。 既然 0.4.5 没问题,找差别,应该可以定位。或者通过一个一个试验,找出最早出问题的日期。 |
不知怎么搞的,打开这个内存盘时,当做压缩文件去解压缩了。以前就发现,使用cat函数,内存盘也被解压缩了。具体原因待查。 |
yaya 你的测试是无效的。 楼主报告的是:当最后一个分区表项被抹去后(即彻底隐藏后)的情况。 楼主报告的是,在那样的情况下,不仅虚拟盘无法建立,就连 cat --hex (hd0)XXXX+YYYY (此处 xxxx 和 yyyy 代表抹去的最后一个分区表项) 都会失败的。 |
截图 |
IMG_20190615_102953.jpg (1.93 MB, 下载次数: 135)
IMG_20190615_102930.jpg (1.91 MB, 下载次数: 137)
本帖最后由 2011yaya2007777 于 2019-6-14 22:03 编辑 我用相同的方法,用新版0.46a,启动51Gb后的一个主分区,可以正常的通过NTLDR加载grldr。看来你的情况不具有普遍性。再说,你反馈0.45c正常,应当启动到某个界面,发截图上来。 我是使用移动硬盘测试的。实机测试。使用了无忧论坛能查到的十几个虚拟机,都不能启动usb接口的移动硬盘。不便截图,不想使用手机拍照。 |
2011yaya2007777 发表于 2019-6-14 13:01 你看4楼,是write命令的输出应该 |
指南针 发表于 2019-6-14 09:45 既然你说 0.4.5 没问题,那么,我认为,这肯定属于 0.4.6 的 bug 了。你可以向开发者报告 bug。 我猜新的 0.4.6 是根据分区表来限制 BIOS 的访问能力的,我认为这不合理。grub4dos 不应该限制 BIOS 的访问能力。即使做了这样的限制,也达不到 “提高可靠性” 的目的。这是因为,分区表上的存在的分区,BIOS 不一定都能访问:该死机的,照样死机;该出问题的,照样出问题。所以这种限制是没有意义的。 |
本帖最后由 不点 于 2019-6-14 08:55 编辑 你可以试试 grub4dos 0.4.5c 系列的版本,看看是否存在同样问题。 如果 0.4.5 也存在同样问题,那就说明,这有可能确实是 BIOS 的问题了。 如果 0.4.5 没这问题(或者发现任何一个老版本的 grub4dos 没这问题),那就可以肯定是 0.4.6 的 bug 了。 进一步界定问题的责任范围: 如果其他 BIOS 不存在此问题,则肯定是 VM14 的责任,而不是 grub4dos 的责任。换句话说,如果 grub4dos 有 bug 的话,那么在任何环境下(无论真实机还是虚拟机)都会表现出同样的问题。如果发现 grub4dos 0.4.6(5月12日版) 在某一台电脑或者某一个虚拟机(只要有一例即可)没有此问题发生,则就立即证明了该版本 grub4dos 没有此问题,因而问题肯定是 VM14 的 BIOS 造成的。 |
本帖最后由 不点 于 2019-6-13 18:02 编辑 指南针 发表于 2019-6-13 17:15 很好,请等我给出计算和分析…… 你的这个 VM14 的 BIOS 最多只能支持磁盘开头的 107876475 个扇区(从扇区 0 至扇区 107876474 共 107876475 个扇区)。 因此,我们对 107876475 进行因数分解: 107876475 = 3×3×3×5×5×7×17×17×79 心目中要记得: 63 = 3×3×7 255=3×5×17 因此: 107876475 = (3×3×7)×(3×5×17)×(5×17×79) = 63×255×6715 也即,最大支持的柱面数是 6715。 好的,以上只是趣味计算罢了。真正有用的,是 107876475 这个扇区号。从它开始,就不能访问了。这是这个 VM14 的 BIOS 的最大访问能力。 107876475 个扇区 = 53938237.5 KB = 52674.0600586 MB = 51.439511776 GB 就是说,这个 VM14 的 BIOS 最大只能访问(大约) 51 GB,其后的扇区,都无法访问到。 根据你前面提供的信息,你的 NTFS 分区正好落在可以访问的区域。 而紧接其后的 FAT32 分区,则(差不多)正好位于不可访问的区域了。 问题应该全然明白了。 |
本帖最后由 不点 于 2019-6-13 17:08 编辑 再执行 blocklist (hd0,1)/bootmgr 看看这个 bootmgr 的扇区列表情况。怀疑它超出 8G 的范围了。 还可以试试 cat --hex (hd0,1)/bootmgr 看看能否成功读完它的全部扇区数据。 计算一下 CHS 模式所能访问的最大扇区数: 1024 × 255 × 63 = 16450560 因此,你试试看那附近的扇区数据,能否访问到。步骤如下: cat --hex (hd0)16450558+1 cat --hex (hd0)16450559+1 cat --hex (hd0)16450560+1 cat --hex (hd0)16450561+1 cat --hex (hd0)16450562+1 cat --hex (hd0)16450563+1 如果都能访问到,再试试更大的扇区号,看看第一个不能成功访问的,是哪个扇区号。 比如,你先试试 cat --hex (hd0)20000000+1 如果成功得到扇区数据,就继续增大扇区号。如果失败了(出现 disk read error),就减小扇区号,继续测试。 这个测试很有必要,因为你的隐藏分区,就位于不可访问的区域。 |
辛苦了。 第二个盘是 NTFS,它的根目录文件名都能列出来了,但是,读取 bootmgr 时失败。感觉很奇怪。 请用 blocklist (hd0,N)/bootmgr 列出 bootmgr 的扇区列表信息,看看它是否位于 8G 以内。 另外,你再试试读第一个分区,就是 300M 的 Linux 分区,看看里面的文件能读出来吗? 另外,执行 geometry (hd0) 命令,看看 (hd0) 有没有 LBA 支持。怀疑这个 (hd0) 不支持 LBA,只支持 CHS。 |
不点 发表于 2019-6-13 10:50 我重新划分了一下分区,把原先后面一整块NTFS调小,后面跟着建了一个3.96GB的NTFS,最后面还特意预留七八个G的空白分区; 把3.96G的8字节丢到103扇区,g4d能正确获取起始扇区和总扇区,但仍disk read error 把这个NTFS分区换成FAT32分区,我注意到分区软件就是把07改成了0B,再测试还是disk read error |
本帖最后由 不点 于 2019-6-13 11:54 编辑 楼主,你的图片显示,出现了读盘错误。有可能是 BIOS 不支持大扇区号造成的。 你只能设法把分区弄在开头,这才能让 BIOS 识别。 不过,把分区弄在开头,又没有意义了。你本来就是想用后面的分区的。而由于 BIOS 不支持大扇区号,你的方案注定失败。 补充:不像是扇区号问题。可能是 NTFS 的原因。 NTFS 是否支持映射为软盘?有可能不支持。你试试 FAT32,如果成功,那就说明是 NTFS 的原因了。 还有一种可能性是,你的分区表指示你的盘有多少个扇区,但你实际的盘却没有那么大,比如说,结尾的扇区不存在,导致 grub4dos 在读取这个不存在的结尾扇区时出错。 注意:grub4dos 每次读扇区是按照“一大块、一大块”来读的,不是 “一个扇区、一个扇区” 来读的。块的大小有可能是 127 扇区,也有可能是 63 扇区以内。这样的“一大块”,在 grub4dos 中,就称为一个“虚拟磁道”(vTrack)。对于 LBA 磁盘设备,这个 vtrack 的大小是 127 扇区(共 63.5 KB)。对于 no-emulation mode 的 CDROM 设备,这个 vtrack 的大小是 32 个 2048 字节的扇区(共 64 KB)。对于不支持 LBA 模式的普通 CHS 磁盘设备,这个 vtrack 的大小就是 BIOS 的 CHS 模式的磁道长度(可能是 63 扇区,也可能比 63 扇区还要小;因 BIOS 的不同而不同)。 假如尾部有一个块不足“一大块”,比如说,尾部有个零头,只有 20 个扇区,此时,假如让 grub4dos 去读尾部的 20 扇区,它就会出错,因为它要去读的(可能)是 127 个扇区。 解决的办法是,永远不要让 grub4dos 去访问磁盘尾部的 128 个扇区。这样,就避免了那种麻烦。也就是说,磁盘尾部的至少 128 个扇区,不要让它们是分区的一部分,要把它们排除在分区之外。 135694336 - 128 = 135694208 因此,你暂时可以试试: map (hd0)616448+135694208 (17) |
本帖最后由 不点 于 2019-6-13 07:13 编辑 楼主,你的图片显示,读的数据是正确的,只不过是 64 位罢了。 看看你那个 64 位的 Hex:816880000096800 按字节,把它倒过来写,就是 00 68 09 00 - 00 88 16 08 这不刚好是你的起始扇区号以及扇区总数吗? 你只需设法屏蔽掉不想要的高位部分,就行了。 你看的那篇文章,可能比较旧了,而 grub4dos 的新版,很可能已经采用 64 位值了。 希望能帮到你。 试试帮你搞定它: # 从 103 扇区第 502 字节开始复制 8 个字节 dd if=(hd0)103+1 of=(md)768+1 bs=1 count=8 skip=502 # 现在 393216 处的 8 个字节已经是一个 64 位的值了。 # 为了让 grub4dos 读取的时候,不至于读取到 64 位值, # 先把高位部分置零,然后再读。 # 好的,先读取 ps,当然,先得保证高位部分为 0,因此,先执行如下 write 命令: write 393224 0 # 注意上述命令很可能会写入 8 个 00 字节,没关系, # 多写的四个字节只是会破坏后面的无用内存,不要紧。 # 好了,现在读取 ps,正是时候,因为高位部分已经清零了: set /a ps=*393220 # 接下来要读 pe 了,同样,先把高位清零: write 393220 0 # 注意上述命令很可能会写入 8 个 00 字节,没关系,ps 已经读过了, # 多写的四个字节只是会破坏后面的无用内存,不要紧。 # 好了,此时读取 pe,正是时候,因为高位部分已经清零了: set /a ps=*393216 # 所需要的数据都读完了,可以什么也不做,也可以再执行一次清零: write 393216 0 |
hao复杂啊,我就进来看看,矩阵的数字是怎么看的,偶也想学 |
Powered by Discuz! X3.3
© 2001-2017 Comsenz Inc.