无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
楼主: 不点
打印 上一主题 下一主题

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

    [复制链接]
301#
发表于 2014-11-2 15:05:50 来自手机 | 只看该作者
不点 发表于 2014-11-2 14:53
恐怕是你导入自己的菜单,出现了错误。用原始的、未经改动的 8G 映像来制作,应该不会有问题吧?

如果你 ...

补充,我那个32g的U盘上用的是某个旧版g4d,但都是同一个0PE,32g上的内置菜单lzma压缩了。1T移动硬盘上的没有

会不会是个bug,不认识内置的未lzma压缩的菜单中的字模?

点评

内置菜单如果不大,无需压缩。用 lzma 压缩了应该也行。如果内置菜单太大,那可能超过 grldr 的处理能力了。如果内置菜单可以控制在 4K 以内,则无需压缩。  详情 回复 发表于 2014-11-2 15:10
回复

使用道具 举报

302#
 楼主| 发表于 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
回复

使用道具 举报

303#
发表于 2014-11-2 15:12:48 来自手机 | 只看该作者
本帖最后由 sunsea 于 2014-11-2 15:26 编辑
不点 发表于 2014-11-2 15:10
内置菜单如果不大,无需压缩。用 lzma 压缩了应该也行。如果内置菜单太大,那可能超过 grldr 的处理能力 ...


奥对,未压缩的0PE的菜单是11K[加上字模],压缩后变成4K多一点,但问题是压缩后也比4k多啊

EDIT:对不起,是我搞错了,压缩后变比4k略少

点评

压缩后可以超过 4K,最大可以达到 32K,都能处理。但未压缩的内置菜单只能是 4K 以内。这是兼容性的处理,没办法。以前都是在低端内存地址 0x800 处放置内置菜单,空间只有 4K。压缩后,采用不同的内存地址,放在 1M  详情 回复 发表于 2014-11-2 15:27
回复

使用道具 举报

304#
 楼主| 发表于 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
回复

使用道具 举报

305#
发表于 2014-11-2 15:45:57 来自手机 | 只看该作者
不点 发表于 2014-11-2 15:27
压缩后可以超过 4K,最大可以达到 32K,都能处理。但未压缩的内置菜单只能是 4K 以内。这是兼容性的处理 ...

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

YP20141102154051992.jpeg (1.22 MB, 下载次数: 64)

YP20141102154051992.jpeg
回复

使用道具 举报

306#
 楼主| 发表于 2014-11-2 15:51:45 | 只看该作者
你写错位置了,也许是从 PBR 开始写的。从头来吧。

点评

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

使用道具 举报

307#
发表于 2014-11-2 16:26:14 | 只看该作者
不点 发表于 2014-11-2 15:51
你写错位置了,也许是从 PBR 开始写的。从头来吧。

现在OK了,不过0PE无法启动,加载了SRS之后过一会儿就在那光标闪

点评

sunsea兄遇到的这个问题应该我和之前的类似。我的也是1T的移动硬盘,当时用的fbinstool格的盘然后可见区放的0pe。您可以参考下当时P大给我的回复哈:http://bbs.wuyou.com/forum.php?mod=redirect&goto=findpost&pti  详情 回复 发表于 2014-11-2 20:41
这问题或许是你点的 0pe 文件被破坏了?与 grub 没太大关系。  详情 回复 发表于 2014-11-2 17:23
回复

使用道具 举报

308#
 楼主| 发表于 2014-11-2 17:23:22 | 只看该作者
sunsea 发表于 2014-11-2 16:26
现在OK了,不过0PE无法启动,加载了SRS之后过一会儿就在那光标闪


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

使用道具 举报

309#
发表于 2014-11-2 20:41:27 | 只看该作者
本帖最后由 2013datong5624 于 2014-11-2 20:44 编辑
sunsea 发表于 2014-11-2 16:26
现在OK了,不过0PE无法启动,加载了SRS之后过一会儿就在那光标闪


sunsea兄遇到的这个问题应该我和之前的类似。我的也是1T的移动硬盘,当时用的fbinstool格的盘然后可见区放的0pe。你可以参考下当时P大给我的回复哈:http://bbs.wuyou.net/forum.php?m ... &fromuid=479076
回复

使用道具 举报

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

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

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

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

回复

使用道具 举报

311#
发表于 2014-11-16 17:47:13 来自手机 | 只看该作者
2013datong5624 发表于 2014-11-1 21:56
win8.1下无法选择u盘?

我日,用管理员运行就好了
回复

使用道具 举报

312#
发表于 2014-11-16 18:22:35 来自手机 | 只看该作者
请教一下不点老师,这个的扇区号分布之类的写部署工具要用的具体细节,看不懂Linux脚本

我要写部署工具

还有FAT数改为一会不会引发一些BUG行为
回复

使用道具 举报

313#
发表于 2014-11-16 18:27:16 来自手机 | 只看该作者
还有如何计算FAT表的占用长度?
回复

使用道具 举报

314#
 楼主| 发表于 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
回复

使用道具 举报

315#
发表于 2014-11-17 06:55:28 来自手机 | 只看该作者
不点 发表于 2014-11-16 21:33
1、时代在前进,U 盘很便宜,所以,没有必要支持小于 8G 的 U 盘。
2、开头的 190 个扇区,每个扇区都带有 ...

那190个扇区的扇区号分布情况?是直接写入Windows下对应扇区号就行了嘛
回复

使用道具 举报

316#
 楼主| 发表于 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,无需采用这种特殊的启动技术。所以,你的程序最好能够判断出磁盘类型,不要给用户造成破坏。

回复

使用道具 举报

317#
 楼主| 发表于 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
复制代码


回复

使用道具 举报

318#
发表于 2014-11-19 13:28:40 | 只看该作者
以后是UEFI的时代了,主要是Intel 主推的缘故,所以还是希望能支持UEFI吧
回复

使用道具 举报

319#
发表于 2014-11-21 16:52:37 | 只看该作者
支持不点,新手路过
回复

使用道具 举报

320#
发表于 2014-11-27 09:15:34 | 只看该作者
哎!希望看得懂的大神 针对这贴,早日制作出符合广泛小白们 使用的教程!
FB 这么火,一是兼容好,而是制作容易,上手快!
回复

使用道具 举报

321#
发表于 2014-11-28 19:30:57 来自手机 | 只看该作者
就是如果写错了,屏幕回显的那个 053E什么意思

点评

随机值,乱码。 写错了免谈。不可以写错。  详情 回复 发表于 2014-11-28 19:44
回复

使用道具 举报

322#
 楼主| 发表于 2014-11-28 19:44:38 | 只看该作者
sunsea 发表于 2014-11-28 19:30
就是如果写错了,屏幕回显的那个 053E什么意思

随机值,乱码。

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

点评

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

使用道具 举报

323#
发表于 2014-11-28 19:47:28 来自手机 | 只看该作者
不点 发表于 2014-11-28 19:44
随机值,乱码。

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

好吧,我部署工具刚刚写完。确认是从物理0扇区写的,但还是有这个毛病
回复

使用道具 举报

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

点评

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

使用道具 举报

325#
发表于 2014-11-28 19:52:30 来自手机 | 只看该作者
不点 发表于 2014-11-28 19:50
是死机失败了吗?你写的代码部分肯定有错误。你可以和 mbr_8G.img 进行比较,看看差别在哪里。

对,稍后比较毛病,正在添加重定向输出到镜像文件功能
回复

使用道具 举报

326#
发表于 2014-11-28 21:44:35 来自手机 | 只看该作者
为什么明明31个保留扇区我把字节数加起来只有三十个?
回复

使用道具 举报

327#
发表于 2014-11-29 18:41:51 | 只看该作者
为什么明明31个保留扇区我把字节数加起来只有三十个?

点评

字节数加起来,等于 0x3E00,这不正是 31 个扇区吗?  详情 回复 发表于 2014-11-29 22:12
回复

使用道具 举报

328#
 楼主| 发表于 2014-11-29 22:12:10 | 只看该作者
sunsea 发表于 2014-11-29 18:41
为什么明明31个保留扇区我把字节数加起来只有三十个?

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

回复

使用道具 举报

329#
发表于 2014-11-30 14:23:34 | 只看该作者
multimbr的部署工具写好了,拿去玩玩吧,内附源码,要装VC2008运行库

multimbr部署工具.zip

177.04 KB, 下载次数: 96, 下载积分: 无忧币 -2

点评

厉害!!不过,怎么找不着关闭按钮呢  详情 回复 发表于 2014-11-30 17:24
超级强悍。就等着你这一天呢。 大家多多测试,提出建议,不断改进,让这个工具成为我们主要的、可靠的多重 mbr 制作工具。  详情 回复 发表于 2014-11-30 17:15

评分

参与人数 3无忧币 +15 收起 理由
weijun189 + 5 赞一个!
不点 + 5 很给力!
527104427 + 5 很给力!

查看全部评分

回复

使用道具 举报

330#
 楼主| 发表于 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
回复

使用道具 举报

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

本版积分规则

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

闽公网安备 35020302032614号

GMT+8, 2024-11-29 13:07

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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