How to Build OVMF from Source on Fedora 23 Workstation

The below process yields the OVMF_CODE.fd and OVMF_VARS.fd files for use with QEMU/KVM guest domains running in Fedora 23.

The Process

First, clone the Git repository at the point in time meaningful to you.  For me, it was the end of the day on 2/16/2016 when my last known good firmware was built.  With the zip file in your ~/Downloads folder, here you go, from start to finish:

#Install the prerequisites:
$ sudo dnf groupinstall development-tools
$ sudo dnf install iasl libuuid-devel nasm gcc-c++ edk2-tools-python

#Unpack the files
$ cd Downloads/
$ unzip edk2
$ mv edk2-6731c20f28cf26345e58ae232f9c1fb2dad6c09e edk2

#Build the EDK2 Base Tools required to build the OVMF binaries
$ make -C BaseTools

#Build the OVMF binaries
$ vim Conf/target.txt
## In vim, change the following lines:
## ACTIVE_PLATFORM = Nt32Pkg/Nt32Pkg.dsc 
## TARGET_ARCH = IA32                         # I presume you're using X86_64 systems
## to:
## ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc 
## TOOL_CHAIN_TAG = GCC49                     # Yes, even though you're using GCC 5.*
$ export WORKSPACE=~/Downloads/edk2
$ ./
$ build

And hopefully you will now watch output scroll by until you find your fresh, hot binaries in:


To resolve my problem, I needed simply to place the OVMF_CODE.fd file into the standard location on my Fedora 23 Hypervisor OS (the host, running KVM/QEMU) as provided by Mr. Hoffman’s RPMs.  In order to prevent my new, stable firmware from being overwritten by future dnf upgrades (hopefully the firmware will return to stable usability soon!), I arranged my OVMF directory as follows:

$ ll /usr/share/edk2.git/ovmf-x64/
total 17164
-rw-r--r--. 1 root root 1966080 Mar 17 05:14 OVMF_CODE-need-smm.fd
lrwxrwxrwx. 1 root root      28 Mar 18 00:05 OVMF_CODE-pure-efi.fd -> OVMF_CODE-pure-efi.fd.stable
-rw-r--r--. 1 root root 1966080 Mar 18 00:04 OVMF_CODE-pure-efi.fd.stable
-rw-r--r--. 1 root root 1966080 Mar 17 05:08 OVMF_CODE-with-csm.fd
-rw-r--r--. 1 root root 2097152 Mar 17 05:14 OVMF-need-smm.fd
-rw-r--r--. 1 root root 2097152 Mar 17 05:04 OVMF-pure-efi.fd
-rw-r--r--. 1 root root  131072 Mar 17 05:14 OVMF_VARS-need-smm.fd
-rw-r--r--. 1 root root  131072 Mar 17 05:04 OVMF_VARS-pure-efi.fd
-rw-r--r--. 1 root root  131072 Mar 17 05:08 OVMF_VARS-with-csm.fd
-rw-r--r--. 1 root root 2097152 Mar 17 05:08 OVMF-with-csm.fd
-rw-r--r--. 1 root root 3024896 Mar 17 05:14 UefiShell.iso

You can see that I’ve renamed my good firmware with a .stable extension and I’ve placed a symlink in the location that my guest VMs expect to find the firmware.  That way, new dnf upgrade operations will overwrite the symlink with the new firmware file and my guests can make use of it immediately.  If it remains broken, I can replace it with a symlink to the stable firmware.

And my guest domain booted right up.  Joy!

Why did I do this?

After recklessly updating the heretofore stable repository for nightly OVMF builds (kindly and dutifully hosted by Gerd Hoffman of Red Hat), I found that my production workstation (on which I have implemented IOMMU-based PCI passthrough of an NVidia GeForce GTX 960, much to my delight) failed to boot.  After passing the Tianocore splash screen, I was met with a lonely, solitary cursor in the upper left of the screen and a VM with one of its four available cores maxed out at 100% utilization indefinitely.


My first thought, of course, was to compile the software from the Git repository myself, cloning the repository’s state at the end of 2/16/2016 when the build was conducted of my last known good firmware. However, after spending about an hour and a half digging through horribly outdated guidelines for compiling the EDK2 toolkit (required to build the OVMF binaries), I had failed to come up with a working procedure.  I felt that I was close, but I also had a foreboding feeling that the procedure simply wasn’t well-tuned for a GNU/Linux environment based on the GCC 5.3.2 compiler.  The instructions, after all, are primarily for Windows, and the information regarding GNU/Linux environments stops abruptly at GCC 4.9.*.  And we all know GCC 5.* does not necessarily work with software intended to be compiled by GCC 4.9.*.

So I digressed into 2 hours of researching OVMF and searching for alternative methods.  I scoured the web for any RPMs I might find that would house those invaluable binaries.

First, I found that the OpenSUSE project hosts its own OVMF RPMs, but sadly, they appear only to host the all-in-one firmware package, and my VM has already been constructed to take advantage of the separation between the OVMF_CODE-pure-efi.fd binary and the NVRAM binary file in /var/libvirt/qemu/nvram/.  This is a superior method, for it permits one to upgrade the OVMF code while retaining one’s non-volatile variables essential to the continued operation of the guest domain.

Then, I found a massively old binary (release r15214) hosted by the Tianocore project itself, but I found it to be only a single “OVMF.fd” file 1 MB in size (rather than the 2 MB for current full binaries), and while it would boot successfully into the UEFI firmware, the firmware was utterly ignorant of my guest domain’s hardware configuration, and my guest domain failed to load – that valuable NVRAM content was absent.

I considered some random guys‘ dead repositories and found nothing I could use.  The search was obvoiusly bearing no fruit.  I became even sillier, trying to splice the binary with my NVRAM contents upon reading that they form the first 128 KB of the full OVMF-pure-efi.fd binary.  Obviously, that did not work (I was going to be pretty giddy if it had).

The only answer was to compile the damn code myself.  I tried spinning up my CentOS 6 VM with GCC 4.4.*, but I ran into a seemingly insurmountable error code based on an absent stdc-headers.h file and Internet chatter about GCC vs. other C compilers in regards to such a file.  So I headed back to Fedora 23, where I had at least built the EDK2 tools successfully.

In searching the Git repository for information about GCC 5.*, I determined from a patch of the build script that the GCC49 tool chain could be used with GCC 5.*.  This was heartening.  I then discovered my major and obvious mistake, that after building the EDK2 environment, I needed to switch the build target as follows:

ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc

And I did it.  Just thirty minutes later, I was able to clone the Git repository from the known-good date and build the OVMF firmware from the cloned repository, restoring my busted VM (which is my production workstation at home) to a working condition.

What a quest.  Lots of learnin’s.  My VM is back in business, and I am well pleased.

This entry was posted in Information Technology and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s