Periodically, I've written articles describing how to setup the EDK on a system and configure it to build a basic "Hello, World"-type program.  Previous examples:
This is not an academic exercise:  there are often significant changes build-to-build of the EDK, including build tools coming and going, source directories coming and going, source reorganization, etc.  Therefore it is helpful to offer a refresher article every once in a while.  Moreover, the effort required to download the required software components, configure them properly, and actually build a UEFI component is, most certainly, non-trivial, as you will see.

This article, then, is the latest in the series of "'Hello World' Quick-Start" articles, and describes setup, configuration, and building of a simple program using the latest (at time of this writing) EDK2 Stable Tag.  As I mentioned in a recent article, Navigating EDK Releases, Tianocore.org has moved away from the "UDK" convention to a more frequent release cadence of stable tags.  Therefore, this article will describe getting up and running with edk2-stable201908 on Microsoft Windows 10.

Introduction

A brief note of introduction:  there is a wiki page on Tianocore that describes how to setup your system.  I find it confusing and unnecessarily intimidating, hence the impetus for this article.  The information you need is scattered across many different Tianocore wiki pages, there is a lot of unnecessary information, and it does not follow a linear flow for getting your system ready to build.  However, for your reference, here is the official setup and install guide for Windows:
https://github.com/tianocore/tianocore.github.io/wiki/Windows-systems

Phase 1: Get Required Components

In previous articles, I recommended downloading a .zip file of the source from Github.  That's still possible, but I think it makes more sense to use git the way it's meant to be used.  Here's how to do it:

git clone the source

Download the source code to your system by cloning https://github.com/tianocore/edk2.git.

Be sure the "Recursive" box is checked, otherwise you'll miss getting necessary sub-modules.  That includes, at a minimum, OpenSSL, but there are also other sub-modules that will come down with the git clone operation.

git checkout the 201908 stable tag

This article is walking through setting up the edk2-stable201908 stable tag, so we need to checkout this tag.  From the directory where you cloned the EDK2 source, perform a git checkout and select the edk2-stable201908 tag:

Setup NASM

A change since my last article on UDK2015 is the requirement of installing NASM.  I'm not 100% sure why this new requirement was added—anyone know?  If so, please leave a comment!

Anyway, you can freely download the NASM assembler from their website.  If you place NASM in C:\NASM, then no further configuration is required on your part.

However, if you (like me) prefer to put NASM somewhere else, follow these steps:

  1. Download NASM
  2. Place it anywhere on your hard drive and make note of its path location
  3. Set the NASM_PREFIX environment variable either in Control Panel/System/Advanced System Settings, or from the command-line prior to launching edksetup.bat.  Example:
    set NASM_PREFIX=C:\wdl\src\wdl\EDK\edk2\nasm\
There is a note on the Tianocore NASM setup wiki saying that the path must end with a "\".  I can confirm for you that this requirement is real.

Setup the ASL Compiler

The ASL compiler is the program that turns ASL source code into AML binary code, which, at run-time, gets interpreted by ACPI drivers.  Most UEFI images do not require the ASL compiler, but, for those that do, you might as well download it.  You can freely download the Windows version from ACPICA:
https://acpica.org/downloads/binary-tools

Download the .zip file and unzip it to the directory:  C:\asl.  I don't know of any way to customize this location.  (if you do, please leave a comment!)

Install Visual Studio 2015

Finally, we need a C compiler.  EDK2 supports many different compilers; I'm using Visual Studio 2015, and the rest of this article will assume Visual Studio 2015.  However, if you choose a different one, that's fine—you may have to make some adjustments.

Phase 2:  Configure the Environment

Now that all the prerequisites have been downloaded and installed, we need to actually configure some things before the build will work.

  1. Open a command prompt to the root of the EDK source tree (i.e. the top-level-directory that contains edksetup.bat)
  2. run edksetup.bat Rebuild
    • This will compile and build the EDK2 build tools into <root>\BaseTools\Bin\Win32.  For example, GenFfs.exe, GenFv.exe, and VfrCompile.exe, among other common tools.
    • This will also copy the the default configuration templates from <root>\BaseTools\Conf to <root>\Conf—specifically, the files build_rule.txt, target.txt, and tools_def.txt

configure target.txt

The previous step copied the default templates of the configuration files into <root>\Conf.  Of these three files, chances are high that you would like to customize target.txt.  Strictly speaking, this is not necessary, since you can specify the same settings dynamically on the command-line when executing BUILD.EXE.  However, it is quite a time-saver, and avoids you having to type in long configuration strings to BUILD.EXE when you’re trying to build a UEFI module later on.
The two target.txt options most likely to need changing are:

1. TARGET_ARCH – nowadays this should probably be X64, and not the default of IA32.

2. TOOL_CHAIN_TAG – Here enter your compiler.  WARNING: this is more tricky than one would expect.  The valid values for this setting are defined in Conf\tools_def.txt, starting under the line:
# Supported Tool Chains

My experience is with the Microsoft compiler, so I’ll describe how to configure TOOL_CHAIN_TAG for that compiler.  There are instructions available at Tianocore for gcc and Macintosh Xcode.

Tianocore provides a decoder table to help you enter the correct TOOL_CHAIN_TAG value:
The first confusing thing about these entries is that they change based on the bitness of your OPERATING SYSTEM, not the bitness of your VISUAL STUDIO.  Remember that ALL VERSIONS OF VISUAL STUDIO ARE 32-BIT!  There is no such thing as 64-bit Visual Studio, although of course the 32-bit Visual Studio IDE contains a 64-bit compiler.  So, for example, the exact same installation of VS2015 will use different TOOL_CHAIN_TAG values depending on whether it gets installed on 32-bit Windows or 64-bit Windows.

The second confusing thing about these entries is that when you want to use Visual Studio on 64-bit Windows, you append “x86”; that conflicts with industry standard nomenclature, where  typically “x86 == 32-bit”, and “x64 == 64-bit”.  So I guess the thinking was that since it’s a 32-bit application, and it gets installed in “Program Files (x86)” when running on 64-bit Windows, that someone decided to append “x86” to the TOOL_CHAIN_TAG. (?)  Counter-intuitive, but that’s how it works.

The third (!) confusing thing about this is that it is perfectly legitimate to say TARGET_ARCH = X64, and TOOL_CHAIN_TAG = VS2015x86.  You read that correctly—the x86 tool chain builds X64.  Sheesh!

Finally, while we're in target.txt, let's change the ACTIVE_PLATFORM to MdeModulePkg/MdeModulePkg.dsc.  This is a more relevant build target than the EmulatorPkg that's there by default, and making this change will allow us to test-build all the EDK2 sources.

Phase 3:  Perform a Test Build

In the same command-prompt where you ran edksetup.bat Rebuild, again from the top-level directory, simply run:
build

(assumes ACTIVE_PLATFORM in target.txt is set to MdeModulePkg/MdeModulePkg.dsc)

This will build all the various modules in the EDK2 system, which should take a few minutes.

Phase 4:  Test in UEFI Shell

Okay, now that we've done all this work, let's test it out by running the HelloWorld.efi application in a UEFI shell.  In the previous step we built MdeModulePkg, which should have built HelloWorld.efi and placed it here:  <root>\Build\MdeModule\DEBUG_VS2015x86\X64

Copy HelloWorld.efi from this build location and let's run it in a UEFI shell.  There are a couple ways to do this, either by building your own UEFI shell, or by using the VisualUefi program.

Using VisualUefi

I wrote an article about Alex Ionescu's VisualUefi program, and I highly recommend this approach:

This allows you to quickly and easily test your UEFI code in a virtual machine so there's no need for rebooting or having a dedicated test machine.  No copying files to a USB flash drive and moving them around.  You can rapidly change, rebuild, and test your UEFI code in the same place on one machine with a quick feedback loop.

Build your own shell

You can also build the UEFI shell from the EDK2 sources like this:

Step 1:  Edit target.txt and change ACTIVE_PLATFORM to ShellPkg/ShellPkg.dsc. Run build from the command prompt, and shell.efi will be created under the build directory, someplace like Build\Shell\DEBUG_VS2015x86\X64\ShellPkg\...

Step 2:  Rename Shell.efi to bootx64.efi.  Put this file on a USB flash drive in a directory \efi\boot, so that the absolute path to the shell is:  \efi\boot\bootx64.efi.  This will allow your test system to automatically boot to the shell.

Step 3:  Copy your application (e.g. HelloWorld.efi) to the same USB flash drive as you did the shell. The exact location does not matter.

Step 4:  Boot the computer; it will automatically boot to the UEFI shell.  (you may need to configure your system to default to UEFI, not Legacy, boot.)

Step 5:  At the shell prompt, select your file system.  This will  be system dependent, based on the various storage devices you have installed.  Generally, look for the filesystems marked “removable”, and select one, for example fs0: <enter>

Step 6:  change directory to where you copied HelloWorld.efi and run it

Result

Whichever approach you choose, you should be able to run HelloWorld.efi from the UEFI shell and see something like this:


Success!  Now that you have the EDK installed and configured, and you are able to build a basic Hello, World application, you can begin customizing it by adding your own UEFI code.  The UefiMain() entry point gives you a pointer to the EFI_SYSTEM_TABLE, which gives you access to the whole system.  Good luck!

Post a Comment

Be sure to select an account profile (e.g. Google, OpenID, etc.) before typing your comment!