The objective of this post is to explain how to get started with UEFI development by getting the UDK2015 development environment up and running, creating a Hello, World example program, and running it in the UEFI shell.  Once you can get a simple application built and running in a UEFI Shell, you can begin extending it to greater and greater sophistication!

There are three basic phases you need to complete in order to make this work:

  1. Download the UDK and get it installed and configured properly on your system
  2. Locate an appropriate sample application and build it
  3. Boot a test system to the UEFI shell and run your sample application


Phase 1: Install and Configure UDK

Step 1:  Download UDK 2015 (116MB)

Step 2:  The main .ZIP is a collection of .ZIPs.  First, extract UDK2015.MyWorkSpace.zip.

Step 3:  This is tricky:  you next have to unzip BaseTools(Windows).zip, or BaseTools(Unix).tar, whichever development environment you prefer, and it has to be put in a subdirectory of the MyWorkSpace directory from Step 2.  The “BaseTools” directory should be at a peer level to Conf, CryptoPkg, MdePkg, etc.  The final directory structure should look like:

    MyWorkSpace

        -->BaseTools

        -->Conf

        -->CryptoPkg

        etc.

Step 4:  Modify Conf\target.txt to suit your build configuration.  Strictly speaking, this is optional, since you can specify the settings in this file dynamically on the command-line to 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 three options most likely to need changing are:

  1. TARGET_ARCH – nowadays this should probably be X64, and not the default of IA32.
  2. MAX_CONCURRENT_THREAD_NUMBER – like the comment says, add one to number of CPUs in your machine.  For example, if you have a four core processor, where each core is HyperThreaded, enter 9 for this number.
  3. TOOL_CHAIN_TAG – Here enter your compiler.  WARNING: this is more tricky than you might think it should be.  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:
    image
    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 VS2010 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. (?)  Counterintuitive, 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 = VS2010x86.  You read that correctly—the x86 tool chain builds X64.  Sheesh!


Phase 2:  Build Sample Application

Now that the UDK has been downloaded, installed, and configured, you are ready to build an actual UEFI application!

The UDK comes with many Hello, World-style applications (and even more sophisticated applications) bundled inside—a very handy feature!  For example, look in some of these directories to find them:

  • MdeModulePkg\Application
  • ShellPkg\Application
  • SecurityPkg\Application
  • … and many others

Select one of them that best suits your needs, and build it like so:

Step 1:  Open a Command Prompt (cmd.exe) and cd to MyWorkSpace\

Step 2:  Run edksetup

Step 3:  build -m MdeModulePkg\Application\HelloWorld\HelloWorld.inf

At this point the UDK will come to life and build the HelloWorld application.  It will use as default the build settings you specified in Conf\target.txt, above.  Any of these settings can be overridden on the command-line.  Please run BUILD.EXE –h to see all the various options.


Phase 3:  Test in UEFI Shell

If you made it this far, you have built a sample application, like HelloWorld.  Now we can test it in the UEFI shell.  Follow these steps:

Step 1:  The UDK comes with UEFI shells already pre-built in binary form, located here:  ShellBinPkg\UefiShell\<arch>.  Select the shell that matches your computer architecture.

Step 2:  Assuming you’re running X64, rename ShellBinPkg\UefiShell\X64\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 the HelloWorld.efi and run it

image

Congratulations, you did it!


Conclusion

At this point the possibilities are endless.  Now that you have the UDK 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.  Enjoy!


Note:  if you’re interested in UDK2014, I wrote a similar post awhile back, located here.

Post a Comment

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