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.