Using UEFI in QEMU/KVM (AArch64 + AArch32)

本文介绍如何在QEMU/KVM平台上使用Tianocore/EDK2构建并运行UEFI固件,支持AArch64及AArch32模式。内容涵盖固件构建、直接从UEFI启动Linux、使用持久化UEFI变量以及启用UEFI安全启动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【转自】https://wiki.linaro.org/LEG/UEFIforQEMU


Using UEFI in QEMU/KVM (AArch64 + AArch32)

This page provides instructions for building and running the port of Tianocore/EDK2 to a QEMU/KVM based 'virt' platform in both ARM and AArch64 mode.

Features

  • Supports the QEMU/arm 'mach-virt' machine type both in AArch64 and AArch32 execution modes
  • Peripherals are discovered dynamically using a flattened device tree image passed by QEMU at the base of RAM (0x4000_0000). This includes the serial UART, RTC, interrupt controller etc
  • Supports reset and poweroff through PSCI
  • Supports virtio block, network and SCSI devices
  • Supports non-volatile variable storage through emulated NOR flash
  • Supports reset, poweroff and RTC access through UEFI Runtime Services
  • Supports UEFI Secure Boot

Prerequisites

To run this UEFI firmware, you will need QEMU version 2.2 or later built for aarch64-softmmu (or arm-softmmu).

To run it in accelerated mode, i.e., under an arm64 or ARM Linux kernel with KVM, you will need a fairly recent host kernel (v3.19 or later).

Note that if your [emulated] hardware has a GICv3, it is essential that your host device tree correctly identifies the GIC as a v3, or KVM will kick it into a mode that is incompatible with the GICv3 handling in UEFI running inside the guest.

Building the firmware

Source can be found on the Tianocore EDK2 GitHub

Prebuilt binaries can be found here.

Before building from the cloned repository the first time, it is necessary to do a

make -C BaseTools

Prepare the environment:

source edksetup.sh
export GCC49_AARCH64_PREFIX=aarch64-linux-gnu-
export GCC49_ARM_PREFIX=arm-linux-gnueabihf-

Then, the code can be built using

build -a <architecture> -t GCC49 -p ArmVirtPkg/ArmVirtQemu.dsc

where <architecture> is either ARM or AARCH64

After the build completes successfully, the firmware image can be found in the file

Build/ArmVirtQemu-<arch>/DEBUG_GCC49/FV/QEMU_EFI.fd

Running the firmware

To run the firmware in non-accelerated mode (e.g., on a x86 box), invoke QEMU in the following way:

qemu-system-aarch64 \
    -m 1024 \
    -cpu cortex-a57 \
    -M virt \
    -bios Build/ArmVirtQemu-<arch>/DEBUG_GCC49/FV/QEMU_EFI.fd \
    -serial stdio

(replace cortex-a57 with cortex-a15 for 32-bit ARM)

This should result in the UEFI shell being launched, unless you hit any key to enter the menu.

Booting Linux

It is possible to boot directly into Linux from UEFI, without an intermediate bootloader. For instance, using this image, which contains a separate FAT /boot partition containing the kernel, we can boot Linux by following these steps:

  • decompress the image:
    •   zcat vexpress64-openembedded_minimal-armv8-gcc-4.9_20140823-686.img.gz > vexpress64-oe.img
  • invoke qemu as above, but add the following command line arguments:

    •   -drive if=none,file=vexpress64-oe.img,id=hd0 
        -device virtio-blk-device,drive=hd0

The disk image is preconfigured to boot a file called 'Image' from the first partition of the first virtio block device (by means of a startup.nsh UEFI shell script), so it should boot the kernel after the countdown expires. To boot manually, enter the shell while hitting Escape (to prevent startup.nsh from being executed) and enter the following command:

Image root=/dev/vda2 console=ttyAMA0,38400n8 earlycon=pl011,0x9000000

Using persistent UEFI variables

It is possible to make UEFI remember the environment variables that are set by the boot configuration menus or by efibootmgr under Linux. To do so, we need to pass two NOR images instead of one, which requires the use of -pflash rather than -bios. However, -pflashrequires the NOR images to be exactly 64 MB in size, so we need to prepare those images first.

  • Create flash0.img containing the UEFI image:

    •   cat QEMU_EFI.fd /dev/zero | dd iflag=fullblock bs=1M count=64 of=flash0.img
  • Create a blank flash1.img:

    •   dd if=/dev/zero of=flash1.img bs=1M count=64
  • Invoke QEMU as above, but replace -bios .../QEMU_EFI.fd with:

    •   -pflash flash0.img -pflash flash1.img

Now, any changes made in the BDS boot menu will persist and be stored in flash1.img

Running under KVM

When running the above on a KVM-enabled AArch64 or ARM system using a KVM-enabled QEMU, replace -cpu cortex-aXX with:

  • -cpu host -enable-kvm

UEFI Secure Boot

This firmware can be built with support for UEFI Secure Boot.

First, follow the instructions in CryptoPkg/Library/OpensslLib/Patch-HOWTO.txt regarding how to download and prepare the OpenSSL sources, since these are not included in the Tianocore tree.

Then, build the firmware image as outlined above, while adding the SECURE_BOOT_ENABLE option:

build -a <arch> -t GCC49 -p ArmVirtPkg/ArmVirtQemu.dsc \
    -D SECURE_BOOT_ENABLE

The resulting firmware can be invoked as described in the preceding sections. Using persistent UEFI variables is recommended, since enrolled certificates are stored as variables internally.

How to configure UEFI Secure Boot and sign boot images is beyond the scope of this guide, but works the same way as it does on other virtual platforms like OVMF.

<think>好的,我需要帮助用户了解如何正确使用qemu-aarch64命令。用户之前已经询问过关于qemu-arm的使用,现在转向qemu-aarch64,可能是在尝试运行64位ARM系统。首先,我需要区分qemu-system-aarch64qemu-aarch64的不同。 根据用户提供的引用[1],用户可能看到了在Windows上创建aarch64虚拟机的示例,但用户现在可能更关注的是在Linux环境下使用qemu-aarch64运行用户模式程序或全系统模拟。需要明确qemu-aarch64通常指的是用户模式模拟,而qemu-system-aarch64是系统模式模拟,两者的用途不同。 用户之前的问题中,我详细讲解了qemu-arm的使用,包括运行静态和动态程序、调试等。现在需要将类似的内容迁移到aarch64架构,同时考虑64位特有的参数和配置。比如,动态链接库路径可能不同,CPU型号也需要对应,如cortex-a72、cortex-a53等。 需要检查用户是否可能混淆了用户模式和系统模式。在回答中应该明确区分这两种模式的使用场景。用户提供的引用中提到的命令是系统模式,但用户的问题可能更倾向于用户模式,所以需要确认用户的实际需求。 接下来,我需要构建一个结构清晰的指南,包括核心命令结构、安装验证、典型场景示例、常见问题等。同时,要确保使用正确的参数,比如-L路径在aarch64下可能不同,例如/usr/aarch64-linux-gnu。还需要提供编译示例,使用aarch64-linux-gnu-gcc编译器。 另外,用户可能遇到动态链接库的问题,需要指导如何正确设置库路径或安装对应的交叉编译库。在调试部分,可能需要使用gdb-multiarch连接到qemu的调试端口,这与之前qemu-arm的步骤类似,但需确认端口和架构是否正确。 在系统模式部分,用户引用中的参数可以作为示例,但需要解释每个参数的作用,如-M指定机器类型,-bios指定固件,-device添加外设等。同时,要提醒用户需要准备合适的EFI固件和镜像文件,比如UEFI.fd和安装ISO。 还要考虑用户的环境,是否已经安装了必要的包,比如qemu-system-arm、交叉编译工具链等。对于不同发行版,安装命令可能不同,需要给出示例,如Ubuntu下的安装步骤。 最后,生成相关问题,帮助用户进一步探索,比如如何配置网络、性能优化、与用户模式的区别等。确保引用正确,比如用户提供的引用[1]是关于系统模式的,可能在相关问题中提及。 需要检查所有命令的正确性,避免拼写错误,并确保参数适用于aarch64架构。同时,保持回答结构清晰,步骤详细,便于用户逐步操作验证。</think>### QEMU-aarch64 使用详解(用户模式 + 系统模式) --- #### 一、核心模式区分 1. **用户模式**:`qemu-aarch64`(直接运行ARM64程序) ```bash # 运行ARM64程序(类似qemu-arm的64位版本) qemu-aarch64 -L /usr/aarch64-linux-gnu ./hello_aarch64 ``` 2. **全系统模式**:`qemu-system-aarch64`(完整虚拟机) ```bash # 启动ARM64虚拟机(需搭配UEFI固件) qemu-system-aarch64 -M virt -cpu cortex-a72 -m 4G -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -hda ubuntu-arm64.img ``` --- #### 二、用户模式实战(运行单程序) **步骤1:环境准备** ```bash # Ubuntu/Debian安装依赖 sudo apt install qemu-user-static gcc-aarch64-linux-gnu # 验证工具链 aarch64-linux-gnu-gcc --version # 应显示aarch64编译器信息[^2] ``` **步骤2:编译与运行** ```c // hello.c #include <stdio.h> int main() { printf("ARM64程序运行成功\n"); return 0; } ``` ```bash # 编译ARM64程序 aarch64-linux-gnu-gcc -static hello.c -o hello_static aarch64-linux-gnu-gcc hello.c -o hello_dynamic # 运行动态链接程序(需指定库路径) qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./hello_dynamic # 输出"ARM64程序运行成功"即验证通过[^3] ``` **调试技巧**: ```bash # 启动GDB调试 qemu-aarch64 -g 1234 ./hello_dynamic & gdb-multiarch ./hello_dynamic (gdb) target remote :1234 (gdb) b main ``` --- #### 三、全系统模式配置(完整虚拟机) **核心参数说明**: ```bash qemu-system-aarch64 \ -M virt \ # 使用QEMU虚拟化平台 -cpu cortex-a72 \ # 指定CPU型号 -smp 4 \ # 4个CPU核心 -m 8G \ # 内存大小 -bios QEMU_EFI.fd \ # UEFI固件(需提前准备) -drive file=ubuntu-arm64.img,format=raw \ # 系统磁盘 -device virtio-gpu-pci \ # GPU加速 -netdev user,id=net0 -device virtio-net-pci,netdev=net0 # 网络配置 ``` **典型启动流程**: 1. 下载UEFI固件: ```bash wget https://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/QEMU_EFI.fd ``` 2. 创建虚拟磁盘: ```bash qemu-img create -f qcow2 ubuntu-arm64.img 20G ``` 3. 启动安装镜像: ```bash qemu-system-aarch64 -M virt -cpu cortex-a72 -m 4G \ -bios QEMU_EFI.fd -cdrom ubuntu-22.04-live-server-arm64.iso \ -drive file=ubuntu-arm64.img,format=qcow2 \ -device virtio-net-device,netdev=net0 -netdev user,id=net0 ``` --- #### 四、常见问题解决 | 问题场景 | 解决方案 | |---------|----------| | **UEFI固件缺失** | 安装`qemu-efi-aarch64`包或手动下载`QEMU_EFI.fd` | | **启动卡在UEFI Shell** | 在Shell中执行`FS0:\EFI\BOOT\BOOTAA64.EFI`[^1] | | **动态链接库错误** | 使用`-L`指定路径或安装`libc6-arm64-cross` | | **网络不可用** | 添加`-nic user,model=virtio-net-pci`参数 | | **图形界面黑屏** | 改用`-nographic`或添加`-device virtio-gpu-pci` | --- #### 五、性能优化建议 1. **启用KVM加速**(需宿主CPU支持): ```bash qemu-system-aarch64 -enable-kvm -machine virt,gic-version=3 ... ``` 2. **使用virtio设备**: ```bash -drive file=disk.img,if=virtio -netdev user,id=net0,model=virtio ``` 3. **分配大页内存**: ```bash -mem-prealloc -mem-path /dev/hugepages ``` --- ### 验证成功标志 1. 用户模式程序正确输出预期结果 2. 全系统模式下完成操作系统安装 3. 虚拟机内执行`uname -m`显示`aarch64` 4. GDB可正常调试ARM64汇编指令 --- ### 高级应用示例 **运行Android ARM64镜像**: ```bash qemu-system-aarch64 -M virt -cpu cortex-a72 -m 6G \ -bios QEMU_EFI.fd -device virtio-gpu-pci \ -drive file=android-arm64.img,format=raw \ -nic user,hostfwd=tcp::5555-:5555 # 启用ADB端口转发 ``` **交叉编译内核测试**: ```bash # 编译ARM64内核 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j8 # 使用QEMU启动测试 qemu-system-aarch64 -M virt -cpu cortex-a72 -m 2G \ -kernel arch/arm64/boot/Image -append "root=/dev/vda console=ttyAMA0" ``` --- ### 相关问题 1. 如何通过QEMU实现ARM64与x86主机之间的文件共享? 2. 用户模式与系统模式在资源占用上有何本质区别? 3. 如何配置TPM安全芯片支持运行Windows ARM64? 4. QEMU中如何调试ARM64内核的启动过程? : UEFI固件路径可能因发行版不同而变化 [^2]: 交叉编译工具链需与目标系统glibc版本匹配 [^3]: `qemu-aarch64-static`更适合容器环境嵌入使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值