构建EDK2镜像并在QEMU启动

从今天起,我将涉足一个新的领域:UEFI。目前UEFI已经逐渐从以X86为主的服务器PC领域,渗透到以ARM为主的终端领域。得益于其灵活的扩展性以及较低的开发门槛,以后越来越多的设备将使用它作为自身启动链的一个重要组成部分。由于UEFI只是一套标准,参照该标准有许多实现,其中最有名之一就是Intel主导开发的EDK2。因此我的学习之旅也会从它开始,今天主要介绍如何构建EDK2以及在QEMU上启动它。

安装依赖

我们将以Debian12作为例子,其他Linux发行版请自行修改。

1
sudo apt install build-essential git python uuid-dev nasm acpica-tools

下载源码

1
2
3
git clone https://github.com/tianocore/edk2.git
cd edk2
git submodule update --init

构建EDK2

EDK2支持多种平台和工具链,这里我们主要介绍QEMU平台上AARCH64和X86两个架构,并且使用CLANG和GCC两种工具链进行编译。

构建EDK2工具集

EDK2源码中包含了一系列工具,用于在构建过程中进行链接打包等工作,因此我们需要先将这些工具构建出来。

1
2
3
export EDK_TOOLS_PATH=$PWD/BaseTools
source edksetup.sh
make -C BaseTools

X86架构

X86架构的QEMU固件所对应的Package是OvmfPkg/OvmfPkgX64.dsc

  1. 使用GCC工具链

    根据需要安装GCC工具链,比如我们现在需要安装X86版本的GCC,并设置prefix:

    1
    2
    sudo apt install gcc
    export GCC5_AARCH64_PREFIX=

    构建EDK2

    1
    2
    source edksetup.sh
    build -a X64 -t GCC5 -p OvmfPkg/OvmfPkgX64.dsc

    编译出的固件在Build/OvmfX64/DEBUG_GCC5

  2. 使用CLANG工具链

    由于clang原生支持交叉编译,因此可以直接安装:

    1
    sudo apt install clang

    构建EDK2

    1
    2
    source edksetup.sh
    build -a X64 -t CLANGDWARF -p OvmfPkg/OvmfPkgX64.dsc

    编译出的固件在Build/OvmfX64/DEBUG_CLANGDWARF

AARCH64架构

AARCH64架构的QEMU固件所对应的Package是ArmVirtPkg/ArmVirtQemu.dsc

  1. 使用GCC工具链

    根据需要安装GCC工具链,比如我们现在需要安装AARCH64版本的GCC,并设置prefix:

    1
    2
    sudo apt install gcc-aarch64-linux-gnu
    export GCC5_AARCH64_PREFIX=aarch64-linux-gnu-

    构建EDK2

    1
    2
    source edksetup.sh
    build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc

    编译出的固件在Build/ArmVirtQemu-AARCH64/DEBUG_GCC5

  2. 使用CLANG工具链

    由于clang原生支持交叉编译,因此可以直接安装:

    1
    sudo apt install clang

    构建EDK2

    1
    2
    source edksetup.sh
    build -a AARCH64 -t CLANGDWARF -p ArmVirtPkg/ArmVirtQemu.dsc

    编译出的固件在Build/ArmVirtQemu-AARCH64/DEBUG_CLANGDWARF

在QEMU中启动

启动所需的固件OVMF_CODE.fdOVMF_VARS.fd<固件目录>/FV中,这里以Build/OvmfX64/DEBUG_GCC5/FVBuild/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV为例。

X86架构

1
2
3
4
5
6
7
cd Build/OvmfX64/DEBUG_GCC5/FV

qemu-system-x86_64 -machine q35 -cpu qemu64 \
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on \
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd \
-net none \
-nographic

AARCH64架构

AARCH64要求pflash的大小为64M,因此我们首先需要调整固件大小到64M:

1
2
3
4
5
6
7
cd Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV

dd if=/dev/zero of=QEMU_EFI_64.fd bs=1M count=64
dd if=/dev/zero of=QEMU_VARS_64.fd bs=1M count=64

dd if=QEMU_EFI.fd of=QEMU_EFI_64.fd conv=notrunc
dd if=QEMU_VARS.fd of=QEMU_VARS_64.fd conv=notrunc
1
2
3
4
5
qemu-system-aarch64 -machine virt -cpu cortex-a57 \
-drive if=pflash,format=raw,unit=0,file=QEMU_EFI_64.fd,readonly=on \
-drive if=pflash,format=raw,unit=1,file=QEMU_VARS_64.fd \
-net none \
-nographic

参考