如何使用 mkisofs 创建将在 UEFI 下的 VirtualBox 中启动的 FreeBSD ISO?

如何使用 mkisofs 创建将在 UEFI 下的 VirtualBox 中启动的 FreeBSD ISO?

我正在尝试编写一个脚本来解压并重新打包 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/cdbootmkisofs命令行中使用而不是-b boot/cdboot.

以下是 UEFI 启动映像内容的描述:

我手头恰好有 RHEL 8.0 beta 1 ISO 映像,并且我刚刚确认它实际上可以在 UEFI 模式下使用 VirtualBox 启动。它使用的 UEFI 启动映像在映像的主 iso9660 文件系统中可用images/efiboot.img,并且它显然只包含一个 FAT 文件系统映像,没有任何类型的分区表。

在 的文件系统中efiboot.img,只有一个\EFI\BOOT包含相应 UEFI 引导加载程序的目录:在本例中, 和BOOTX64.EFIBOOTIA32.EFI它们似乎都是安全启动垫片,分别对应的 GRUB 版本为 和grubx64.efigrubia32.efi以及它们所需的任何辅助文件: GRUB配置文件、GRUB 字体文件和安全启动垫片的 MOKManager。

相关内容