Translate

Archives

Image of Linux Kernel Development (3rd Edition)
Image of RHCE Red Hat Certified Engineer Linux Study Guide (Exam RH302) (Certification Press)
Image of Advanced Programming in the UNIX Environment, Second Edition (Addison-Wesley Professional Computing Series)
Image of XSLT 2.0 and XPath 2.0 Programmer's Reference (Programmer to Programmer)

Installing and Configuring UDK2017 on Fedora 26

UDK2017 (UEFI Development Kit, 2017 release), released in June 2017, contains reasonably detailed instructions on how to build the UDK2017 release on a “Linux-like System” which in practical terms is actually Ubuntu 16.04 LTS Desktop and GCC 5. In this post, I show you how to install and build UDK2017 on Fedora 26 Desktop using GCC 7.

UDK2017 is simply a validated snapshot of the EDK 11 (EFI Development Kit, version 2) source code at a particular point in time. The previous validated snapshot of EDK 11 was UDK2015 which was released in September 2015. Why EDK2? It is because there was a major redesign and rewrite of the original version of the EDK and there was a need to differentiate between the two versions.

Henceforth, in this post I will use the term EDK2 instead of EDK 11.

This post assumes that you have a modicum of understanding about EDK2, Fedora, and the GCC toolchain. I also assume that gcc, git, and make are already installed. If not, you will need to install the appropriate RPMs. You also need the GNU C++ compiler installed because one of the build tools, i.e. vfrcompiler, requires building with a C++ compiler. Among other things, the vrfcompiler tool converts VFRs (Virtual Forms Representation) into IFRs (Internal Forms Representation) which form part of a UEFI HII (Human Interface Infrastructure) database.

First, you need to obtain the UDK2017 sources. You can use git to get a copy of the UDK2017 sources as shown here:

$ cd ~
$ git clone https://github.com/tianocore/edk2.git vUDK2017
$ mv vUDK2017 UDK2017


or, if you prefer, you can download a zipfile or a tarball of the source files from here.

In the rest of this post, I assume that UDK2017 is installed at ~/UDK2017. In my case, that is /home/fpm/UDK2017. For some unknown reason, the current online instructions for building UDK2017 on a “Linux-like System” specify the root as ~/src/MyWorkspace.

Next install all the necessary RPMs to build the UDK2017 build tools.

# dnf install gcc-c++ iasl nasm libuuid-devel

Now, you should be able to make all the necessary build tools which are needed to build applications in UDK2017.

$ cd ~/UDK2017/BaseTools
$ make


For detailed information on all the EDK2 tools (and there are lots of them), refer to the EDK BaseTools User Guides. By the way, all EDK2 tools use INI style text based files to describe components, platforms and firmware volumes.

Assuming that the build tools have all been built successfully, the next step is to test and validate the build environment. Initialize the UDK2017 build environment using the edksetup.sh shell script.

$ cd ~/UDK2017
$ . ./edksetup.sh
WORKSPACE: /home/fpm/UDK2017
EDK_TOOLS_PATH: /home/fpm/UDK2017/BaseTools
CONF_PATH: /home/fpm/UDK2017/Conf
$

Note difference when you initiate the build environment for the second time or subsequent times:

$ cd ~/UDK2017
$ . ./edksetup.sh
Loading previous configuration from /home/fpm/UDK2017/Conf/BuildEnv.sh
WORKSPACE: /home/fpm/UDK2017
EDK_TOOLS_PATH: /home/fpm/UDK2017/BaseTools
CONF_PATH: /home/fpm/UDK2017/Conf

On Fedora 26, the default version of the GCC C compiler is 7.2.1. UDK2017 does not support GCC C compiler v7 out of the box. It only supports versions 4.4 through 5.0. However, it will still build modules (packages) and binaries using the default settings. Later on in this post, I will show you how to add GCC 7 support.

To test that your UDK2017 build environment is correct, enter following commands to build the supplied MdeModule package:

$ cd ~/UDK2017
$ . ./edksetup.sh
$ build -p MdeModulePkg/MdeModulePkg.dsc -t GCC5
Build environment: Linux-4.12.9-300.fc26.x86_64-x86_64-with-fedora-26-Twenty_Six
Build start time: 03:27:43, Oct.2 2017

WORKSPACE        = /home/fpm/UDK2017
ECP_SOURCE       = /home/fpm/UDK2017/EdkCompatibilityPkg
EDK_SOURCE       = /home/fpm/UDK2017/EdkCompatibilityPkg
EFI_SOURCE       = /home/fpm/UDK2017/EdkCompatibilityPkg
EDK_TOOLS_PATH   = /home/fpm/UDK2017/BaseTools
CONF_PATH        = /home/fpm/UDK2017/Conf

Architecture(s)  = X64
Build target     = DEBUG
Toolchain        = GCC5

Active Platform          = /home/fpm/UDK2017/MdeModulePkg/MdeModulePkg.dsc

Processing meta-data .......


If the build is successful, there should be a UEFI executable named “HelloWorld.efi” in the ~/UDK2017/Build/MdeModule/DEBUG_GCC5/IA32 directory.

Now that you have proved that your basic build environment is working by building a specific package, it is time to build your own UEFI application. Typically, you will want your own source code area (sandbox?) within the UDK2017 directory framework for applications you develop. Let us call this area MyApps.

Create a new directory ~/UDK2017/MyApps and cd to that directory. Create a file named MyApps.dec containing the following text:

[Defines]
  DEC_SPECIFICATION              = 0x00010005
  PACKAGE_NAME                   = MyApps
  PACKAGE_GUID                   = B3E3D3D5-D62B-4497-A175-264F489D127E
  PACKAGE_VERSION                = 0.01

[Guids]

[PcdsFixedAtBuild]


The DEC (Declaration) file format was designed to support building packaging and distribution of EDK2 modules, as well as for building custom applications using the EDK2 build infrastructure. See the EDK II Package Declaration (DEC) File Format Specification for full details. It can be accessed from here.

Also, in the same subdirectory, create a file named MyApps.dsc containing the following text:

[Defines]
  PLATFORM_NAME                  = MyApps
  PLATFORM_GUID                  = 0458dade-8b6e-4e45-b773-1b27cbda3e06
  PLATFORM_VERSION               = 0.01
  DSC_SPECIFICATION              = 0x00010006
  OUTPUT_DIRECTORY               = Build/MyApps
  SUPPORTED_ARCHITECTURES        = X64
  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
  SKUID_IDENTIFIER               = DEFAULT

#
#  Debug output control
#
  DEFINE DEBUG_ENABLE_OUTPUT      = FALSE       # Set to TRUE to enable debug output
  DEFINE DEBUG_PRINT_ERROR_LEVEL  = 0x80000040  # Flags to control amount of debug output
  DEFINE DEBUG_PROPERTY_MASK      = 0

[PcdsFeatureFlag]

[PcdsFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|$(DEBUG_PROPERTY_MASK)
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|$(DEBUG_PRINT_ERROR_LEVEL)

[PcdsFixedAtBuild.IPF]

[LibraryClasses]
  # Entry Point Libraries
  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
  ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

  # Common Libraries
  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
  !if $(DEBUG_ENABLE_OUTPUT)
    DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
    DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
  !else   ## DEBUG_ENABLE_OUTPUT
    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
  !endif  ## DEBUG_ENABLE_OUTPUT

  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
  PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
  ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
  HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf

[Components]

#### Applications ####
  MyApps/HelloWorld/HelloWorld.inf

A DSC file is an EDK2 platform description file that contains a list of:

  • EDK2 Module INF Files
  • EDK Components
  • EDK libraries (used by EDK components)
  • EDK2 Library class instance mappings (used by EDK2 modules)
  • EDK2 PCD Entries

See the EDK II Platform Description (DSC) File Specification for full details. It can be accessed from here. The sample contents provided above contain most of the libraries that you should ever need. The only supported architecture in the above platform description file is X64; you can add additional architectures such as IA32 or AARCH64 if you want too.

Next, let us create a simple Hello World UEFI application. In our particular build environment, all the source files associated with our Hello World application are located in one directory and form a package. Go ahead an create a subdirectory under …/UDK2017/MyApps named HelloWorld.

In the HelloWorld subdirectory, create a file named HelloWorld.inf with the following contents:

Defines]
  INF_VERSION                   = 0x00010006
  BASE_NAME                     = HelloWorld
  FILE_GUID                     = a912f198-7f0e-4803-b908-b757b806ec83
  MODULE_TYPE                   = UEFI_APPLICATION
  VERSION_STRING                = 1.0
  ENTRY_POINT                   = ShellCEntryLib
  VALID_ARCHITECTURES           = X64

[Sources]
  HelloWorld.c

[Packages]
  MdePkg/MdePkg.dec
  ShellPkg/ShellPkg.dec

[LibraryClasses]
  UefiLib
  ShellCEntryLib


An INF file is an EDK2 module information file. INF files are used by EDK2 build tools to generate AutoGen.c and AutoGen.h and Makefile/GNU makefile files for the EDK2 build infrastructure. The intent of a module’s INF file is to define the source files, libraries, and definitions relevant to building the module, creating one or more binary files that are either raw binary files or PE32 or PE32+ or COFF format files. See the EDK II Module Information (INF) File Specification for full details. It can be accessed from here.

Next, in the HelloWorld subdirectory, create a file named HelloWorld.c containing the folloowing:

#include <uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>

INTN
EFIAPI
ShellAppMain( UINTN Argc, CHAR16 **Argv)
{
    Print(L"Hello World!\n");

    return(0);
}


This is the actual source file for our HelloWorld UEFI application. Everything else we have done up to this point was related to the EDK2 build environment.

Now, we finally get to build out HelloWorld application:

$ cd ~/UDK2017
$ . ./edksetup.sh 
Loading previous configuration from /home/fpm/UDK2017/Conf/BuildEnv.sh
WORKSPACE: /home/fpm/UDK2017
EDK_TOOLS_PATH: /home/fpm/UDK2017/BaseTools
CONF_PATH: /home/fpm/UDK2017/Conf

$ build -p MyApps/MyApps.dsc -t GCC5
[UDK2017]$ build -p MyApps/MyApps.dsc -t GCC5
Build environment: Linux-4.12.9-300.fc26.x86_64-x86_64-with-fedora-26-Twenty_Six
Build start time: 12:03:37, Sep.27 2017

WORKSPACE        = /home/fpm/UDK2017
ECP_SOURCE       = /home/fpm/UDK2017/EdkCompatibilityPkg
EDK_SOURCE       = /home/fpm/UDK2017/EdkCompatibilityPkg
EFI_SOURCE       = /home/fpm/UDK2017/EdkCompatibilityPkg
EDK_TOOLS_PATH   = /home/fpm/UDK2017/BaseTools
CONF_PATH        = /home/fpm/UDK2017/Conf

Architecture(s)  = X64
Build target     = DEBUG
Toolchain        = GCC5

Active Platform          = /home/fpm/UDK2017/MyApps/MyApps.dsc

Processing meta-data . done!
Building ... /home/fpm/UDK2017/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf [X64]
Building ... /home/fpm/UDK2017/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf [X64]
Building ... /home/fpm/UDK2017/MdePkg/Library/BaseLib/BaseLib.inf [X64]
Building ... /home/fpm/UDK2017/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf [X64]
"gcc" -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=BaseMemoryLibStrings -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address -flto -DUSING_LTO -Os -c -o /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MdePkg/Library/BaseMemoryLib/BaseMemoryLib/OUTPUT/./SetMem.obj -I/home/fpm/UDK2017/MdePkg/Library/BaseMemoryLib -I/home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MdePkg/Library/BaseMemoryLib/BaseMemoryLib/DEBUG -I/home/fpm/UDK2017/MdePkg -I/home/fpm/UDK2017/MdePkg/Include -I/home/fpm/UDK2017/MdePkg/Include/X64 /home/fpm/UDK2017/MdePkg/Library/BaseMemoryLib/SetMem.c
Building ... /home/fpm/UDK2017/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf [X64]
"gcc" -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=BasePcdLibNullStrings -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address -flto -DUSING_LTO -Os -c -o /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MdePkg/Library/BasePcdLibNull/BasePcdLibNull/OUTPUT/./PcdLib.obj -I/home/fpm/UDK2017/MdePkg/Library/BasePcdLibNull -I/home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MdePkg/Library/BasePcdLibNull/BasePcdLibNull/DEBUG -I/home/fpm/UDK2017/MdePkg -I/home/fpm/UDK2017/MdePkg/Include -I/home/fpm/UDK2017/MdePkg/Include/X64 /home/fpm/UDK2017/MdePkg/Library/BasePcdLibNull/PcdLib.c

 ...

"gcc-ar" cr /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/OUTPUT/HelloWorld.lib  @/home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/OUTPUT/object_files.lst
"gcc" -o /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x40 -Wl,--entry,_ModuleEntryPoint -u _ModuleEntryPoint -Wl,-Map,/home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.map,--whole-archive -Wl,-melf_x86_64,--oformat=elf64-x86-64,-pie -flto -Os -Wl,--start-group,@/home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/OUTPUT/static_library_files.lst,--end-group -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=HelloWorldStrings -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address -flto -DUSING_LTO -Os -Wl,--defsym=PECOFF_HEADER_SIZE=0x228 -Wl,--script=/home/fpm/UDK2017/BaseTools/Scripts/GccBase.lds -Wno-error
"objcopy"  /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll
cp -f /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.debug
objcopy --strip-unneeded -R .eh_frame /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll
objcopy --add-gnu-debuglink=/home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.debug /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll
cp -f /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.debug /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/HelloWorld.debug
"GenFw" -e UEFI_APPLICATION -o /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.efi /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.dll
cp -f /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.efi /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/OUTPUT
cp -f /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/HelloWorld.efi /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/HelloWorld.efi
cp -f /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/DEBUG/*.map /home/fpm/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/OUTPUT

- Done -
Build end time: 12:03:45, Sep.27 2017
Build total time: 00:00:08

$ 


Note how a HelloWorld.dll was first built, and genfw was then used to convert that DLL into HelloWorld.efi which is actually a simple MSDOS executable.

Examining the list of files generated by our build revels more interesting information:

$ cd ~/UDK2017/Build/MyApps/DEBUG_GCC5/X64/MyApps/HelloWorld/HelloWorld/OUTPUT
$ ls -al
total 172
drwxrwxr-x. 2 fpm fpm  4096 Sep 27 12:03 .
drwxrwxr-x. 4 fpm fpm  4096 Sep 27 12:03 ..
-rw-rw-r--. 1 fpm fpm 44032 Sep 27 12:03 AutoGen.obj
-rw-rw-r--. 1 fpm fpm  5888 Sep 27 12:03 HelloWorld.efi
-rw-rw-r--. 1 fpm fpm  5098 Sep 27 12:03 HelloWorld.inf
-rw-rw-r--. 1 fpm fpm 50640 Sep 27 12:03 HelloWorld.lib
-rw-rw-r--. 1 fpm fpm 34503 Sep 27 12:03 HelloWorld.map
-rw-rw-r--. 1 fpm fpm  4704 Sep 27 12:03 HelloWorld.obj
-rw-rw-r--. 1 fpm fpm   190 Sep 27 12:03 object_files.lst
-rw-rw-r--. 1 fpm fpm  1607 Sep 27 12:03 static_library_files.lst
$ file HelloWorld.efi
HelloWorld.efi: MS-DOS executable

$ objdump -x HelloWorld.efi

HelloWorld.efi:     file format pei-x86-64
HelloWorld.efi
architecture: i386:x86-64, flags 0x0000010b:
HAS_RELOC, EXEC_P, HAS_DEBUG, D_PAGED
start address 0x0000000000001070

Characteristics 0x2e
	executable
	line numbers stripped
	symbols stripped
	large address aware

Time/Date		Wed Dec 31 19:00:00 1969
Magic			020b	(PE32+)
MajorLinkerVersion	0
MinorLinkerVersion	0
SizeOfCode		00001200
SizeOfInitializedData	00000240
SizeOfUninitializedData	00000000
AddressOfEntryPoint	0000000000001070
BaseOfCode		0000000000000240
ImageBase		0000000000000000
SectionAlignment	0000000000000040
FileAlignment		0000000000000040
MajorOSystemVersion	0
MinorOSystemVersion	0
MajorImageVersion	0
MinorImageVersion	0
MajorSubsystemVersion	0
MinorSubsystemVersion	0
Win32Version		00000000
SizeOfImage		00001700
SizeOfHeaders		00000240
CheckSum		00000000
Subsystem		0000000a	(EFI application)
DllCharacteristics	00000000
SizeOfStackReserve	0000000000000000
SizeOfStackCommit	0000000000000000
SizeOfHeapReserve	0000000000000000
SizeOfHeapCommit	0000000000000000
LoaderFlags		00000000
NumberOfRvaAndSizes	00000010

The Data Directory
Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 0000000000000000 00000000 Import Directory [parts of .idata]
Entry 2 0000000000000000 00000000 Resource Directory [.rsrc]
Entry 3 0000000000000000 00000000 Exception Directory [.pdata]
Entry 4 0000000000000000 00000000 Security Directory
Entry 5 0000000000001680 00000080 Base Relocation Directory [.reloc]
Entry 6 00000000000015b8 0000001c Debug Directory
Entry 7 0000000000000000 00000000 Description Directory
Entry 8 0000000000000000 00000000 Special Directory
Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
Entry a 0000000000000000 00000000 Load Configuration Directory
Entry b 0000000000000000 00000000 Bound Import Directory
Entry c 0000000000000000 00000000 Import Address Table Directory
Entry d 0000000000000000 00000000 Delay Import Directory
Entry e 0000000000000000 00000000 CLR Runtime Header
Entry f 0000000000000000 00000000 Reserved

PE File Base Relocations (interpreted .reloc section contents)

Virtual Address: 00001000 Chunk size 128 (0x80) Number of fixups 60
	reloc    0 offset  460 [1460] DIR64
	reloc    1 offset  468 [1468] DIR64
	reloc    2 offset  470 [1470] DIR64
	reloc    3 offset  478 [1478] DIR64
	reloc    4 offset  480 [1480] DIR64
	reloc    5 offset  488 [1488] DIR64
	reloc    6 offset  490 [1490] DIR64
	reloc    7 offset  498 [1498] DIR64
	reloc    8 offset  4a0 [14a0] DIR64
	reloc    9 offset  4a8 [14a8] DIR64
	reloc   10 offset  4b0 [14b0] DIR64
	reloc   11 offset  4b8 [14b8] DIR64
	reloc   12 offset  4c0 [14c0] DIR64
	reloc   13 offset  4c8 [14c8] DIR64
	reloc   14 offset  4d0 [14d0] DIR64
	reloc   15 offset  4d8 [14d8] DIR64
	reloc   16 offset  4e0 [14e0] DIR64
	reloc   17 offset  4e8 [14e8] DIR64
	reloc   18 offset  4f0 [14f0] DIR64
	reloc   19 offset  4f8 [14f8] DIR64
	reloc   20 offset  500 [1500] DIR64
	reloc   21 offset  508 [1508] DIR64
	reloc   22 offset  510 [1510] DIR64
	reloc   23 offset  518 [1518] DIR64
	reloc   24 offset  520 [1520] DIR64
	reloc   25 offset  528 [1528] DIR64
	reloc   26 offset  530 [1530] DIR64
	reloc   27 offset  538 [1538] DIR64
	reloc   28 offset  540 [1540] DIR64
	reloc   29 offset  548 [1548] DIR64
	reloc   30 offset  550 [1550] DIR64
	reloc   31 offset  558 [1558] DIR64
	reloc   32 offset  560 [1560] DIR64
	reloc   33 offset  568 [1568] DIR64
	reloc   34 offset  570 [1570] DIR64
	reloc   35 offset  578 [1578] DIR64
	reloc   36 offset  580 [1580] DIR64
	reloc   37 offset  588 [1588] DIR64
	reloc   38 offset  590 [1590] DIR64
	reloc   39 offset    0 [1000] ABSOLUTE
	reloc   40 offset    0 [1000] ABSOLUTE
	reloc   41 offset    0 [1000] ABSOLUTE
	reloc   42 offset    0 [1000] ABSOLUTE
	reloc   43 offset    0 [1000] ABSOLUTE
	reloc   44 offset    0 [1000] ABSOLUTE
	reloc   45 offset    0 [1000] ABSOLUTE
	reloc   46 offset    0 [1000] ABSOLUTE
	reloc   47 offset    0 [1000] ABSOLUTE
	reloc   48 offset    0 [1000] ABSOLUTE
	reloc   49 offset    0 [1000] ABSOLUTE
	reloc   50 offset    0 [1000] ABSOLUTE
	reloc   51 offset    0 [1000] ABSOLUTE
	reloc   52 offset    0 [1000] ABSOLUTE
	reloc   53 offset    0 [1000] ABSOLUTE
	reloc   54 offset    0 [1000] ABSOLUTE
	reloc   55 offset    0 [1000] ABSOLUTE
	reloc   56 offset    0 [1000] ABSOLUTE
	reloc   57 offset    0 [1000] ABSOLUTE
	reloc   58 offset    0 [1000] ABSOLUTE
	reloc   59 offset    0 [1000] ABSOLUTE

There is a debug directory in .data at 0x15b8

Type                Size     Rva      Offset
  2        CodeView 00000070 000015d4 000015d4
(format NB10 signature 00000000 age 0)

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00001200  0000000000000240  0000000000000240  00000240  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000240  0000000000001440  0000000000001440  00001440  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  2 .reloc        00000080  0000000000001680  0000000000001680  00001680  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
SYMBOL TABLE:
no symbols
$ 

Turning now to how to add GCC version 7 support to the UDK2017 build environment. Fortunately, only one file needs to be augmented, i.e. …/UDK2017/Conf/tools_def.txt. Here are the diffs:

210a211,213
> DEFINE GCC7_IA32_PREFIX        = ENV(GCC7_BIN)
> DEFINE GCC7_X64_PREFIX         = ENV(GCC7_BIN)
> 
4630a4634,4645
> 
> DEFINE GCC7_IA32_CC_FLAGS            = DEF(GCC5_IA32_CC_FLAGS)
> DEFINE GCC7_X64_CC_FLAGS             = DEF(GCC5_X64_CC_FLAGS)
> DEFINE GCC7_IA32_X64_DLINK_COMMON    = DEF(GCC5_IA32_X64_DLINK_COMMON)
> DEFINE GCC7_IA32_X64_ASLDLINK_FLAGS  = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS)
> DEFINE GCC7_IA32_X64_DLINK_FLAGS     = DEF(GCC5_IA32_X64_DLINK_FLAGS)
> DEFINE GCC7_IA32_DLINK2_FLAGS        = DEF(GCC5_IA32_DLINK2_FLAGS) -Wno-error
> DEFINE GCC7_X64_DLINK_FLAGS          = DEF(GCC5_X64_DLINK_FLAGS)
> DEFINE GCC7_X64_DLINK2_FLAGS         = DEF(GCC5_X64_DLINK2_FLAGS) -Wno-error
> DEFINE GCC7_ASM_FLAGS                = DEF(GCC5_ASM_FLAGS)
> 
> 
5563a5579,5666
> 
> 
> ####################################################################################
> #
> # GCC 7 - This configuration is used to compile under Linux to produce
> #         PE/COFF binaries using GCC 7
> #
> ####################################################################################
> *_GCC7_*_*_FAMILY                = GCC
> 
> *_GCC7_*_MAKE_PATH               = DEF(GCC7_IA32_PREFIX)make
> *_GCC7_*_*_DLL                   = ENV(GCC7_DLL)
> *_GCC7_*_ASL_PATH                = DEF(UNIX_IASL_BIN)
> *_GCC7_*_DTC_PATH                = DEF(DTC_BIN)
> 
> *_GCC7_*_PP_FLAGS                = DEF(GCC_PP_FLAGS)
> *_GCC7_*_ASLPP_FLAGS             = DEF(GCC_ASLPP_FLAGS)
> *_GCC7_*_ASLCC_FLAGS             = DEF(GCC_ASLCC_FLAGS)
> *_GCC7_*_VFRPP_FLAGS             = DEF(GCC_VFRPP_FLAGS)
> *_GCC7_*_APP_FLAGS               =
> *_GCC7_*_ASL_FLAGS               = DEF(IASL_FLAGS)
> *_GCC7_*_ASL_OUTFLAGS            = DEF(IASL_OUTFLAGS)
> 
> ##################
> # GCC7 IA32 definitions
> ##################
> *_GCC7_IA32_OBJCOPY_PATH         = DEF(GCC7_IA32_PREFIX)objcopy
> *_GCC7_IA32_CC_PATH              = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_SLINK_PATH           = DEF(GCC7_IA32_PREFIX)gcc-ar
> *_GCC7_IA32_DLINK_PATH           = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_ASLDLINK_PATH        = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_ASM_PATH             = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_PP_PATH              = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_VFRPP_PATH           = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_ASLCC_PATH           = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_ASLPP_PATH           = DEF(GCC7_IA32_PREFIX)gcc
> *_GCC7_IA32_RC_PATH              = DEF(GCC7_IA32_PREFIX)objcopy
> 
> *_GCC7_IA32_ASLCC_FLAGS          = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto
> *_GCC7_IA32_ASLDLINK_FLAGS       = DEF(GCC7_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386
> *_GCC7_IA32_ASM_FLAGS            = DEF(GCC7_ASM_FLAGS) -m32 -march=i386
> *_GCC7_IA32_DLINK2_FLAGS         = DEF(GCC7_IA32_DLINK2_FLAGS)
> *_GCC7_IA32_RC_FLAGS             = DEF(GCC_IA32_RC_FLAGS)
> *_GCC7_IA32_OBJCOPY_FLAGS        =
> *_GCC7_IA32_NASM_FLAGS           = -f elf32
> 
>   DEBUG_GCC7_IA32_CC_FLAGS       = DEF(GCC7_IA32_CC_FLAGS) -flto -Os
>   DEBUG_GCC7_IA32_DLINK_FLAGS    = DEF(GCC7_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,-m,elf_i386,--oformat=elf32-i386
> 
> RELEASE_GCC7_IA32_CC_FLAGS       = DEF(GCC7_IA32_CC_FLAGS) -flto -Os -Wno-unused-but-set-variable -Wno-unused-const-variable
> RELEASE_GCC7_IA32_DLINK_FLAGS    = DEF(GCC7_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,-m,elf_i386,--oformat=elf32-i386
> 
>   NOOPT_GCC7_IA32_CC_FLAGS       = DEF(GCC7_IA32_CC_FLAGS) -O0
>   NOOPT_GCC7_IA32_DLINK_FLAGS    = DEF(GCC7_IA32_X64_DLINK_FLAGS) -Wl,-m,elf_i386,--oformat=elf32-i386 -O0
> 
> ##################
> # GCC7 X64 definitions
> ##################
> *_GCC7_X64_OBJCOPY_PATH          = DEF(GCC7_X64_PREFIX)objcopy
> *_GCC7_X64_CC_PATH               = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_SLINK_PATH            = DEF(GCC7_X64_PREFIX)gcc-ar
> *_GCC7_X64_DLINK_PATH            = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_ASLDLINK_PATH         = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_ASM_PATH              = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_PP_PATH               = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_VFRPP_PATH            = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_ASLCC_PATH            = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_ASLPP_PATH            = DEF(GCC7_X64_PREFIX)gcc
> *_GCC7_X64_RC_PATH               = DEF(GCC7_X64_PREFIX)objcopy
> 
> *_GCC7_X64_ASLCC_FLAGS           = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto
> *_GCC7_X64_ASLDLINK_FLAGS        = DEF(GCC7_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64
> *_GCC7_X64_ASM_FLAGS             = DEF(GCC7_ASM_FLAGS) -m64
> *_GCC7_X64_DLINK2_FLAGS          = DEF(GCC7_X64_DLINK2_FLAGS)
> *_GCC7_X64_RC_FLAGS              = DEF(GCC_X64_RC_FLAGS)
> *_GCC7_X64_OBJCOPY_FLAGS         =
> *_GCC7_X64_NASM_FLAGS            = -f elf64
> 
>   DEBUG_GCC7_X64_CC_FLAGS        = DEF(GCC7_X64_CC_FLAGS) -flto -DUSING_LTO -Os
>   DEBUG_GCC7_X64_DLINK_FLAGS     = DEF(GCC7_X64_DLINK_FLAGS) -flto -Os
> 
> RELEASE_GCC7_X64_CC_FLAGS        = DEF(GCC7_X64_CC_FLAGS) -flto -DUSING_LTO -Os -Wno-unused-but-set-variable -Wno-unused-const-variable
> RELEASE_GCC7_X64_DLINK_FLAGS     = DEF(GCC7_X64_DLINK_FLAGS) -flto -Os
> 
>   NOOPT_GCC7_X64_CC_FLAGS        = DEF(GCC7_X64_CC_FLAGS) -O0
>   NOOPT_GCC7_X64_DLINK_FLAGS     = DEF(GCC7_X64_DLINK_FLAGS) -O0


You can download the full updated tools_def.txt from here. The file is named UDK2017_GCC7_tools_def.txt.

You can also set defaults for a number of the build options such the package to build, the target architecture, toolchain to use, and more. To do this, you need to modify …/UDK2017/Conf/target.txt. Here are the diffs of the modifications I made to my version of this file:

26c26,27
< ACTIVE_PLATFORM       = Nt32Pkg/Nt32Pkg.dsc
---
> # ACTIVE_PLATFORM       = Nt32Pkg/Nt32Pkg.dsc
> ACTIVE_PLATFORM       = MyApps/MyApps.dsc

50c51
< TARGET_ARCH           = IA32
---
> TARGET_ARCH           = X64

60c61,62
< TOOL_CHAIN_TAG        = MYTOOLS
---
> # TOOL_CHAIN_TAG        = MYTOOLS
> TOOL_CHAIN_TAG        = GCC7 

65c67,68
< MAX_CONCURRENT_THREAD_NUMBER = 1
---
> # MAX_CONCURRENT_THREAD_NUMBER = 1
> MAX_CONCURRENT_THREAD_NUMBER = 5


Now when you type build by itself, it looks in …/UDK2017/Conf/target.txt as usual, sees that it should use …/UDK2017/MyApps/MyApps.dsc to determine what package to build, and uses the GCC7 toolchain to build a 64-bit version of the application.

OK, this post is getting quite long and it is time to stop. Hopefully, you now have sufficient information to start developing UEFI applications on Fedora 26. Whilst I have not tested it, all that I have described here should also work on RHEL and CentOS distributions.

UPDATE: December 2017. I upgraded to Fedora 27 and everything still works.

Leave a Reply