无忧启动论坛

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

准备基于 fbinst 进行再开发,请各位提供帮助

    [复制链接]
91#
 楼主| 发表于 2014-10-27 13:10:55 | 显示全部楼层
Diskgen 是在 win7 下操作的吗?试试在 xp 下操作。估计是 win7 系统修改了写入的数据。你可以比较一下,看看 win7 究竟更改了什么内容?
回复

使用道具 举报

92#
 楼主| 发表于 2014-10-27 16:59:18 | 显示全部楼层
不知道查看?没什么神秘的,take it easy。如果有时间折腾的话,试试下面的方法。

首先把你的 U 盘全部扇区清零。 然后在 XP 下操作,向 U 盘导入 multimbr 映像文件,向 U 盘拷入自己的测试文件,建立某个文件夹,用 diskgen 更改错误。之后,把 U 盘按照扇区备份起来。

接下来重复这个过程,但在 win7 下操作。

比较两次备份的结果,看看有什么不同,即可发现秘密。

点评

diskgen报了两次错误,一次是分区表参数溢出,一次是DBR参数溢出,diskgen可以自动修正分区表,DBR提示需要重新格式化 是不是windows7对分区表和DBR的检验更严格,有不对劲就报错?建议添加u盘总扇区数选项到编译  详情 回复 发表于 2014-10-27 17:35
回复

使用道具 举报

93#
 楼主| 发表于 2014-10-27 18:03:41 | 显示全部楼层
不是这样的。在 XP 下操作,diskgen 也只是修复分区表的错误,不修复 FAT表的总扇区数错误。通过前面的测试报告,我们知道,XP 下修复好了的,Win7 也认了,不再报错。这说明,win7 也不在乎 FAT 的总扇区数错误。

可以给 diskgen 的开发者提建议,要求自动修复 FAT 总扇区数错误。不要给出一条 “需要格式化” 的可怕信息。

总扇区数一般是用不到的。即使错误,(尤其是偏大)问题也不严重。


点评

用Winhex进行了二进制比较,竟然没发现不一样  详情 回复 发表于 2014-10-27 19:40
回复

使用道具 举报

94#
 楼主| 发表于 2014-10-27 19:46:14 | 显示全部楼层
本帖最后由 不点 于 2014-10-27 19:51 编辑
sunsea 发表于 2014-10-27 19:40
用Winhex进行了二进制比较,竟然没发现不一样


好啊,那就给你一个问号,让你的脑子不会闲着。那你再想想究竟是怎么回事呢?是不是 win7 下需要插拔一次 U 盘?或者还有别的什么步骤?

还有一种可能,导致你发现不了差别。那就是,Win7 可能拒绝写入某些扇区,但缓存中却允许有这些扇区,只是拒绝提交给 U 盘罢了。你截获的 U 盘扇区仅仅是 win7 缓存的,不是它真正写入 U 盘的。这样,你就找不出差别了。

点评

删了文件夹且插拔之后: 查找差异 1. 可移动磁盘 2: 32,212,250,624 字节 2. G:\dd-0.5\XP.img: 104,857,600 字节 Offsets: 16 进制 7E83E8: BF FF 7E83E9: D0 FF 7E83EA: 7D FF 7E83EB: 00 FF 7E  详情 回复 发表于 2014-10-27 20:00
弹出插拔之后比出毛病来了(对不起我往里面新建了一个文件夹,希望能忽略) 查找差异 1. 可移动磁盘 2: 32,212,250,624 字节 2. G:\dd-0.5\XP.img: 104,857,600 字节 Offsets: 16 进制 7E83E8: BE FF 7E  详情 回复 发表于 2014-10-27 19:58
重现问题步骤: 1。Windows7 SP1系统 2。一个32G Kingston DT101 G2的U盘 3.用mbr_32g.img写入,然后弹出再插入U盘 4.大规模写数据,我这大约写到2G时出现了无法创建文件,提示文件系统错误65536 5.用DiskGeniu  详情 回复 发表于 2014-10-27 19:50
回复

使用道具 举报

95#
 楼主| 发表于 2014-10-27 20:01:08 | 显示全部楼层
前面 datong 兄的报告说,即使只有很少的文件,也不能创建文件夹。你的报告过于复杂了,涉及文件太多,不利于定位问题的根源。

其实 8G,16G,32G 等都类似,只要通过一种方式确定问题的根源,就可以了。

所以,我想等待 datong 兄给出报告。

点评

明天考虑编写批处理来测试极限 建1000个文件夹,名字是编号,根目录下100个,然后每个目录下10个,每个目录下放一个内容是随机数的文件 然后记录出问题的编号  详情 回复 发表于 2014-10-27 20:07
这个比较报告除了新建了一个文件夹外没有任何其他东西,比处毛病没?参考的XP镜像是空的  详情 回复 发表于 2014-10-27 20:04
回复

使用道具 举报

96#
 楼主| 发表于 2014-10-27 20:11:00 | 显示全部楼层
本帖最后由 不点 于 2014-10-27 20:16 编辑

你还是重新做吧,别插入一些多余的步骤,不要创建多余的文件,然后再比较。

你可以保持 U 盘没有文件和文件夹,保持为空的,但用 diskgen 修正分区表,然后检测差别。

一步一步来,不要一开始就把问题引向复杂。


回复

使用道具 举报

97#
 楼主| 发表于 2014-10-28 09:04:35 | 显示全部楼层
好的,接下来试试首先用 diskgen 修复分区表,看看情况怎样。

我这里见不到 win7 电脑,所以,很难亲自测试。等哪天我找一台 win7 电脑了,便可亲自测试了。

回复

使用道具 举报

98#
 楼主| 发表于 2014-10-28 10:52:19 | 显示全部楼层
那麻烦您再做一个试验,导入的操作在 XP 下进行,用 diskgen 修复也在 XP 下进行。然后,在 XP 下拷入一两个文件,例如 menu.lst 之类的。然后,进入 win7,看看这次还出错误吗?

我不想太麻烦您。所以就做这最后一个试验吧。其余的情况,可能需要我亲自去试验了。

回复

使用道具 举报

99#
 楼主| 发表于 2014-10-28 15:54:04 | 显示全部楼层
我没有找到测试环境。不过现在似乎怀疑确实是 BPB 表上的总扇区数的错误使 win7 感到不舒服。

你可以再做一个试验,这次使用 mbr_8G.img 来执行导入到你的 16G 盘上。这样虽然浪费了后面的 8G,但保证了所有的 FAT32 扇区都是可访问的。这样,也不需要 diskgen 去纠正了(它也没什么可以纠正的,所有的数据都是正确的)。仍然在 XP 下执行操作,然后到 win7 下检验是否一切 OK?

回复

使用道具 举报

100#
 楼主| 发表于 2014-10-28 17:15:17 | 显示全部楼层
本帖最后由 不点 于 2014-10-28 17:25 编辑

好的,症结找到了,容我思考对策。也许需要一些时日,才能权衡出一个可行的对策。

如果您方便的话,也可以试试在 win7 下执行前面这个导入的操作,看看是不是也 OK 了?


嗯——初步的对策:向 diskgen 的开发者求助!让 diskgen 来修复 BPB 的总扇区数,只需修复扇区号为 63 的那个扇区的 BPB 表即可,别的都不用动,这是因为 Windows 只访问扇区 63 处的 BPB(它是 FAT32 分区的合法首扇区),不会承认别的 BPB,所以,即使别的 BPB 改了也不起作用。

能否烦劳您给 diskgen 的开发者提出这个建议呢?

点评

或者求医不如求己,编译脚本里增加指定总扇区数的选项,然后BPB和分区表都按输入配置  详情 回复 发表于 2014-10-28 18:47
回复

使用道具 举报

101#
 楼主| 发表于 2014-10-28 21:03:46 | 显示全部楼层
本帖最后由 不点 于 2014-10-28 21:05 编辑
sunsea 发表于 2014-10-28 18:47
或者求医不如求己,编译脚本里增加指定总扇区数的选项,然后BPB和分区表都按输入配置


这也确实是个方案。以前的 三重 mbr 就是与容量无关的,适应于任意的容量。不过,这次没按那种方案来处理。这次的方案比较简单,只提供四种容量,无需专门的安装程序。三重mbr以及后来的fbinst,都是需要专门的安装程序。各有优缺点。

我们这次唯一需要的,就是一个能够修复分区表以及bpb表的工具。这些工具,可以是某个通用的工具,无需我们重复编写,也算是节约资源,低碳环保吧。

点评

我有时间试着写写。另:应该修正所有的BPB和分区表,因为有些弱智的BIOS可能会拿中间任意一个分区表和BPB读盘然后去读不存在的扇区引起各种Bug  详情 回复 发表于 2014-10-28 22:47
回复

使用道具 举报

102#
 楼主| 发表于 2014-10-29 06:47:30 | 显示全部楼层
本帖最后由 不点 于 2014-10-29 06:57 编辑
sunsea 发表于 2014-10-28 22:47
我有时间试着写写。另:应该修正所有的BPB和分区表,因为有些弱智的BIOS可能会拿中间任意一个分区表和BPB ...


其它分区表和bpb无需修复,因为windows看不见它们,不承认它们。而bios以及grub4dos都不使用总扇区数,基本上是永远用不着它。你在win7下如果不写盘而只是读盘,你也用不上总扇区数。

所以,我们不需要工具,只要有 diskgen 来修复就够了。用 bootice 的扇区修改能力手动修复也行。

假如你真想做这个工作,可以参考 bootlace.com 的做法。不过感觉没什么迫切性。
回复

使用道具 举报

103#
 楼主| 发表于 2014-10-29 10:48:58 | 显示全部楼层
谢谢您的支持。2048 扇区只有 1M,不够用。multimbr 是与 fbinst 等价的技术,至少需要 8M 才行。

三重 mbr、fbinst 和此处所讨论的 multimbr,都是 U 盘启动技术,不便于用在普通硬盘上。普通硬盘可以使用 wee 或者类似的技术。不同的软件都有各自的使用范围,各司其职,不能混乱。

回复

使用道具 举报

104#
 楼主| 发表于 2014-10-29 18:00:36 | 显示全部楼层
本帖最后由 不点 于 2014-10-29 23:51 编辑

谢谢您辛苦验证和回馈。

就是说,大家用 hex 工具修复分区表和 BPB 表即可。diskgen 已经能够修复分区表了,只差修复 BPB 表了。

各位可以用 google 搜索一下,看看网络上还有没有能够修复分区表和 BPB 的工具。

我记得有个 partition guru 的软件,不知道有没有这功能。

还有一个软件,叫 partition table doctor,也可以用来修复 boot sector。

点评

现在需要那个带一个主分区和一个拓展分区的那个镜像了,刚买了1T的移动硬盘  详情 回复 发表于 2014-11-2 09:17
做了个修复BPB和分区表的小工具,要安装VC2008运行库 建议用管理员权限运行 球排查Bug http://pan.baidu.com/s/1gdrIvXh 注意,别选错了!这会毁了你的硬盘!  详情 回复 发表于 2014-11-1 19:58
回复

使用道具 举报

105#
 楼主| 发表于 2014-11-2 11:04:29 | 显示全部楼层
sunsea 发表于 2014-11-2 09:17
现在需要那个带一个主分区和一个拓展分区的那个镜像了,刚买了1T的移动硬盘

下次编译的时候,就再编译出来吧。目前你可以暂时用 diskgen 添加一个扩展分区以及逻辑分区。

点评

我如此操作了(重新编译了菜单,改成了0PE的和10-29的0.4.6),然后启动错误,什么都没看到(显示器延迟很大),只看见一个光秃秃的菜单,键盘用不了,什么菜单上的字都没看到,用G4D的默认MBR正常,就是用的那个1T  详情 回复 发表于 2014-11-2 14:29
回复

使用道具 举报

106#
 楼主| 发表于 2014-11-2 14:53:14 | 显示全部楼层
恐怕是你导入自己的菜单,出现了错误。用原始的、未经改动的 8G 映像来制作,应该不会有问题吧?

如果你想更改内置菜单,你只需更改 preset_menu.lst 文件。敲入 make 编译时,这个菜单会自动替换掉 grldr 里面的内置菜单。

点评

补充,我那个32g的U盘上用的是某个旧版g4d,但都是同一个0PE,32g上的内置菜单lzma压缩了。1T移动硬盘上的没有 会不会是个bug,不认识内置的未lzma压缩的菜单中的字模?  详情 回复 发表于 2014-11-2 15:05
我就是这么干的。我在我的32G的u盘上实验没有出现这个问题  详情 回复 发表于 2014-11-2 14:57
回复

使用道具 举报

107#
 楼主| 发表于 2014-11-2 15:02:20 | 显示全部楼层
你确定一下是什么问题。引导 grldr 之前的过程都正常吧?怀疑 0.4.6 有问题,换成 0.4.5 的试试。
回复

使用道具 举报

108#
 楼主| 发表于 2014-11-2 15:10:16 | 显示全部楼层
本帖最后由 不点 于 2014-11-2 15:12 编辑
sunsea 发表于 2014-11-2 15:05
补充,我那个32g的U盘上用的是某个旧版g4d,但都是同一个0PE,32g上的内置菜单lzma压缩了。1T移动硬盘上 ...


内置菜单如果不大,无需压缩。用 lzma 压缩了应该也行。如果内置菜单太大,那可能超过 grldr 的处理能力了。如果内置菜单可以控制在 4K 以内,则无需压缩。超过 4K,必须压缩。

点评

奥对,未压缩的0PE的菜单是11K[加上字模],压缩后变成4K多一点  详情 回复 发表于 2014-11-2 15:12
回复

使用道具 举报

109#
 楼主| 发表于 2014-11-2 15:27:56 | 显示全部楼层
sunsea 发表于 2014-11-2 15:12
奥对,未压缩的0PE的菜单是11K[加上字模],压缩后变成4K多一点,但问题是压缩后也比4k多啊

压缩后可以超过 4K,最大可以达到 32K,都能处理。但未压缩的内置菜单只能是 4K 以内。这是兼容性的处理,没办法。以前都是在低端内存地址 0x800 处放置内置菜单,空间只有 4K。压缩后,采用不同的内存地址,放在 1M 以上,空间很大,因此,可以达到 32K(这是压缩后的大小,压缩前当然可以更大了)。

点评

我用了lzma压缩过的菜单再写了一次,因为前面也用8g镜像部署了一遍,所以就只写了前3000扇区。结果提示如下,为什么[g4d没到3000扇区这个位置,我也没放别的东西,就是改了0扇区分区表添加了拓展分区]  详情 回复 发表于 2014-11-2 15:45
回复

使用道具 举报

110#
 楼主| 发表于 2014-11-2 15:51:45 | 显示全部楼层
你写错位置了,也许是从 PBR 开始写的。从头来吧。

点评

现在OK了,不过0PE无法启动,加载了SRS之后过一会儿就在那光标闪  详情 回复 发表于 2014-11-2 16:26
回复

使用道具 举报

111#
 楼主| 发表于 2014-11-2 17:23:22 | 显示全部楼层
sunsea 发表于 2014-11-2 16:26
现在OK了,不过0PE无法启动,加载了SRS之后过一会儿就在那光标闪


这问题或许是你的 0pe 文件被破坏了?与 grub 没太大关系。
回复

使用道具 举报

112#
 楼主| 发表于 2014-11-3 11:01:43 | 显示全部楼层
我又考虑了一下,觉得建立扩展分区或者另外一个主分区的工作,最好是用一个外部的工具来做。

因为 multimbr 的内部设计是不知道 U 盘的大小的,所以,它建立的扩展分区或主分区也都很盲目。

如果太大,容易造成读取不存在的扇区而死机。如果太小,又浪费了 U 盘空间。

所以,这个工作目前最好是由第三方的工具来做。

回复

使用道具 举报

113#
 楼主| 发表于 2014-11-16 21:33:45 | 显示全部楼层
本帖最后由 不点 于 2014-11-18 18:01 编辑

1、时代在前进,U 盘很便宜,所以,没有必要支持小于 8G 的 U 盘。
2、开头的 190 个扇区,每个扇区都带有 bpb 和 分区表。bpb 上的总扇区数比同一扇区上的分区表上的分区长度正好多了 63。
3、U 盘的总扇区数填在最开头的那个扇区的 bpb 表上。
4、U 盘的总扇区数减去 63,得到第一分区的总扇区数。这个总扇区数是填在最开头的那个扇区的分区表上的。
5、其后的每个扇区,其 bpb 总扇区数逐步递降,其分区表上的分区长度也是逐步递降。

6、只用一个 fat 表,原则上也行,但微软建议 fat 表取 2 个。这个,你自己决定吧。
7、每个 fat 表的长度(即扇区数),固定采用以下值:0x3F00 或 0x7E00 或 0xFC00 或 0x1F800 或 0x3F000 等等,分别相应于 8G、16G、32G、64G、128G 等等的 U 盘。这些值都是成倍增加的。详述如下:

当 U 盘总扇区数 <= 0x3F60 + 1026*0x003F00 时,Fat 表长度为 0x003F00 ---- 就是大约 8 G 的 U盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x007E00 时,Fat 表长度为 0x007E00 ---- 就是大约 16G 的 U盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x00FC00 时,Fat 表长度为 0x00FC00 ---- 就是大约 32G 的 U 盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x01F800 时,Fat 表长度为 0x01F800 ---- 就是大约 64G 的 U 盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x03F000 时,Fat 表长度为 0x03F000 ---- 就是大约 128G 的 U 盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x07E000 时,Fat 表长度为 0x07E000 ---- 就是大约 256G 的 U 盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x0FC000 时,Fat 表长度为 0x0FC000 ---- 就是大约 512G 的 U 盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x1F8000 时,Fat 表长度为 0x1F8000 ---- 就是大约 1024G 的 U 盘
当 U 盘总扇区数 <= 0x3F60 + 1026*0x3F0000 时,Fat 表长度为 0x3F0000 ---- 就是大约 2048G 的 U 盘

点评

那190个扇区的扇区号分布情况?是直接写入Windows下对应扇区号就行了嘛  详情 回复 发表于 2014-11-17 06:55
回复

使用道具 举报

114#
 楼主| 发表于 2014-11-17 08:23:52 | 显示全部楼层
本帖最后由 不点 于 2014-11-17 08:29 编辑

这样吧,接下来我把 buildimg.sh 的注释添加在这里,你慢慢研究。生成的 mbr_??G.IMG 文件,应该直接写入 U 盘最开头,即,必须从扇区号 0(即,从 MBR 扇区) 开始覆盖 U 盘。初次编程,也有可能错把 PBR 当成 MBR,你写入之后,用 BOOTICE 的扇区编辑功能检查一下 MBR 是否已经改变,如果没有改变,那你有可能写入到 PBR 了。

注意,写入本地硬盘没有意义,硬盘都支持 LBA,无需采用这种特殊的启动技术。所以,你的程序最好能够判断出磁盘类型,不要给用户造成破坏。

回复

使用道具 举报

115#
 楼主| 发表于 2014-11-17 09:20:08 | 显示全部楼层
本帖最后由 不点 于 2014-11-18 18:14 编辑

  1. if [ "$1" = "" ]; then
  2.         # write error message to /dev/stderr
  3.         echo "Please use \`make' to build images. exit!" 1>&2
  4.         exit 1
  5. elif [ "$1" = "mbr_8G.img" ]; then
  6.         # 0x3F00=16128
  7.         fatsize=16128
  8. elif [ "$1" = "mbr_16G.img" ]; then
  9.         # 0x7E00=32256
  10.         fatsize=32256
  11. elif [ "$1" = "mbr_32G.img" ]; then
  12.         # 0xFC00=64512
  13.         fatsize=64512
  14. elif [ "$1" = "mbr_64G.img" ]; then
  15.         # 0x1F800=129024
  16.         fatsize=129024
  17. elif [ "$1" = "mbr_128G.img" ]; then
  18.         # 0x3F000=258048
  19.         fatsize=258048
  20. else
  21.         # write error message to /dev/stderr
  22.         echo "Invalid image file name: $1. exit!" 1>&2
  23.         exit 1
  24. fi
复制代码

Makefile 调用 buildimg.sh 的语法是这样的:

sh  buildimg.sh mbr_8G.img
sh  buildimg.sh mbr_16G.img
sh  buildimg.sh mbr_32G.img
sh  buildimg.sh mbr_64G.img
sh  buildimg.sh mbr_128G.img

可以手动执行这几条命令中的任意一条。这个脚本目前没有支持 256G 或更大的 U 盘,但你的软件可以很容易照葫芦画瓢添加支持直到 2048G 的 U 盘。
  1. if [ ! -f multimbr.mbr ]; then
  2.         # write error message to /dev/stderr
  3.         echo "Cannot find multimbr.mbr, exit!" 1>&2
  4.         exit 1
  5. fi
复制代码

需要用 multimbr.mbr 中的代码来构建 mbr_?G.img 的前 191 个扇区(扇区 0 至扇区 190)。multimbr.mbr 总共是由两个扇区构成的。

multimbr.mbr 的第一个扇区的代码用来构建 mbr_?G.img 的前 190 个扇区(扇区 0 至扇区 189)。
multimbr.mbr 的第二个扇区的代码用来构建 mbr_?G.img 的扇区 190。

扇区 0 - 扇区 189,共 190 个扇区,填充的是第一阶段的扇区。目的是为了能够捕捉到 BIOS 传递过来的控制。只要屏幕有显示信息,就是捕捉到了控制。第一阶段在完成必要的探测之后,会同时加载第二阶段(扇区 190)和第三阶段(它是 GRLDR,位于扇区 191 至扇区 1341)的代码到内存 0000:7E00。

首扇区的扇区序列号为 0x3F60,往后逐步递降,递降到最小的扇区序列号 0x0020 为止(它就是扇区 16192 的扇区序列号)。再往后则是 FAT32 的数据结构,因此,那是不可以随便填入扇区序列号的。

multimbr.mbr 是由源代码文件 multimbr.S 编译生成的。它是这个软件的核心,是保证启动成功率的关键。测试稳定之后,它们一般就不会随便改动了。所以,你可以直接把 multimbr.mbr 嵌入到你的软件里面。multimbr.S 是 public domain 的,你可以用于任何目的,请看授权协议。但 GRLDR 是 GPL 软件,大概你只能把它单独放在你的软件包里面,而且你还得提供源代码,或者告知源代码如何能够让别人获得。
  1. if [ ! -f grldr ]; then
  2.         # write error message to /dev/stderr
  3.         echo "Cannot find grldr, exit!" 1>&2
  4.         exit 1
  5. fi
复制代码

从扇区 191 开始,至扇区 1341,共 1151 个扇区,要放置 GRLDR 了,这当然是把原始的 grldr 嵌入扇区序号以后再放置到这里的。所以,没有 GRLDR 是不行的,要报错退出。

但是启动代码并不检查 GRLDR 的结构,你可以用任何东西来冒充 GRLDR,让 multimbr 的核心代码去加载执行。

第一阶段的 multimbr 代码(即 multimbr.mbr 的第一扇区代码,也即 mbr_?G.img 的开头 190 个扇区上的代码)会把控制权交给第二阶段的 multimbr 代码(即 multimbr.mbr 的第二扇区代码,也即位于 mbr_?G.img 的扇区号 190 上的代码),内存地址是 0000:7E00。然后第二阶段代码再把控制权交给第三阶段的 GRLDR,内存地址是 0000:8000。

扇区 190,共 1 个扇区,是第二阶段的扇区(stage2),它的物理序列号是 0x3EA2。第二阶段接管控制时, CS:IP=0000:7E00。第二阶段的代码首先检查 CPU 寄存器以及内存的数据是否正常,如果有错误,则停机并打印失败信息,让用户了解失败的原因。如果一切正常,则把内存中的第三阶段的 GRLDR 进行整理(即去掉其内嵌的物理序列号);然后打印一条信息,让用户有机会按 P 键暂停。用户松开 P 键,2 秒之后就启动 GRLDR 了。用户每秒按一次 P 键,可保持程序处于暂停状态。GRLDR 取得控制时, CS:IP=0000:8000,DH=0xFF,DL=启动盘的盘号(0 是软盘,0x80 是硬盘);同时,堆栈上也压入了 DX 的值,虽然这对于 GRLDR 来说,没什么用处。

扇区 191 - 扇区 1341,共 1151 个扇区,是第三阶段的扇区(grldr)。注意,它的每个扇区都带有正确的物理序列号。它的物理序列号是从 0x3EA1 (十进制 16033)开始的,逐步递降。grldr 的最后一个扇区的物理序列号是 0x3A23(十进制 14883)。

扇区 1342 - 扇区 16192,共 14851 个扇区(大约 7M),是空白扇区,但每个扇区都带有物理序列号。其最开头的扇区的物理序列号是 0x3A22(十进制 14882),其结尾的扇区的物理序列号是 0x0020(十进制 32)。空白扇区是用户可以使用的。当然了,用户不可以破坏扇区的物理序列号,要保持正确的物理序列号。用户可能需要在自己的 menu.lst 菜单中添加自己的特殊工具,才能使用空白扇区上的数据。

从扇区 16193 开始,是 FAT32 的文件系统结构扇区。其开头的 31 个扇区(0x1F 个扇区)是保留扇区。紧接着是两份 FAT 表。在两份 FAT 表之后,紧接着是根目录,占用 8 个扇区(也就是 4K,这也就是我们所使用的 cluster “簇” 的长度)。因为根目录是空的,里面没有东西,所以,这 8 个扇区都填满了 00 字节。
  1. if [ ! -f preset_menu.lst ]; then
  2.         # write error message to /dev/stderr
  3.         echo "Cannot find preset_menu.lst, exit!" 1>&2
  4.         exit 1
  5. fi
复制代码

原始 grldr 的内置菜单会被修改为 preset_menu.lst 的内容。所以,preset_menu.lst 必须存在。
  1. # locate bootlace signature
  2. i=$((0x2000+$(od -A n -j 0x206C -N 4 -t u4 grldr)-0x8200))
  3. j=$((0xce1a02b0-$(od -A n -j $i -N 4 -t u4 grldr)))

  4. if [ "$j" != 0 ]; then
  5.         # write error message to /dev/stderr
  6.         echo "Unrecognized grldr. exit!" 1>&2
  7.         exit 1
  8. fi
复制代码

检查是不是 GRLDR 文件,如果不是的,那就没法修改内置菜单了。
  1. if [ ! -f grldr.new ] || [ grldr.new -ot grldr ]; then
  2.         # write message to /dev/stderr
  3.         echo Updating grldr.new ... 1>&2

  4.         {
  5.                 # duplicate the head
  6.                 dd bs=8197 skip=0 count=1 2> /dev/null

  7.                 # discard the control byte
  8.                 dd bs=1 count=1 2> /dev/null 1>&2

  9.                 # write new control byte and disable PXE
  10.                 printf "\x01"

  11.                 # duplicate the body and locate the preset menu
  12.                 dd bs=$((i+16-8198)) count=1 2> /dev/null

  13.                 # write our new preset menu.
  14.                 cat preset_menu.lst

  15.                 # end the menu with a null
  16.                 printf "\x00"

  17.         } < grldr > grldr.new
  18. fi
复制代码

修改了 grldr 的控制字节,屏蔽掉 PXE 功能,启动更安全可靠。同时也修改了内置菜单。生成了新的 grldr.new,这才是真正要安装的第三阶段启动文件。
  1. # Redirect stdout to destination image file
  2. exec > $1
复制代码

这条命令的意思是,接下来所有的输出都重定向到 mbr_?G.img。
  1. # two FATs, data area
  2. # data area=fatsize * clusters_per_FAT32_sector * sectors_per_cluster
  3. # clusters_per_FAT32_sector = 512 / 4 = 128
  4. # sectors_per_cluster = 8
  5. # 128 * 8 = 1024
  6. # data area = fatsize * 1024
  7. # two FATs = fatsize * 2
  8. # two FATs + data area = fatsize * 1026
  9. t=$((fatsize*1026))

  10. i=16224; #; i=$((33+126+255*63))
复制代码

t 是从 FAT 表开始的 FAT32 卷所占用的全部扇区数。
16224 就是 0x3F60,它是首扇区的序列号。序列号是逐步递降的。从首扇区(扇区 0)至扇区 16192,每个扇区都带有序列号。从 16193 开始,所有的扇区都不再带有序列号。

16224+t 就是整个 U 盘的总扇区数。
  1. j=0
  2. a=0
  3. b=0

  4. cat grldr.new /dev/zero | while [ $i -gt 31 ]; do
复制代码

扇区序列号大于 31,意思是从首扇区一直延续到扇区 16192。扇区 16192 的扇区序列号是 32(=0x20)。
  1.         a=$((i&255))
  2.         b=$(((i>>8)&255))
复制代码

扇区序列号的低字节放在变量 a 中,高字节放在变量 b 中。
  1.         k=$((i+t))
复制代码

第一个 FAT 表位于扇区 16224,所以,这里的变量 k 就是从当前扇区开始直到 FAT32 分区结尾处的扇区数。
  1.         l=$((k-63))
复制代码

变量 L 比 k 小 63。表示当前扇区的分区表上的 FAT32 卷的长度。
  1.         c=$((k&255))
  2.         d=$(((k>>8)&255))
  3.         p=$(((k>>16)&255))
  4.         q=$(((k>>24)&255))
  5.         y=$((l&255))
  6.         z=$(((l>>8)&255))
  7.         r=$(((l>>16)&255))
  8.         s=$(((l>>24)&255))
复制代码

c,d,p,q 是 k 从低到高的四个字节。y,z,r,s 是 L 从低到高的四个字节。
  1.         m=$((i-32+1))
  2.         n=$((i-32+6))
  3.         e=$((m&255))
  4.         f=$(((m>>8)&255))
  5.         g=$((n&255))
  6.         h=$(((n>>8)&255))
复制代码

m, n 是保存 FAT32 文件系统信息的扇区的指针。e,f 是 m 的两个字节。g,h 是 n 的两个字节。
  1.         if [ $j -lt 190 ]; then
复制代码

下面这一段是生成第一阶段的扇区,即,扇区号小于 190 的那些扇区。
  1.         #; 190 MBR sectors (stage 1)
  2.         printf "\xEB\x5E\x90\x4D\x53\x57\x49\x4E\x34\x2E\x31\x00\x02\x08\x$(printf %x $a)\x$(printf %x $b)\x02\x00\x00\x00\x00\xF8\x00\x00\x3F\x00\xFF\x00\x3F\x00\x00\x00\x$(printf %x $c)\x$(printf %x $d)\x$(printf %x $p)\x$(printf %x $q)\x$(printf %x $((fatsize&255)))\x$(printf %x $(((fatsize>>8)&255)))\x$(printf %x $(((fatsize>>16)&255)))\x$(printf %x $(((fatsize>>24)&255)))\x00\x00\x00\x00\x02\x00\x00\x00\x$(printf %x $e)\x$(printf %x $f)\x$(printf %x $g)\x$(printf %x $h)"
复制代码

先写入扇区开头的 52 个字节,属于 BPB 的范畴。固定的那些域,不再解释。可变的那些数据有:扇区序列号,总扇区数,每个FAT表所占用的扇区数,以及保存 FAT32 文件系统信息的两个扇区的指针。
  1.         dd if=multimbr.mbr bs=1 skip=52 count=406 2> /dev/null
复制代码

从 multimbr.mbr 取 406 字节,当然,先跳过 52 个字节,因为刚才已经写好了 52 字节。只需从 multimbr.mbr 中取出 406 字节。因此,总共已经生成的字节数是 406 + 52 = 458(=0x1CA)。那么,下一个字节所处的偏移就是 0x1CA,也就是分区表上的分区长度域。
  1.         printf "\x$(printf %x $y)\x$(printf %x $z)\x$(printf %x $r)\x$(printf %x $s)"
复制代码

是的,它就是分区长度的四个字节。
  1.         if true; then
复制代码

下面这段是要执行的,即,生成空的分区表项,不再创建第二个主分区(或扩展分区)
  1.                 # this will not create the second partition
  2.                 printf "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  3.         else
复制代码

下面这段目前被屏蔽,不会执行。假如执行它,则会生成第二主分区,其长度延伸到 U 盘的结尾。
  1.                 # this will create the second partition
  2.                 # 0xFFFFFFFF=4294967295
  3.                 len=$((4294967295-k))
  4.                 printf "\x00\xFE\xFF\xFF\x0C\xFE\xFF\xFF\x$(printf %x $c)\x$(printf %x $d)\x$(printf %x $p)\x$(printf %x $q)\x$(printf %x $((len&255)))\x$(printf %x $(((len>>8)&255)))\x$(printf %x $(((len>>16)&255)))\x$(printf %x $(((len>>24)&255)))"

  5.         fi
复制代码

下面这句,又生成两个空的主分区表项,并用 55 AA 结束这个扇区。
  1.         printf "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xAA"
  2.         true
  3.     elif [ $j -eq 190 ]; then
复制代码

下面这段,是生成扇区 190,它是第二阶段的扇区。第一阶段的扇区在接管控制以后,会把控制权交给第二阶段的这个扇区。
  1.         #; 1 sector of stage 2
  2.         dd if=multimbr.mbr skip=1 count=1 2> /dev/null
复制代码

第二阶段的扇区生成完毕,但要稍微多做一点工作,就是把 grldr.new 开头的 14 个字节打印出来(记住,所有的打印结果都是重定向到 mbr_?G.img 了)。
  1.         #; 1151 sectors for GRLDR(stage 3). It begins at sector 191.
  2.         dd bs=14 count=1 2> /dev/null
  3.         true
  4.     elif [ $j -lt 1341 ]; then
复制代码

下面这段,插入扇区序列号,打印 grldr.new 的 510 个字节;再插入下一个扇区序列号,再打印 grldr.new 的 510 字节;如此反复,直到扇区 1340 为止。
  1.         printf "\x$(printf %x $a)\x$(printf %x $b)"
  2.         dd bs=510 count=1 2> /dev/null
  3.         true
  4.     elif [ $j -eq 1341 ]; then
复制代码

下面这段,是处理第三阶段的最后一个扇区(也就是 grldr.new 的尾巴),扇区号是 1341。先打印出扇区序列号,然后又打印出 grldr.new 的 496 个字节。总共打印了 498 个字节,但加上先前在扇区 190 时多打印的 14 个字节,正好凑够 512 字节。所以,第三阶段的扇区生成完毕。
  1.         printf "\x$(printf %x $a)\x$(printf %x $b)"
  2.         dd bs=496 count=1 2> /dev/null
  3.         #; end of GRLDR at sector 1341
  4.         true
复制代码

如果存在 userdata 文件,则下一段会执行 break 命令退出循环。
  1.     elif [ -f userdata ]; then
  2.         break
  3.         true
  4.     else
复制代码

否则,如果不存在 userdata 文件,则执行下面这段,生成扇区 1342 至扇区 16192,它们是空扇区,但要嵌入扇区序列号。
  1.         #; 14851 empty sectors, from sector 1342 to sector 16192
  2.         printf "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x$(printf %x $a)\x$(printf %x $b)"
  3.         dd if=/dev/zero bs=496 count=1 2> /dev/null
  4.         true
  5.     fi
复制代码

下面是循环变量 j 递增,同时扇区序列号 i 递减。
  1.         i=$((i-1))
  2.         j=$((j+1))
  3. done
复制代码

如果存在 userdata 文件,则会执行下面这段。那就是用 userdata 生成扇区 1342 至扇区 16192,并嵌入扇区序列号。
  1. #; debug output: i=16224, j=0, a=0, b=0
  2. #; echo i=$i j=$j a=$a b=$b 1>&2
  3. #; exit

  4. if [ -f userdata ]; then
  5.         i=14882; #; i=$((33+126+255*63-1342))
  6.         j=1342
  7.     cat userdata /dev/zero | while [ $i -gt 31 ]; do
  8.         a=$((i&255))
  9.         b=$(((i>>8)&255))

  10.         if [ $j -eq 1342 ]; then
  11.             #; 14851 sectors for USERDATA, from sector 1342 to sector 16192.
  12.             dd bs=14 count=1 2> /dev/null
  13.             printf "\x$(printf %x $a)\x$(printf %x $b)"
  14.             dd bs=510 count=1 2> /dev/null
  15.             true
  16.         elif [ $j -lt 16192 ]; then
  17.             printf "\x$(printf %x $a)\x$(printf %x $b)"
  18.             dd bs=510 count=1 2> /dev/null
  19.             true
  20.         elif [ $j -eq 16192 ]; then
  21.             printf "\x$(printf %x $a)\x$(printf %x $b)"
  22.             dd bs=496 count=1 2> /dev/null
  23.             #; end of USERDATA at sector 16192
  24.             true
  25.         else
  26.             echo "It should not get here. Exit!" 1>&2
  27.             exit 1
  28.             true
  29.         fi

  30.         i=$((i-1))
  31.         j=$((j+1))
  32.     done
  33. fi
复制代码

以上告一段落,生成了 multimbr 的关键数据结构,其中每个扇区都带有扇区序列号。
以下生成的,则是起着辅助作用的 FAT32 数据结构。首先写 31 个 隐藏扇区。
  1. #; write 31 hidden sectors
  2. printf "\x52\x52\x61\x41"
  3. dd if=/dev/zero bs=480 count=1 2> /dev/null
  4. printf "\x72\x72\x41\x61\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xAA"
  5. dd if=/dev/zero bs=510 count=1 2> /dev/null
  6. printf "\x55\xAA"
  7. dd if=/dev/zero bs=2046 count=1 2> /dev/null
  8. printf "\x55\xAA\x52\x52\x61\x41"
  9. dd if=/dev/zero bs=480 count=1 2> /dev/null
  10. printf "\x72\x72\x41\x61\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xAA"
  11. dd if=/dev/zero bs=510 count=1 2> /dev/null
  12. printf "\x55\xAA"
  13. dd if=/dev/zero bs=11776 count=1 2> /dev/null
复制代码

然后写第一个 FAT 表:
  1. #; write the 1st FAT
  2. printf "\xF8\xFF\xFF\x0F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x0F"
  3. dd if=/dev/zero bs=$((fatsize*512-12)) count=1 2> /dev/null
复制代码

最后再写第二个 FAT 表,以及根目录的一个 cluster (8 个扇区)。至此,扇区数据全部生成完毕。
  1. #; write the 2nd FAT, and 8 more sectors(=1 cluster) for root dir
  2. printf "\xF8\xFF\xFF\x0F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x0F"
  3. dd if=/dev/zero bs=$((fatsize*512-12+4096)) count=1 2> /dev/null
复制代码


回复

使用道具 举报

116#
 楼主| 发表于 2014-11-28 19:44:38 | 显示全部楼层
sunsea 发表于 2014-11-28 19:30
就是如果写错了,屏幕回显的那个 053E什么意思

随机值,乱码。

写错了免谈。不可以写错。

点评

好吧,我部署工具刚刚写完。确认是从物理0扇区写的,但还是有这个毛病  详情 回复 发表于 2014-11-28 19:47
回复

使用道具 举报

117#
 楼主| 发表于 2014-11-28 19:50:33 | 显示全部楼层
是死机失败了吗?你写的代码部分肯定有错误。你可以和 mbr_8G.img 进行比较,看看差别在哪里。

点评

对,稍后比较毛病,正在添加重定向输出到镜像文件功能  详情 回复 发表于 2014-11-28 19:52
回复

使用道具 举报

118#
 楼主| 发表于 2014-11-29 22:12:10 | 显示全部楼层
sunsea 发表于 2014-11-29 18:41
为什么明明31个保留扇区我把字节数加起来只有三十个?

字节数加起来,等于 0x3E00,这不正是 31 个扇区吗?

回复

使用道具 举报

119#
 楼主| 发表于 2014-11-30 17:15:23 | 显示全部楼层
sunsea 发表于 2014-11-30 14:23
multimbr的部署工具写好了,拿去玩玩吧,内附源码,要装VC2008运行库

超级强悍。就等着你这一天呢。

大家多多测试,提出建议,不断改进,让这个工具成为我们主要的、可靠的多重 mbr 制作工具。

点评

为了应付可变的第一分区容量,我用了fbinst里面的格式化代码里的fat表大小计算公式,bean也真是牛。 还有,为什么我用fbinst里面的格式化代码里的fat表大小计算公式算出来的结果和WinHex报告的“应该的”大小结果  详情 回复 发表于 2014-11-30 17:26
回复

使用道具 举报

120#
 楼主| 发表于 2015-1-17 17:30:57 来自手机 | 显示全部楼层
本帖最后由 不点 于 2015-1-17 18:08 编辑

android 下的 firefox 真够垃圾,好不容易打的字,废掉了。其他浏览器经常崩溃,还不如 firefox。没辙了,只能忍受。

期待着某个好系统诞生。

==========

言归正传,撒手不管了。身体欠佳,另外,发现这个软件也遭到了封杀。我所以也就决定不再纠缠 x86 下的软件开发了。

封杀的技术细节,不再公布。

我是想告诉 zds1210,你以为这个软件能够达到理想的启动成功率,恐怕没那么好的事。

这个软件的下载量很少,竟然已经遭到封杀,爱动脑筋的人不妨开动脑筋,想想这里面大概的情况。

特别指出,软件能在你周围的机器运行,不能证明没有封杀。所谓的封杀,就是说,机器支持 bios,能运行别的启动软件,包括运行 fbinst,却不能正常使用这个软件。调试跟踪的结果,证明是封杀。至于说细节,不再公布。

会不会继续遭到大面积封杀,只有天知道。不过我已经没有兴趣编写 x86 软件了。

今后我也可能很少露面了。如果我不在论坛出现,有事可以用 email 联系。

点评

求封杀细节。看看能不能想想办法,送佛送到西啊  详情 回复 发表于 2015-1-17 18:14
回复

使用道具 举报

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

本版积分规则

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

闽公网安备 35020302032614号

GMT+8, 2024-5-18 03:06

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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