我正在尝试使用 UEFI 在 QEMU 上启动自定义内核。这是针对我正在编写的操作系统的。当我运行此命令时,我会进入 UEFI shell。我可能错了,但我认为如果一切设置正确,QEMU 应该启动到内核而不是 UEFI shell。我尝试使用启动管理器运行内核并更改启动顺序,但没有任何成功。
我怀疑我的内核格式不对。当我在 Ubuntu 中运行文件 myKernel.img 时,我得到了以下输出:
myKernel.img: OpenPGP Secret Key
我在网上读过关于 UEFI 存根的文章,但我认为这只适用于 Linux 内核。以下是我构建 myKernel.img 的方法:
aarch64-linux-gnu-objcopy -O binary myKernel.elf myKernel.img
这是 QEMU 命令:
qemu-system-aarch64 \
-cpu cortex-a76 \
-machine virt,kernel=myKernel.img \
-display gtk,show-tabs=on -device ramfb -serial vc \
-drive if=pflash,format=raw,unit=0,file=firmware/uefi/AARCH64_OVMF_CODE.fd,readonly=on \
-drive if=pflash,format=raw,unit=1,file=firmware/uefi/AARCH64_OVMF_VARS.fd
我很感激任何建议或忠告!另外,如果这个问题不适合在这里提出,请告诉我。我最初在 Stack Overflow 上问过这个问题,但该网站不适合。
由于我确实没有足够深入的知识,所以回答非常肤浅:
当文件不是“原始机器代码块”以外的任何特定格式时,您通常会得到这样的结果,即它没有可识别的标头,并且命令
file
最终显示其最接近的猜测。(它根据几个前导字节做出大多数决定,而 ARM 机器代码可能恰好与有效的 OpenPGP 标头相符。)然后它很可能期望图像具有类似 Linux 的标头,该标头指示应在哪个基地址加载图像、入口点在哪里等。您的
-O binary
输出没有任何此类信息。(从概念上讲,它与您当前正在删除的 ELF 标头类似,但高度特定于 Linux 且依赖于平台;例如,x86 上的 Linux 将使用比 AArch64 上更复杂的握手。)
虽然当它与 UEFI 结合使用时,我几乎希望此选项需要 EFI 格式的映像文件而不是 Linux 内核文件。
只有存根部分(即将引导加载程序直接粘贴到内核映像上的概念)是 Linux 特有的,但它解决的整体问题是 UEFI 特有的。
UEFI 无法直接接受原始的“在 X 处加载并跳转到 Y”映像(例如您
objcopy -O binary
生成的映像),因为它不知道在哪里加载它以及入口点在哪里。相反,它期望提供一个.efi
包含此信息的 PE/COFF 格式的文件(即另一个名称的 .exe 文件)。传统上,这应该是一个专用的引导加载程序(例如 grubx64.efi 或 elilo.efi),然后它知道如何启动 Linux 内核,并且这同样适用于通过 UEFI 启动的任何操作系统 - 例如 Windows 通过 winload.efi 启动 - 并且唯一特定于 Linux 的部分是将这两个功能组合成一个双面的“vmlinuz 但具有 PE/COFF 组成” .efi 文件。
因此,要么将您的构建输出本身包装到 PE/COFF 标头中,以便它成为 UEFI 运行的有效 .efi 文件(可能使用elf2efi),要么您需要使用中介(例如 GRUB 或 U-Boot)(即它本身已经是一个有效的 .efi 程序)来加载它。