我正在尝试编写一个脚本来解压并重新打包 FreeBSD ISO,以便我可以使用它进行安装。目标是无人值守安装。
我已经编写了以下脚本,但它不起作用。虽然原始 ISO 将在 UEFI 模式下在 VirtualBox 中启动,但新创建的 ISO 则不会。
#!/bin/sh
inst_cfg="$1"
src_iso="$2"
dst_iso="$3"
iso_mnt=$(mktemp -d /tmp/freebsd-mnt-XXXXXX)
iso_wrk=$(mktemp -d /tmp/freebsd-wrk-XXXXXX)
vol_id=$(isoinfo -d -i "${src_iso}" | sed -n -e 's/^Volume id: \(.*\)$/\1/p')
md_name=$(mdconfig -a -t vnode -f "${src_iso}")
mount -t cd9660 "/dev/${md_name}" "${iso_mnt}"
cp -a -v "${iso_mnt}/" "${iso_wrk}"
cp "${inst_cfg}" "${iso_wrk}/etc/installerconfig"
mkisofs -J -R -no-emul-boot -V "${vol_id}" -b boot/cdboot -o "${dst_iso}" "${iso_wrk}"
umount "${iso_mnt}" # cd9660
mdconfig -d -u "${md_name}"
rm -rf "${iso_mnt}"
rm -rf "${iso_wrk}"
创建的文件系统看起来不错。我已经比较了原始 ISO 和自定义 ISO 的文件,唯一的区别是installerconfig
添加的文件和boot.catalog
(我理解mkisofs
添加了,但为什么?这可能是问题所在吗?)
我尝试过各种选项组合mkisofs
,包括-R -U
、-L -D -R
、-J -R
,但没有任何区别。
此外,FreeBSD 手册有趣的是有以下评论:
因此,如果 /tmp/myboot 拥有一个可启动的 FreeBSD 系统,其启动映像位于 /tmp/myboot/boot/cdboot 中,则此命令将生成 /tmp/bootable.iso:
mkisofs -R -no-emul-boot -b boot/cdboot -o /tmp/bootable.iso /tmp/myboot
这确实不是生成一个在 UEFI 模式下 VirtualBox 下启动的 ISO。
有人知道出了什么问题吗?
答案1
问题不在于文件系统内容,而在于引导记录和分区:
$ xorriso -indev FreeBSD-12.0-RELEASE-amd64-bootonly.iso -report_el_torito plain -report_system_area plain
...
libisofs: WARNING : Found hidden El-Torito image. Its size could not be figured out, so image modify or boot image patching may lead to bad results.
libisofs: NOTE : Found hidden El-Torito image for EFI.
libisofs: NOTE : EFI image start and size: 20 * 2048 , 1600 * 512
...
Boot record : El Torito , MBR protective-msdos-label cyl-align-off GPT
...
El Torito catalog : 19 1
El Torito images : N Pltf B Emul Ld_seg Hdpt Ldsiz LBA
El Torito boot img : 1 BIOS y none 0x0000 0x00 4 420
El Torito boot img : 2 UEFI y none 0x0000 0x00 1600 20
El Torito img blks : 1 1204
El Torito img blks : 2 400
System area options: 0x00000201
System area summary: MBR protective-msdos-label cyl-align-off GPT
ISO image size/512 : 675508
Partition offset : 0
MBR heads per cyl : 0
MBR secs per head : 0
MBR partition table: N Status Type Start Blocks
MBR partition : 1 0x00 0xee 1 676107
GPT : N Info
GPT backup problems: Not a GPT 1.0 header of 92 bytes for 128 bytes per entry
GPT disk GUID : 7ce0bf52def9e8118c360cc47ad8b808
GPT entry array : 2 2 separated
GPT lba range : 3 676105 676107
GPT partition name : 1
GPT partition GUID : 1 6de0bf52def9e8118c360cc47ad8b808
GPT type GUID : 1 28732ac11ff8d211ba4b00a0c93ec93b
GPT partition flags: 1 0x0000000000000000
GPT start and size : 1 80 1600
GPT partition name : 2
GPT partition GUID : 2 73e0bf52def9e8118c360cc47ad8b808
GPT type GUID : 2 9d6bbd83417fdc11be0b001560b84f0f
GPT partition flags: 2 0x0000000000000000
GPT start and size : 2 3 29
BIOS 启动映像和 EFI 系统分区都不是 ISO 中的文件,而是未命名的块区域。
如果您不采用通过固定增长或通过附加会话的方式
cp FreeBSD-12.0-RELEASE-amd64-bootonly.iso new.iso
xorriso -boot_image any keep \
-dev new.iso \
-map /path/to/your_installerconfig /etc/installerconfig
[other -map commands for files or directory trees ...]
那么你需要提取这些区域
dd if=FreeBSD-12.0-RELEASE-amd64-bootonly.iso bs=512 skip=80 count=1600 \
of=efi_part.img
dd if=FreeBSD-12.0-RELEASE-amd64-bootonly.iso bs=512 skip=1680 count=4816 \
of=bios_boot.img
(El Torito 以 2048 块为单位提供 LBA,但大小以 512 块为单位。4 * 420 = 1680。1204 个 2048 字节块的 BIOS 映像大小是由高于 420 的最低文件系统对象 LBA 估计的。可能它更小,但任何过大应该不会造成伤害。)
然后是从 U 盘启动 BIOS 的 MBR 代码:
dd if=FreeBSD-12.0-RELEASE-amd64-bootonly.iso bs=1 count=446 \
of=mbr_code.img
如果您不打算通过BIOS启动,则不需要bios_boot.img和mbr_code.img。
从解压和主计算的树 $HOME/files_for_iso 和提取的图像文件构建新的 ISO
xorriso -as mkisofs \
-o new.iso \
-d -l -r \
-V "12_0_RELEASE_AMD64_BO" \
-G mbr_code.img \
-b /bios_boot.img \
-no-emul-boot -boot-load-size 4 \
-eltorito-alt-boot \
-append_partition 2 0xef efi_part.img \
-e '--interval:appended_partition_2:all::' \
-no-emul-boot \
bios_boot.img $HOME/files_for_iso
这不会产生 GPT,而是产生一个 MBR 分区表,其中包含两个类型为 0x83(用于 ISO 文件系统)的分区和 0xef(用于 EFI 系统分区)的分区。
(是否必须测试 BIOS 从 USB 记忆棒启动。许多 MBR 需要修补信息才能找到下一阶段的启动程序。)
答案2
通过在标准映像之上创建另一个 cd9660 会话来添加额外文件要容易得多,而不是解压并打包 iso:
cp FreeBSD-12.0-RELEASE-amd64-bootonly.iso new.iso
volid=$(isoinfo -d -i new.iso | awk '/Volume id/{print$3}')
growisofs -M new.iso -d -l -r -V "$volid" -graft-points \
/etc/installerconfig=/path/to/your_installerconfig \
[other files ...]
这应该“继承”前一个会话的引导映像,并且具有相同路径的新文件将覆盖光盘上已有的文件(但前提是它们较新,当使用标准mkisofs
/时genisoimage
)。
请注意,除非新会话的卷 ID 设置为与旧会话相同(如上所述),否则 FreeBSD 安装程序不会自动挂载 cd,但会提示输入带有mountroot>
.
我已经使用 qemu 测试了上面的内容OVMFUEFI 固件来自这里,使用以下命令行:
qemu-system-x86_64 -enable-kvm -m 2G -serial none \
-bios ovmf-x64/OVMF-pure-efi.fd -cdrom new.iso
如果您确实需要从头开始创建 UEFI 可启动 CD,那么您可以在 FreeBSD's 中找到更多信息维基百科(在“UEFI 下的 CD/DVD 启动”下)和这里。
FreeBSD 损坏的增长文件
由于一个错误,growisofs
当与常规文件而不是设备一起使用时,在 FreeBSD 上会崩溃;为了避免这种情况,您应该将此 diff 应用于growisofs.c
(应用 with patch -l
):
--- growisofs.c~ 2018-12-14 07:32:38.814189935 +0200
+++ growisofs.c 2018-12-14 07:32:43.602431986 +0200
@@ -3471,7 +3471,8 @@
CLOSEONEXEC(in_fd);
CLOSEONEXEC(out_fd);
#if !(defined(__APPLE__) && defined(__MACH__))
- CLOSEONEXEC(ioctl_fd);
+ if(ioctl_handle != INVALID_HANDLE)
+ CLOSEONEXEC(ioctl_fd);
#endif
#undef CLOSEONEXEC
答案3
许多有关创建可启动 ISO 的文档的问题在于,它们往往默认采用非 UEFI 启动。
以下是一个很好的参考资料,其中包含有关从 CD/DVD 介质进行 UEFI 启动的信息:https://dev.lovelyhq.com/libburnia/libisofs/raw/master/doc/boot_sectors.txt
因此,如果您想在 UEFI 中使用单独的 El Torito 启动映像(就像您以前对 BIOS 所做的那样),您需要确保启动映像嵌入了正确的平台IDUEFI 的字节。对于 x86 BIOS,平台 ID 为 0。PowerPC 使用 1;值 2 指定用于 Mac; UEFI 指定值为 0xef,即十进制的 239。
所以在我看来你必须有一些指定平台 ID 值的方法:直接或使用某些选项来指定启动映像应该是UEFI启动图像。我想此 Fedora 文档由 mosvy 链接通过使用选项-e
来指定位置efiboot.img
而不是使用-b
传统 BIOS 启动映像来实现此目的。
因此,请验证您的信息boot/cdboot
是否有效UEFI启动映像,并尝试-e boot/cdboot
在mkisofs
命令行中使用而不是-b boot/cdboot
.
以下是 UEFI 启动映像内容的描述:
我手头恰好有 RHEL 8.0 beta 1 ISO 映像,并且我刚刚确认它实际上可以在 UEFI 模式下使用 VirtualBox 启动。它使用的 UEFI 启动映像在映像的主 iso9660 文件系统中可用images/efiboot.img
,并且它显然只包含一个 FAT 文件系统映像,没有任何类型的分区表。
在 的文件系统中efiboot.img
,只有一个\EFI\BOOT
包含相应 UEFI 引导加载程序的目录:在本例中, 和BOOTX64.EFI
,BOOTIA32.EFI
它们似乎都是安全启动垫片,分别对应的 GRUB 版本为 和grubx64.efi
,grubia32.efi
以及它们所需的任何辅助文件: GRUB配置文件、GRUB 字体文件和安全启动垫片的 MOKManager。