无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站广告联系 微信:wuyouceo QQ:184822951
楼主: 2011yaya2007777
打印 上一主题 下一主题

支持含有碎片的文件仿真

    [复制链接]
181#
发表于 2017-8-26 14:13:01 | 显示全部楼层
2011yaya2007777 发表于 2017-8-26 09:51
我的猜测是:
(0x14)内存盘映射在 "Usable RAM: Base: 0xD6FFF000, Length: 0x1000",从而误导Windows XP在 ...

我猜不是那么回事。我的修复也弄好了,让 mdyblog 试试我的修复,看看成功不成功?

这里要说说怎么样才叫 “成功”:无论内存盘放在哪一个内存块上(与内存块长度无关,长度为 0x1000 也行),都能通过 Windows 这个衙门(关卡),而顺利启动——这才算是成功。

在上述这个 “成功”的定义之下,请 mdyblog 试试我的补丁,看看是否成功(当然希望成功了)。


附件解压后含有 asm.S.diff 和 asm.S.new 两个文件。

asm.S.diff 是补丁文件,只是为了方便大家查看代码究竟有哪些改动。

asm.S.new 改名为 asm.S,替换 2017-06-25 的 0.4.6a 中的 asm.S,重新编译即可。

我暂时没有编译环境,请 yaya 编译一个版本,供 mdyblog 测试。

如果 mdyblog 自己有编译环境,那 mdyblog 就可以自己来编译、测试了。


asm.tar.gz

88.8 KB, 下载次数: 7

包含补丁文件和 asm.S.new 文件,供测试。只含源代码,需要编译后才能用。

回复

使用道具 举报

182#
发表于 2017-8-26 16:20:56 | 显示全部楼层
我感觉,既然 mdyblog 测试 asm.S.new 成功,那就证实了我前面的猜测。于是我们就又摸清楚了 Windows 的一个 “脾气”,即,Windows 不喜欢存在 “长度为 0”的内存块。一旦存在这样的内存块,Windows 就“乱了阵脚”或 “找不到北”了。

当一个内存块被(一个或多个)内存盘占据时,剩余未被占据的部分,如果恰好是 0(也即正好全部被内存盘占满),这是旧版本的 grub4dos 处理不好(无法处理)的情况。旧版本的 grub4dos 用 int15 来返回 0 的可用内存块长度给 int15 的调用者(比如操作系统)。Windows 遇上这个 0 长度的内存块,彻底乱套,拒绝继续启动。

我的解决办法是:当这种情况发生时,不修改这个可用内存块(usable RAM)的长度,即,保持这个内存块长度不变,而把它的 type(类型) 从 “usable RAM(用户可用)”更改成 “reserved(系统保留,用户不可用)”。这就完美解决了。

错误的技术根源猜测。我猜 Windows
(有可能)把长度为 0 的内存块当成长度为 4G(=2 的 32 次方) 来处理了,也有可能是当作 2 的 64 次方来处理了,于是就全乱了。大家很熟悉:在二进制表示中,负1(即 “-1”) 与最大的数是相同的,而“最大的数”再加上 1,就等于 0。所以,在 long 整数(即 32 位整数)中,0 和 4G 是一样的(4G 就是 2 的 32 次方)。在 long long 整数(即 64 位整数)中,0 就等于 2 的 64 次方(可以粗略理解为 “无限大”)。

换句话说,Windows 的实模式启动代码把长度为 0 的内存块(有可能)当成长度为“无限大”来处理了。那么,由于 Windows 认为整个内存全部被(这个内存块)占用,完全没有可用内存了。于是,Windows 就认为内存不够了。因此,它就要报错,并且拒绝继续启动 Windows 的内核。


回复

使用道具 举报

183#
发表于 2017-8-27 12:00:35 | 显示全部楼层
2011yaya2007777 发表于 2017-8-27 11:54
他怎么位于6A4C90?而不是6B7FF8?

是啊,浪费了 6B7FF8 处的空间。莫非 mdyblog 抄错了?mdyblog 是不是简单复制粘贴前面一帖的内容了?

点评

肯定是今天测试的,不是copy昨天的。 LOG中还打印了%@DATE% %@TIME% 2017-08-27 11:27:47 floppies_orig=0, harddrives_orig=2, floppies_curr=0, harddrives_curr=3 Number of ATAPI CD-ROMs: 0 ram_d  详情 回复 发表于 2017-8-27 13:11
回复

使用道具 举报

184#
发表于 2017-8-27 13:16:20 | 显示全部楼层
本帖最后由 不点 于 2017-8-27 14:11 编辑
2011yaya2007777 发表于 2017-8-27 12:11
直接使用grldr,不用编译。

好像程序是错的,yaya。

  1.          subl        %es:(%di), %eax
  2.          sbbl        %es:4(%di), %edx        /* EDX:EAX=new length */
  3.          jb        5f                        /* start_address is below the base */
  4. +        /* now EDX=0 */ 此处怎能断定 EDX=0 ?  在 4G 以上的空间,它可能是大于 0 的。用的是 64 位地址,不是 32 位。EDX 是 高32位,EAX 是低32位
  5. +        testl        %eax, %eax                /* EAX also be zero? ZF holds it! */
  6. +        jne 7f
  7. +        /* Change memory address type from 1 (usable) to 2 (reserved). Note
  8. +         * that original value is long integer of 1 (all higher 3 bytes = 0).
  9. +         * So only the lowest byte needs to be incremented. */
  10. +        incb        %es:16(%di)                /* memory address type */
  11. +        jmp        5f
  12. +7:
  13.          subl        %es:8(%di), %eax
  14.          sbbl        %es:12(%di), %edx        /* EDX:EAX=difference */
  15.          jnb        5f                        /* new length is too big */
复制代码


就算 mdyblog 测试通过了,有问题的代码也是不能用的。

补充:感觉 yaya 的程序确实比我的简化了不少。赞!上述毛病稍微改进一下,不知道行不行:


  1.          subl        %es:(%di), %eax
  2.          sbbl        %es:4(%di), %edx        /* EDX:EAX=new length */
  3.          jb        5f                        /* start_address is below the base */
  4. +        ja        7f        <-------------------  就增加这一句
  5. +        /* now EDX=0 */
  6. +        testl        %eax, %eax                /* EAX also be zero? ZF holds it! */
  7. +        jne 7f
  8. +        /* Change memory address type from 1 (usable) to 2 (reserved). Note
  9. +         * that original value is long integer of 1 (all higher 3 bytes = 0).
  10. +         * So only the lowest byte needs to be incremented. */
  11. +        incb        %es:16(%di)                /* memory address type */
  12. +        jmp        5f
  13. +7:
  14.          subl        %es:8(%di), %eax
  15.          sbbl        %es:12(%di), %edx        /* EDX:EAX=difference */
  16.          jnb        5f                        /* new length is too big */
复制代码

我的那个程序可能比较罗嗦、复杂,但逻辑的正确性是没问题的(我只是检查了几遍,没发现问题;也不敢肯定真的没问题)。要是上述这个代码在逻辑上没问题的话,那可是非常漂亮的了。
回复

使用道具 举报

185#
发表于 2017-8-27 13:19:34 | 显示全部楼层
mdyblog 发表于 2017-8-27 13:11
肯定是今天测试的,不是copy昨天的。
LOG中还打印了%@DATE% %@TIME%
2017-08-27 11:27:47


没有使用最高的可用地址,就是错误啊(程序的逻辑包含着错误,属于 bug)。与你想不想节约这点空间没关系。

回复

使用道具 举报

186#
发表于 2017-8-27 15:34:19 | 显示全部楼层
2011yaya2007777 发表于 2017-8-27 14:57
不点所言极是,确实应当增加
04.+        ja        7f

昨天我写代码,纠结了半天,费了不少工夫。看到我以前写的这段 int15_e820_handler 代码,我甚至觉得很棒、很简练,有些地方竟然看不懂,还要琢磨半晌才能弄懂,就好像不是我写的一样。这说明,我现在的水平已经下降了!可能是脑细胞退化了吧!有点悲哀,但不能不承认。

chenall、yaya 你们比我可年轻多了。我希望你们到我这岁数的时候,可不要像我这样了。趁着你们现在年轻,要多多的用脑子,宝剑锋自磨砺出,脑子不用就迟钝了。当然了,身体是第一位的,一定要注意营养,注意锻炼,注意休息。

我现在脑子不好使,暂时没有发现上述代码是否有别的问题。yaya 可再检查确认一下。
回复

使用道具 举报

187#
发表于 2017-8-29 09:23:01 | 显示全部楼层
2011yaya2007777 发表于 2017-8-29 09:11
经过进一步测试,结论如下:
使用 int15/eax=e820, 返回4Gb以下可用内存块(4Gb及以上可用内存块无影响), ...

非常好,又弄清楚了一个问题。这也间接说明 XP 不去处理 4G 以上的内存。可以试试 64 位的操作系统(Win7~Win10),看看情况又有什么不同?说不定 0K 问题不存在了,也未可知。弄清楚总是有好处的。

假如 Win7~Win10 不存在 0K 问题,说明微软认为 XP 是个 bug,已经修复。

假如 Win7~Win10 也存在 0K 问题,说明微软所理解的 int15 规范是不允许有 0 长度的内存块的。


回复

使用道具 举报

188#
发表于 2017-8-29 17:54:17 | 显示全部楼层
2011yaya2007777 发表于 2017-8-29 16:15
经测试,Win7~Win10 不存在 0K 问题。
看来 WinXP 启动时检查 4Gb 以下的所有可用内存块,如果长度为零就 ...

关于 XP 反馈的信息,你给出的这种解释,或许不符合 Windows XP 开发者的想法。Windows 开发者有可能是把内存块长度减去 1,算出内存块最末尾的字节(相对于内存块开头)的偏移量。0 长度算出的最大偏移量就是 0xFFFFFFFF 了。既然有这么大的一个偏移量,就相当于说,该内存块占满了所有的内存,于是,常规内存也被 “吞噬”,或者说,与该内存块 “有重叠”。如果 “被吞噬” 的常规内存算作 “不存在” 的话,那么,常规内存量就成为 0 了。

XP 所说的 512K,是指常规内存底端的 512K,这不能随便从别处分配(不能位于扩展内存中)。它是指 “起始于物理地址 0,终止于物理地址 0x80000” 的这段常规内存。Windows 启动程序(甚至 Windows 内核),有可能使用这 512K 的空间。只要这个空间被别的软件占用,Windows 就要报错。

Win7~Win10 可能发现 XP(对于长度为 0 的内存块)的那种 “理解” 太过于 “绕弯”,于是就纠正过来了。这说明微软(或者 Windows 的开发者)认为 XP 的那种处理,是个 bug。
回复

使用道具 举报

189#
发表于 2017-8-30 00:00:12 | 显示全部楼层
2011yaya2007777 发表于 2017-8-29 18:14
长度是指基地址开始的长度。如果觉得太大,那也是从基地址开始的长度太大,此时不应当包含常规内存吧。

现在不是跟别人 “讲道理”的时候。我们作为 “外界”的人,程序不是我们写的,我们只能 “猜测”,只能尽量想出一些 “可能性”(这些 “可能性”还都“堂而皇之”、能够“说得过去”)。换句话说,我们是尽量替人家“找理由”。

譬如你刚刚提到的这个疑问,那我们如何替人家“自圆其说”呢?我觉得可以像这样(仅仅是举例,其实可能性多得很):

人家只要发现内存块长度为 4G,就认为这个内存块已经“包括所有的内存”了,此时忽略内存块的基地址。

是我们得替人家找理由;不是反过来,即,由人家来回答我们的问题。
回复

使用道具 举报

190#
发表于 2017-9-18 16:51:39 | 显示全部楼层
请稍等,容我先慢慢理解一下你的意思,然后再回复。
回复

使用道具 举报

191#
发表于 2017-9-18 17:28:53 | 显示全部楼层
首先,注意 --in-situ 的含义:它只是把分区表虚拟化,别的保持不动。

它只是把——比如说,从偏移扇序号 80h 开始的 1000h 个扇区——虚拟为主分区。也就是说,让主分区表的某一项(如果有空位的话)指向这个位置(起始地址和长度)。

特别注意,虚拟磁盘的其他扇区都是 “实在” 的,未进行虚拟化。这一点很重要,不要在理解上有偏差。

因此,你那种 “备份” 的想法,感觉就有点 “奇葩” 了。本来 --in-situ 就是一个指针而已,根本没有什么东西需要备份。如果 “非要备份不可” 的话,那也是备份这个指针,即备份 80h 和 1000h 这两个数字(即,虚拟主分区的起始扇区号和虚拟主分区的长度)。

假如你希望达到这样的目的:

Fr To Hm Sm To_C _H _S   Start_Sector     Sector_Count   DHR
-- -- -- -- ---- -- -- ---------------- ---------------- ---
82 80 FE 01 000E FE FF 0000000000000080 0000000000001000 H=S

你应该直接使用

map --in-situ (hd0)0x80+0x1000 (hd2)

嵌套的 --in-situ,容易出问题。我是说,我在编程的时候,就有可能出现 bug 之类的(即,没有处理好的情况)。如果你发现了 bug,你可以让 chenall、yaya 解决。我发现,chenall、yaya 都解决过以前我没处理好的一些问题,而且都解决得很漂亮。

但最好别让 chenall、yaya 他们太过于忙碌——我认为,能不做就不要做;能躲过,就尽量躲过。因为万一改动坏了,不是还得折腾吗。这年月(BIOS 逐步被抛弃),grub4dos 也不值得再投入太大的精力了——我认为。

因此,建议尽量避免嵌套使用 --in-situ。否则,你让开发者修复 bug,这恐怕有工作量吧?


点评

建议尽量避免嵌套使用 --in-situ。 ---------------------- 将一个没有分区表的磁盘片(相当于1个分区IMG), 虚拟成一个磁盘。 好像只能 用 --in-situ。 还有其它的方式吗?  详情 回复 发表于 2017-9-18 19:02
你应该直接使用 map --in-situ (hd0)0x80+0x1000 (hd2) ---------------------- 显示中, 这两步是没关联的。这里只是演示下。 第一步可能是另外一个grldr 传过来的。 map --in-situ (hd0)0x1080+0x1000  详情 回复 发表于 2017-9-18 18:44
回复

使用道具 举报

192#
发表于 2017-9-18 19:44:21 | 显示全部楼层
抱歉,我还是不太理解你的处境。请容我再仔细研究一下你的帖子,然后再试试回复。
回复

使用道具 举报

193#
发表于 2017-9-18 20:21:08 | 显示全部楼层
你可能是在 “超限使用 grub4dos”,——不知我这么理解,是否恰当。

--in-situ 的“作用”,或者说“目的”,就是把一个硬盘上的连续扇区序列虚拟成一个主分区。用户最常用的情景,可能是把一个逻辑分区虚拟为主分区。

如果 --in-situ 完成了(或者说“达到”了)这样的目的,那么,--in-situ 就没有错误。


--in-situ 虚拟技术的实现细节是这样的:

当应用程序试图去访问虚拟硬盘的时候,应用程序所看到的是一个虚拟的(通俗地说,就是“假”的)分区表。这个虚拟分区表上有四个表项。其中有一项正是用户所关心的“(虚拟的、假的)主分区”。

抱歉,我没能理解你的描述。我真不知道,--in-situ 还能用来干别的事。你似乎就是在用 --in-situ 来干别的事。

我绝不是说不可以这么做。你能这么做,肯定是好事。但问题在于,我不了解你的处境,理解不了你的操作过程,以及问题关键点在什么地方,没法帮你。

假如你能通俗地为我(或者为网友们)解释清楚你的应用场景(或应用的方法),你可以详细解释一下。否则,我们不在一个轨道上,互相没法交流。

假如我不理解你的操作过程或某些关键的细节,我肯定没法回复。
回复

使用道具 举报

194#
发表于 2017-9-18 21:07:56 | 显示全部楼层
mdyblog 发表于 2017-9-18 19:02
建议尽量避免嵌套使用 --in-situ。
----------------------
将一个没有分区表的磁盘片(相当于1个分 ...

你说的其实就是将软盘虚拟为硬盘。举例:

map --mem (...)/.../floppy.img  (hd0)

当 grub4dos 发现你的 IMG 不含 MBR 分区表、同时也在使用 --mem 参数的时候,grub4dos 会自动在内存中为这个 IMG 添加一个分区表。

其实,我这个回复是多余的。因为你肯定知道这个情况。


下面继续讨论相关话题。

如果没有 --mem,那么目前的 grub4dos 还不具有“自动为 IMG 添加虚拟分区表”功能。

--in-situ 不是为 IMG 添加分区表。--in-situ 其实是在对整个硬盘进行虚拟化。它不是仅仅对某个 IMG 的一个连续扇区序列进行虚拟化。--in-situ 把硬盘的分区表给“更改”了(“虚拟化”了),通常是添加了一个表项(比如通常是 hd0,0),让它指向用户所关心的 IMG (或任意一个连续扇区序列)。注意,这里的概念不要弄错。用户虽然只关心 IMG 的虚拟,但整个硬盘都被虚拟了。在虚拟的硬盘上,用户通常除了能够看得见虚拟的 (hd0,0) 之外,还能看见其他真实分区,比如 (hd0,4), (hd0,5),等等。这些分区都是虚拟硬盘 (hd0) 中的一部分。不要以为,经过 --in-situ 虚拟化了的 (hd0) 上只有一个分区(即与 IMG 所对应的那个分区)。经过 --in-situ 虚拟化以后,虚拟硬盘上的分区,比真实硬盘还多了一个分区(多出的这个分区就是 IMG 所对应的那个分区)。真实硬盘上原来有的分区(不管是逻辑分区还是主分区),在虚拟硬盘上也都存在,一个都不少(但其分区编号可能与对应的真实硬盘有所不同)。

另外,grub4dos 确实有一个功能,就是,把一个逻辑分区虚拟成一个含有分区表的硬盘。这种功能比 --in-situ 实现得还要早。也就是说,--in-situ 是后来才开发出来的。

注意,是把逻辑分区虚拟成硬盘,不是把普通扇区序列(比如不含分区表的 IMG 文件)虚拟成硬盘。由于这不是你关心的情况(你关心的是对 IMG 的虚拟,不是对逻辑分区的虚拟),我也就不再详述了。readme 文件里面好像提到过这种功能吧。这一点,我猜你可能早都知道了。但这个功能,似乎很少有人用。


回复

使用道具 举报

195#
发表于 2017-9-18 23:11:12 | 显示全部楼层
明白了。mdyblog 是想给已经 --in-situ (并且已经 --hook )了的盘映射出一个新的盘号。结果,新盘丢失了 --in-situ 特有的信息(起始扇区号,扇区总长度,以及映射参数)。此时,出现的 bug 是,map (hd0) (hd2) 执行时未能认出 hd0 是一个具有 --in-situ 映射参数的虚拟盘,结果,导致 hd2 克隆了普通硬盘 hd0,而不是克隆经过 --in-situ 虚拟后的硬盘 hd0。

yaya 看看能否修复。我可有点累,忙不过来。如果 yaya 能做的话,那就做吧。不怕弄坏,弄坏了还可以恢复。如果没有时间,那就等着以后有时间再弄。磁盘仿真程序虽然最初是我写的,但是,现在我觉得,看代码都累,而且,我还不一定能看懂以前我自己写的代码。所以,即使让我来修复,也不一定比 yaya 更轻松一些。chenall 也可以,只是觉得,chenall 来这儿的时间都不太多,估计和我有点类似,忙不过来。
回复

使用道具 举报

196#
发表于 2017-9-19 07:43:01 | 显示全部楼层
问题是,hd0 是先前某个 grldr 所建立的虚拟盘。他只知道 hd0 是虚拟盘,不知道 hd0 的映射参数(起始扇区、扇区总数等信息),因此他没法用 map --in-situ (hd0)0x1080+0x1000 (hd2) 。再一个,他也是想使用起来简单方便罢了。所以,他想让 grub4dos 能够自动处理这种含有 --in-situ 的嵌套映射问题。本质上属于嵌套,如果没有嵌套,一切都正常。而 mdyblog 正是希望嵌套使用磁盘虚拟功能。

我都费了好大劲才了解了 mdyblog 的意思。这确实属于 grub4dos 在处理含有 --in-situ 的嵌套映射时的 bug。你再慢慢琢磨琢磨。
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-5-16 03:47

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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