186 lines
7.0 KiB
Plaintext
186 lines
7.0 KiB
Plaintext
|
Running the OVMF image in qemu
|
||
|
==============================
|
||
|
|
||
|
The easiest way to run the OVMF image is to specify a pflash device for the
|
||
|
firmware file. Here is the example to use OVMF in the flash mode:
|
||
|
|
||
|
$ cp /usr/share/qemu/ovmf-x86_64.bin .
|
||
|
$ qemu-system-x86_64 -pflash ovmf-x86_64.bin
|
||
|
|
||
|
Please make sure the file is writable before using the flash mode, or all
|
||
|
your changes won't be saved.
|
||
|
|
||
|
Starting from r15670, two extra firmware files are provided for the flash mode:
|
||
|
ovmf-*-code.bin and ovmf-*-vars.bin, and all non-volatile variables will be
|
||
|
stored in ovmf-*-vars.bin. Example:
|
||
|
|
||
|
$ cp /usr/share/qemu/ovmf-x86_64-vars.bin .
|
||
|
$ qemu-system-x86_64 \
|
||
|
-drive if=pflash,format=raw,unit=0,readonly,file=/usr/share/qemu/ovmf-x86_64-code.bin \
|
||
|
-drive if=pflash,format=raw,unit=1,file=ovmf-x86_64-vars.bin
|
||
|
|
||
|
It would be easier to manage the NV variables with the separated vars firmware.
|
||
|
|
||
|
NOTE: Running OVMF with '-bios' is deprecated and should not be used anymore.
|
||
|
|
||
|
Variable Stores with preloaded keys
|
||
|
-----------------------------------
|
||
|
|
||
|
Besides the generic OVMF images, there are images preloaded with different
|
||
|
vendor keys.
|
||
|
|
||
|
ovmf-x86_64-smm-ms-vars.bin
|
||
|
- PK: SUSE Linux Enterprise Secure Boot CA
|
||
|
- KEK: Microsoft Corporation KEK CA 2011, SUSE Linux Enterprise Secure Boot CA
|
||
|
- db: Microsoft Corporation UEFI CA 2011, Microsoft Windows Production PCA 2011
|
||
|
|
||
|
ovmf-x86_64-smm-opensuse-vars.bin
|
||
|
- PK: openSUSE Secure Boot CA
|
||
|
- KEK: openSUSE Secure Boot CA
|
||
|
- db: openSUSE Secure Boot CA
|
||
|
|
||
|
ovmf-x86_64-smm-suse-vars.bin
|
||
|
- PK: SUSE Linux Enterprise Secure Boot CA
|
||
|
- KEK: SUSE Linux Enterprise Secure Boot CA
|
||
|
- db: SUSE Linux Enterprise Secure Boot CA
|
||
|
|
||
|
Note that the preloaded key images are all 64 bit because openSUSE/SLE and
|
||
|
Windows only support Secure Boot in 64 bit mode.
|
||
|
|
||
|
Those variable stores are created with EnrollDefaultKeys.efi which enrolls
|
||
|
the Microsoft keys into KEK and db. It also reads the key from SMBIOS Type 11
|
||
|
and enrolls the key into PK and KEK. If the "--no-default" switch is provided,
|
||
|
the program will ignore the Microsoft keys and enroll the key from SMBIOS into
|
||
|
db instead.
|
||
|
|
||
|
x86_64 4MB images
|
||
|
-----------------
|
||
|
|
||
|
The OVMF upstream decides to switch the default flash size to 4MB since
|
||
|
the edk2 commit 1c47fcd465a496. It's mainly for Windows HCK which requests
|
||
|
a larger variable store. To maintain the backward compatibility, the 4MB
|
||
|
images are built separately. Only those images with 4m, e.g. ovmf-x86_64-4m.bin,
|
||
|
are the 4MB images. Otherwise, it's built with FD_SIZE_2MB, i.e. a 2MB image.
|
||
|
|
||
|
x86_64 SMM Support
|
||
|
------------------
|
||
|
The image files with "-smm", e.g. ovmf-x86_64-smm.bin, are the images
|
||
|
with SMM support. SMM provides better (virtual) hardware separation between
|
||
|
the guest OS and the firmware to prevent the runtime guest OS from tampering
|
||
|
with the variable store and S3 areas, so it's recommended to enable SMM along
|
||
|
with Secure Boot. Here are the requirements to use the SMM images:
|
||
|
|
||
|
* SMM support requires QEMU 2.5.
|
||
|
* The minimum required QEMU machine type is "pc-q35-2.5".
|
||
|
* SMM with KVM requires Linux 4.4 (host).
|
||
|
|
||
|
Here are the qemu commands to start a VM with SMM support:
|
||
|
|
||
|
$ cp /usr/share/qemu/ovmf-x86_64-smm-vars.bin .
|
||
|
$ qemu-system-x86_64 \
|
||
|
-machine q35,smm=on,accel=(tcg|kvm) \
|
||
|
-global driver=cfi.pflash01,property=secure,value=on \
|
||
|
-drive if=pflash,format=raw,unit=0,readonly,file=/usr/share/qemu/ovmf-x86_64-smm-code.bin \
|
||
|
-drive if=pflash,format=raw,unit=1,file=ovmf-x86_64-smm-vars.bin \
|
||
|
-global ICH9-LPC.disable_s3=1 \
|
||
|
...
|
||
|
|
||
|
NOTE: The pflash variable store is required to use OVMF with SMM.
|
||
|
|
||
|
Creating Platform and Key Exchange keys
|
||
|
=======================================
|
||
|
|
||
|
A note about terminology. In UEFI terms, "key" means certificate (not the
|
||
|
openssl key). UEFI keys are required to be based on RSA 2048 bit keys.
|
||
|
|
||
|
The Platform key and Key Exchange Keys should be the equivalent of CA root
|
||
|
certificates (i.e. a self signed certificate). Note that in current tianocore
|
||
|
OVMF, the input certificates, if taken from external media, *must* be in a
|
||
|
file with a .cer extension and in DER format.
|
||
|
|
||
|
The platform key is the key which controls updates to the Key Exchange Key
|
||
|
database. The Key Exchange Key controls updates to the signature databases.
|
||
|
Note that if the Key Exchange Key is an X509 key, any key which has the KEK as
|
||
|
its root signature can also be used to validate an efi binary without need for
|
||
|
any entries in the signatures database.
|
||
|
|
||
|
|
||
|
Create Platform Key (PK)
|
||
|
------------------------
|
||
|
|
||
|
openssl req -new -x509 -newkey rsa:2048 -keyout PK.key -out PK.crt -days <length>
|
||
|
|
||
|
Note that the Key is PK.crt (PK.key is the private key you use to sign other
|
||
|
certificates)
|
||
|
|
||
|
Now convert to DER format
|
||
|
|
||
|
openssl x509 -in PK.crt -out PK.cer -outform DER
|
||
|
|
||
|
The file PK.cer can be placed on a USB key for enrolling as the platform key.
|
||
|
|
||
|
Create Key Exchange Key (KEK)
|
||
|
-----------------------------
|
||
|
|
||
|
This is done exactly as the Platform key above, except call the file KEK.cer
|
||
|
instead.
|
||
|
|
||
|
Note, for expermentation purposes, there's no reason the KEK and the PK can't
|
||
|
be the same certificate.
|
||
|
|
||
|
Creating derived keys from the KEK
|
||
|
----------------------------------
|
||
|
|
||
|
This process can be used to create subordinate keys which can be used to sign
|
||
|
efi binaries (since their roots can be traced back to the KEK).
|
||
|
|
||
|
openssl req -new -newkey rsa:2048 -keyout new.key -out new.csr -days <length>
|
||
|
|
||
|
Now sign the certificate request with the KEK:
|
||
|
|
||
|
openssl x509 -req -in new.csr -CA KEK.crt -CAkey KEK.key -set_serial 1 -out new.crt
|
||
|
|
||
|
Note that since the new key doesn't have to be enrolled in the platform
|
||
|
because its root of trust can be traced back to the KEK, there's no need to
|
||
|
create a DER form of the key (the sbsign utilites used to sign efi binaries
|
||
|
take the key.crt file which is in PEM form).
|
||
|
|
||
|
Running the UEFI ARM image in qemu
|
||
|
==================================
|
||
|
There are two flavors of the UEFI ARM images: AArch32 and AArch64.
|
||
|
For the AArch64 image, use the following command:
|
||
|
|
||
|
qemu-system-aarch64 -m 1024 -M virt -cpu cortex-a57 -bios /usr/share/qemu/qemu-uefi-aarch64.bin -serial stdio
|
||
|
|
||
|
For AArch32:
|
||
|
qemu-system-arm -m 1024 -M virt -cpu cortex-a15 -bios /usr/share/qemu/qemu-uefi-aarch32.bin -serial stdio
|
||
|
|
||
|
Source Level Debugging
|
||
|
======================
|
||
|
It's possible to debug OVMF with gdb connecting to qemu with the following
|
||
|
steps:
|
||
|
|
||
|
(1) install the debug package: qemu-ovmf-x86_64-debug
|
||
|
|
||
|
(2) Start the virtual machine with '-s' or "-gdb tcp::1234"
|
||
|
|
||
|
(3) Start gdb in another terminal and issue the following commands:
|
||
|
|
||
|
(gdb) set architecture i386:x86-64:intel
|
||
|
(gdb) target remote localhost:1234
|
||
|
(gdb) source /usr/share/ovmf-x86_64/gdb_uefi-ovmf-x86_64-<flavor>.py
|
||
|
(gdb) reload-uefi -o /usr/lib/debug/ovmf-x86_64/DebugPkg/GdbSyms/GdbSyms/DEBUG/GdbSyms.dll
|
||
|
|
||
|
(4) Happy debugging
|
||
|
|
||
|
Reference: https://www.mail-archive.com/edk2-devel@lists.sourceforge.net/msg07075.html
|
||
|
|
||
|
Note: It's also possible to debug OVMF with Xen, but the way to set up the port
|
||
|
is differnt. Instead of adding the port number to qemu, you need gdbsx.
|
||
|
Before starting gdb, execute this command:
|
||
|
|
||
|
# gdbsx -a <domainid> 64 1234
|
||
|
|
||
|
Then gdbsx will listen to port 1234 for the specific domainU. The rest is
|
||
|
the same as qemu.
|