无忧启动论坛

标题: 疑似grub4dos比较大的bug [打印本页]

作者: sratlf    时间: 2013-6-25 03:01
标题: 疑似grub4dos比较大的bug
本帖最后由 sratlf 于 2013-6-25 03:16 编辑

1,下面测试用的脚本  文件夹含有少量文件时不会发生下面截图的错误  过多的时候会执行错误
2,06-24 0.45c版在vmware虚拟机启动失败  卡死时出现光标  但没出现Running menu commands(hangup means you have a problematic config)...提示
  1. !BAT
  2. ls (hd0,0)/winxp/windows/system32/ | call :automake %0
  3. exit

  4. :automake
  5. echo A
  6. setlocal
  7. echo B
  8. exit
复制代码
下面截图是多个版本的测试  暂时还没找到是从哪个版本开始出现问题的




dir.zip

8.02 KB, 下载次数: 3, 下载积分: 无忧币 -2

(hd0,0)/winxp/windows/system32/下文件列表


作者: chenall    时间: 2013-6-25 10:41
批处理脚本不要带UTF-8签名..
注意看截图!BAT前面还有字符,所以认为这不是一个合法的批处理 文件.
作者: sratlf    时间: 2013-6-25 10:46
chenall 发表于 2013-6-25 10:41
批处理脚本不要带UTF-8签名..
注意看截图!BAT前面还有字符,所以认为这不是一个合法的批处理 文件.

应该不是签名的问题  有换用ansi编码  错误提示是一样的

而且无论是utf8签名还是ansi  脚本都能执行  错误是在输出A以后执行setlocal时产生的
作者: chenall    时间: 2013-6-25 11:03
你有条件再测试一下,使用debug 3.

我预计到30号才有时间.
作者: sratlf    时间: 2013-6-25 11:38
chenall 发表于 2013-6-25 11:03
你有条件再测试一下,使用debug 3.

我预计到30号才有时间.

测试了最新的几个版本  先看下结果吧

0.46a版测试
0624的测试结果最奇怪  debug 3情况下能正常执行  其他情况会报错  错误截图在#1

几个版本都不正常





再之前的版本有丢失文件的bug  找不到测试用的test.bat脚本。。。 就没有测试

0.45c版测试
0624版vmware启动失败  卡死时有光标  但没hangup means...提示
0419及之前的版本正常  0521版出错




作者: 不点    时间: 2013-6-25 15:13
提醒一下,5月21日至6月24日之间没有编译结果。怀疑死机是由 daven  5月24日的改动造成的。


作者: sratlf    时间: 2013-6-25 16:46
不点 发表于 2013-6-25 15:13
提醒一下,5月21日至6月24日之间没有编译结果。怀疑死机是由 daven  5月24日的改动造成的。

0.46a的有几个  是yaya的usb测试版本  就一次测试了  0.45c的没有
作者: 不点    时间: 2013-6-25 18:06
因为 daven 的改动,我粗略看了代码,当时就有一种感觉,改动太大,有可能造成启动时便发生死机的问题。chenall 说他已经检验过了。但我怀疑 chenall 并未彻底检验。

其他改动,都不至于影响到启动死机的问题。如果找不到导致死机的原因,并且能够确定是 daven 的改动引起的,那只好废除 daven 的改动。等待 chenall 安排一个测试流程,确定到底是什么原因导致死机的。


作者: chenall    时间: 2013-6-29 11:58
本帖最后由 chenall 于 2013-6-29 11:59 编辑

首先看了第一个问题,这个应该是内存溢出了(冲突了),以前的版本没有体现出来.(这个文件太多的话建议还是分段加载,否则肯定没有办法全部加载完,多的会被截掉,需要自己注意),当然了也需要找到哪里的内存冲突了.

第二个问题,VMWARE启动失败,你是使用什么方式启动的?用软盘启动正常.用光盘失败.
我试了用ISO启动无论是QEMU还是VMWARE都会失败,原因是由于R348的改动引起的
下面的那个6144改成其它的任意值都会导致开机失败(新版的是0X8000,我改成6144之后正常,改成其它的就失败.),对ASM还有启动过程不了解,等不点查看下.
movw        $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 1 + 6144)

作者: 不点    时间: 2013-6-29 13:47
chenall 发表于 2013-6-29 11:58
首先看了第一个问题,这个应该是内存溢出了(冲突了),以前的版本没有体现出来.(这个文件太多的话建议还是分段 ...

6144 改成 0x8000,肯定没错。估计是你生成 ISO 的方式不对。
作者: sratlf    时间: 2013-6-29 14:13
chenall 发表于 2013-6-29 11:58
首先看了第一个问题,这个应该是内存溢出了(冲突了),以前的版本没有体现出来.(这个文件太多的话建议还是分段 ...

以前|有限制的时候会截断  后来|无限制就忽略这个了

vmware的话是iso joliet格式  参数如下

mkisofs.exe -o MaxBOOTt.ISO -V "MaxBOOT" -J -joliet-long -hide-joliet boot.catalog -l -relaxed-filenames -gbk4dos-filenames -gbk4win-filenames -no-emul-boot -b GRLDR boot

作者: 不点    时间: 2013-6-29 14:39
这条mkisofs命令,似乎也没错。再加上 -boot-load-size 4,据说能够适应于所有的 bios。

你生成的 iso,在别的虚拟机下能启动吗?在真实机下能启动吗?

如果能,那就说明我们刚好又碰上了 vmware 的某个未知 bug 了。
作者: chenall    时间: 2013-6-29 15:29
sratlf 发表于 2013-6-29 14:13
以前|有限制的时候会截断  后来|无限制就忽略这个了

vmware的话是iso joliet格式  参数如下

先试试这个,应该解决内存冲突问题,BAT CALL 的参数长度现在允许最多达到32KB(正常情况下足够使用了),超过的话会报错.(以前只有4KB,但由于程序中没有进行判断,如果超过4KB的话就会溢出了.)

grub4dos-0.4.5c.rar

275.95 KB, 下载次数: 6, 下载积分: 无忧币 -2


作者: sratlf    时间: 2013-6-29 15:31
不点 发表于 2013-6-29 14:39
这条mkisofs命令,似乎也没错。再加上 -boot-load-size 4,据说能够适应于所有的 bios。

你生成的 iso, ...

别的虚拟机和实机都还没测试  只有0624的0.45c会卡住  之前的版本还有0624的0.46a都没问题
作者: sratlf    时间: 2013-6-29 15:35
chenall 发表于 2013-6-29 15:29
先试试这个,应该解决内存冲突问题,BAT CALL 的参数长度现在允许最多达到32KB(正常情况下足够使用了),超过 ...

能提供0.46a的吗  0.45c的在vmware还是卡死。。。  没法测试
作者: chenall    时间: 2013-6-29 15:38
sratlf 发表于 2013-6-29 15:35
能提供0.46a的吗  0.45c的在vmware还是卡死。。。  没法测试

这个是没有打R348补丁的0.4.5c版本.

grub4dos-0.4.5c.rar

135.43 KB, 下载次数: 1, 下载积分: 无忧币 -2


作者: sratlf    时间: 2013-6-29 16:05
chenall 发表于 2013-6-29 15:38
这个是没有打R348补丁的0.4.5c版本.

貌似还是有问题  这个可以启动了  但是执行脚本的时候各种卡死  每次卡死时命令都不一样  还找不到什么固定规律

而且相对以前的所有版本  这个版本执行内置菜单需要的时间要长的多  默认内置菜单  以前一闪而过的现在需要三四秒
作者: 不点    时间: 2013-6-29 16:07
chenall 发表于 2013-6-29 15:38
这个是没有打R348补丁的0.4.5c版本.

你都已经证明 r348 有问题了,何必再让 sratlf 去测试?

真正有意义的,是测试别的虚拟机以及真实机下的情况。

我前面提到,mkisofs 中应该有参数 -boot-load-size 4,成功率最高,也就是说,bios 适应性最高。请添加这个参数,然后在各个虚拟机和真实机下测试,以便能够找出问题的根源。

把 6144 改成 0x8000 是没错的。问题是碰上 bios 适应性问题了,怀疑有些 bios 不能适应这个改动,而另外的 bios 应该是没问题的。一步一步来,我们先通过测试,确定这一点,然后根据测试的情况反馈,再安排下一个测试。


作者: sratlf    时间: 2013-6-29 16:15
不点 发表于 2013-6-29 16:07
你都已经证明 r348 有问题了,何必再让 sratlf 去测试?

真正有意义的,是测试别的虚拟机以及真实机下 ...

0624 0.45c 虚拟机下添加-boot-load-size 4参数启动结果还是一样的  依然卡死
作者: 不点    时间: 2013-6-29 16:20
本帖最后由 不点 于 2013-6-29 16:44 编辑

好的,关于启动失败,请 sratlf 测试多个虚拟机,最好能测试一台真实机。目的是找出一个成功启动、不死机的机器。暂时怀疑,某些 BIOS 占用堆栈空间大,与加载的 grldr 代码发生了冲突。

EDIT:

发现我的代码改动有遗漏,请终止测试启动失败问题。等待我给出修复。
作者: 不点    时间: 2013-6-29 17:27
已经修复,附件是修复后的 grldrstart.S 文件,适用于 0.4.5c,不适用于 0.4.6a。

如果测试成功,请 chenall 直接提交。

grldrstart.rar

41.76 KB, 下载次数: 6, 下载积分: 无忧币 -2

0.4.5c 源代码


作者: chenall    时间: 2013-6-29 17:50
本帖最后由 chenall 于 2013-6-29 17:57 编辑
不点 发表于 2013-6-29 17:27
已经修复,附件是修复后的 grldrstart.S 文件,适用于 0.4.5c,不适用于 0.4.6a。

如果测试成功,请 che ...


测试正常,源码先提交了.

grub4dos-0.4.5c.rar

135.4 KB, 下载次数: 23, 下载积分: 无忧币 -2


作者: 不点    时间: 2013-6-29 17:57
死机的问题解决了,那么 chenall 接下来应该删除 0.4.5c-2013-06-24 的下载,以免别人再下载这个已经被证明是有问题的版本。
作者: sratlf    时间: 2013-6-30 09:40
不点 发表于 2013-6-29 17:57
死机的问题解决了,那么 chenall 接下来应该删除 0.4.5c-2013-06-24 的下载,以免别人再下载这个已经被证明 ...

貌似还是有点问题  用的#22的grldr  启动没问题了  但是执行脚本时还是卡死  已在其他版本测试过执行没问题的


作者: chenall    时间: 2013-6-30 11:08
没道理啊,这个改动不应该影响才对的..

麻烦把可以重现问题的文件打包一份上来,我下午抽空看下.
作者: zhaohj    时间: 2013-6-30 12:24
编译的文件大小为何比以前还大?我记得不点大已经取消了stage1及stage1.5,应该更加精简啊。
我测试srsf6n(22楼的grldr)也卡死,自己用gebian gcc4.8.1-2下载最新源码编译后的grldr测试srsf6n没问题。
是否是编译的问题?
作者: 不点    时间: 2013-6-30 12:45
我记得不点大已经取消了stage1及stage1.5,应该更加精简啊。


完全是两回事。源代码精简了,不等于执行码能精简。

我们的执行码中,一直都不存在 stage1 和 stage1.5,所以,执行码根本不受影响。

作者: chenall    时间: 2013-6-30 17:47
刚上传的版本应该解决了,,眼花没有注意看,.
作者: sratlf    时间: 2013-6-30 18:17
chenall 发表于 2013-6-30 17:47
刚上传的版本应该解决了,,眼花没有注意看,.


0630版没有#1的两个问题了  还有个问题忘记说了  用0.45c的grldr启动0.46a的grldr会报错  最近的几个版本都这样

grldr2是0630 0.46a的grldr改名的

作者: 快雪时晴    时间: 2013-6-30 18:20
sratlf 发表于 2013-6-30 18:17
0630版没有#1的两个问题了  还有个问题忘记说了  用0.45c的grldr启动0.46a的grldr会报错  最近的几个版 ...

的确如此,用0.46a grldr  ---->0.46a grldr 也会报错,非法格式。
(ud)/grldr   --------> U可见区 /GRLDR
作者: 不点    时间: 2013-6-30 18:36
感觉 有关 0.4.6 的 grldr 格式问题,最好由 yaya 来解决。yaya 原来都解决过一次了,这次又出问题,需要再次解决。正如 bootlace64 需要重新解决那样,grldr 格式问题应该也需要重新解决。


作者: sratlf    时间: 2013-7-2 00:27
chenall 发表于 2013-6-30 17:47
刚上传的版本应该解决了,,眼花没有注意看,.

貌似还是有点bug  看截图



作者: 2011yaya2007777    时间: 2013-7-2 08:49
关于 0.4.6a 的 grldr 格式识别问题已经解决。
作者: sratlf    时间: 2013-7-2 09:20
2011yaya2007777 发表于 2013-7-2 08:49
关于 0.4.6a 的 grldr 格式识别问题已经解决。

用0630 0.45c还是启动不了0702 0.46a...
作者: zhaohj    时间: 2013-7-2 09:41
本帖最后由 zhaohj 于 2013-7-2 11:25 编辑

        if (arg_len > 0x8000)
        {
            errnum = ERR_WONT_FIT;  //Error 28: Select item cannot fit into memory  
            return 0;
        }
-----------------------------
@sratlf:
目前是超过0x20(kb)就直接报错退出
你这个也太变态了,一般不会遇到的吧。但我认为截断比较好,并给出提示。
作者: 不点    时间: 2013-7-2 09:57
2011yaya2007777 发表于 2013-7-2 08:49
关于 0.4.6a 的 grldr 格式识别问题已经解决。

是不是修改了 chainloader 命令,让它识别 0.4.6a 的 GRLDR 格式?

如果这样做,那么老版本的 grub4dos 还是无法用 chainloader 加载 0.4.6a 的 GRLDR。

最好是修改新版的 GRLDR 的格式,让它可以被老版本的 chainloader 加载。除非根本做不到这一点。


作者: chenall    时间: 2013-7-2 10:03
本帖最后由 chenall 于 2013-7-2 10:10 编辑
sratlf 发表于 2013-7-2 00:27
貌似还是有点bug  看截图


看13楼的说明..
你的参数太长了,已经超过32KB.建议分段处理..

确实有必要的话再改大一些..

想了想下一版还是改掉好了,不限制,但是还是要受管道缓冲区的大小限制(目前是0x20000 共128KB,我想应该没有那么变态的应用会超过这个限制)
作者: sratlf    时间: 2013-7-2 10:07
zhaohj 发表于 2013-7-2 09:41
if (arg_len > 0x8000)
        {
            errnum = ERR_WONT_FIT;  //Error 28: Select item cannot fit into mem ...

也不是我遇到的  是另外一个用户遇到的  还是在实机上。。。  http://bbs.wuyou.net/forum.php?m ... &fromuid=330930

我再想想怎么办吧  因为是用脚本实现的检索文件  如果强行截断的话用户又该说脚本有bug  找不到文件了。。。
作者: 不点    时间: 2013-7-2 10:09
zhaohj 发表于 2013-7-2 09:41
if (arg_len > 0x8000)
        {
            errnum = ERR_WONT_FIT;  //Error 28: Select item cannot fit into mem ...

列文件所占的空间,32K 绝对不够。即使预留 1M 也不够。这应该属于 “超限使用 grub4dos” 的范畴吧。
作者: 2011yaya2007777    时间: 2013-7-2 10:14
是不是修改了 chainloader 命令,让它识别 0.4.6a 的 GRLDR 格式?

是的。错误源于判断原 0x2000 处的内核头部 4 字节 EA 70 82 00 。现在 0x2000-0x33ff 插入 usb 驱动代码,内核头部移动到了 0x3400。
建议:0.4.5c 与 0.4.6a 同时打补丁。
作者: chenall    时间: 2013-7-2 10:15
本帖最后由 chenall 于 2013-7-2 10:16 编辑
sratlf 发表于 2013-7-2 10:07
也不是我遇到的  是另外一个用户遇到的  还是在实机上。。。  http://bbs.wuyou.net/forum.php?mod=redir ...


先用这个试试吧,取消了批处理call的参数长度限制..

只受限于重定向输出缓冲区大小,目前是128KB,如果这样还不够用的话需要自己想办法了,我WIN7的I386目录列表也没有超过64KB.

grub4dos-0.4.5c-07-02.rar

135.26 KB, 下载次数: 15, 下载积分: 无忧币 -2


作者: sratlf    时间: 2013-7-2 10:27
chenall 发表于 2013-7-2 10:15
先用这个试试吧,取消了批处理call的参数长度限制..

只受限于重定向输出缓冲区大小,目前是128KB,如果 ...

应该是没问题了  虚拟机测试通过
作者: chenall    时间: 2013-7-2 10:36
2011yaya2007777 发表于 2013-7-2 10:14
是的。错误源于判断原 0x2000 处的内核头部 4 字节 EA 70 82 00 。现在 0x2000-0x33ff 插入 usb 驱动代码 ...

@不点

不知是否可以使用0x1FFC处的grldr_signature来判断?这个应该不会变吧.


作者: 不点    时间: 2013-7-2 23:47
本帖最后由 不点 于 2013-7-3 00:56 编辑
2011yaya2007777 发表于 2013-7-2 10:14
是的。错误源于判断原 0x2000 处的内核头部 4 字节 EA 70 82 00 。现在 0x2000-0x33ff 插入 usb 驱动代码 ...


为何要插入到内核头部之前?在 asm.S 中实现,不是更好吗?

挪动内核头部,只怕会带来一连串的不兼容问题。

给 0.4.5c 打补丁,那么老版本就放弃支持了?这个思路是不对头的。假如实在没有办法了,只好这么做。问题是,我很怀疑这是 “实在没办法” 了。

幸亏原来的代码检查内核头部,否则你这个改动所带来的混乱,不知道会等到何时才能发现。

当我们能够保持兼容性的时候,就不要破坏兼容性。除非是做不到,或者代价太高。

这个 USB 驱动也属于内核吧?那么他就应该放在内核头部之后。

grldr 的头部只有 8K 是可以被 NTLDR 加载的。你的 0x2000-0x33ff 的代码,不可能被 ntldr 加载到。所以,它放在这里没有意义,不如放在内核头部之后好。



背景:

内核起始于 grldr 偏移 0x2000,是固定的。内核头部有很多控制变量,是用户可以读写的。用户甚至在启动 grldr 之前可以动态修改内核头部中的变量,比如,启动盘的 drive number 以及启动盘的 chs 信息。你把头部一挪动,那原来的外部程序就要写错位置,失效了。

内核头部还记录了 preset menu 的位置。外部程序可以读出内核头部的指针,计算出 preset menu 的位置。头部被挪动到 0x2000 之后,那些外部程序都要泡汤了。

甚至 grldr 自己的头部代码(位于 grldr 第2扇区的代码)也写内核头部信息(有关 PXE 启动的控制信息)。头部一挪动,就好像没有坐标了,所有的东西都得改。

我们的文档早都公开过了(虽然是零零散散公开的),内核头部起始于 grldr 的偏移 0x2000 处。头部的变量也公布了。外部程序都把这当成依据了。此时再挪动,那不就是自乱阵脚吗?连文档也得修改了。

现在忽然想起,论坛上报告 bootice 写 preset menu 竟然会导致程序死锁,写入的结果 grldr 文件竟然达 4G 之多!我感到很疑惑:怎么会呢?这下子终于可以猜到原因了:内核头部被挪动造成的。

作者: 2011yaya2007777    时间: 2013-7-3 07:25
好吧,那就在 asm.S 中实现。
那只能是在加载 grldr 之后,从菜单中加载 usb 驱动了。
怎样从菜单加载?即菜单语句如何写?如何带入参数?可否给一个示例?
作者: chenall    时间: 2013-7-3 08:50
本帖最后由 chenall 于 2013-7-3 08:51 编辑

这个驱动是如何调用的???

目前的call命令可以调用某个地址处的程序.
比如这个驱动程序的开始地址是0x8000

则可以用以下命令来调用,后面还可以加参数
call Fn.0x8000

一个例子:
我们知道grub_printf函数的地址在(*(int **)0x8300)[0]处.
这时先读取0x8300处的值
read 0x8300
比如得到的值是0x30d81d
再读一下0x30d81d的值就是printf函数的地址了.
read 0x30d81d
比如得到的值是0x324e47
现在我们知道printf函数的地址了就可以调用.

call Fn.0x324e47 0 "Test Printf"
上面就是call Fn.X 功能的执行过程.这些内部函数都已经简化了处理方法直接调用第几个函数就行了.
call Fn.0 和上面的是一样的.

当然了这个应该是只能调用32程序.
作者: 不点    时间: 2013-7-3 09:54
2011yaya2007777 发表于 2013-7-3 07:25
好吧,那就在 asm.S 中实现。
那只能是在加载 grldr 之后,从菜单中加载 usb 驱动了。
怎样从菜单加载?即 ...

不知情者,不为过。其实那很简单啊。asm.S 的第一条指令就是 JMP 指令。你顺着 JMP 指令走,看看你的代码适合插入在什么地方,就可以插入了。你的代码不长,只有几个 K 的大小,可以插入。还可以把你的代码放在 asm.S 中的某个位置,然后用 call 指令调用你的代码便可。

在 asm.S 的 618 行,有如下注释和代码:

/* transition to protected mode */
call EXT_C(real_to_prot)

这显然是必经之路,切换到保护模式。所以,如果你的实模式代码插入到这个之前,肯定会执行的。这只是举例而已,其实可插入的地方很多,你自己看究竟插入到什么地方最合适,就插入到什么地方。如果你不知道插入到哪里最合适,那就插入到这里吧:

1:
#endif /* !STAGE1_5 */

你的 USB 实模式处理程序插入在这里

/* transition to protected mode */
call EXT_C(real_to_prot)


asm.S 在切换到 32 位保护模式并做适当的准备工作后,就要调用 common.c 中的 C 语言程序 init_bios_info () 和 stage2.c 里面的 cmain()。

call EXT_C(init_bios_info)
call EXT_C(cmain)

如果你的代码可以转换成 32 位的 C 语言代码,你也可以把它插入到 call init_bios_info 之前,或者插入在 call init_bios_info 和 call cmain 之间。cmain 就是开始处理菜单的地方,也就是真正的 grub4dos 的核心主程序。
作者: 2011yaya2007777    时间: 2013-7-3 10:07
比如在 asm.S 中有一 grub_usb 函数,如何知道函数的地址?
作者: 2011yaya2007777    时间: 2013-7-3 10:19
不知情者,不为过

好吧,我试一试
作者: 2011yaya2007777    时间: 2013-7-4 16:45
已经把 usb 驱动放在 asm.S 中。使用方法依旧。




欢迎光临 无忧启动论坛 (http://bbs.c3.wuyou.net/) Powered by Discuz! X3.3