Re-format README
* Make it look right in Markdown format * Fix PE32+ spec link Signed-off-by: Callum Farmer <gmbr3@opensuse.org>
This commit is contained in:
parent
2a3244d2e5
commit
dfc27f3416
151
README.md
151
README.md
@ -1,18 +1,19 @@
|
||||
-------------------------------------------------
|
||||
Building EFI Applications Using the GNU Toolchain
|
||||
-------------------------------------------------
|
||||
-------------------------------------------------
|
||||
Building EFI Applications Using the GNU Toolchain
|
||||
-------------------------------------------------
|
||||
|
||||
David Mosberger <davidm@hpl.hp.com>
|
||||
David Mosberger <davidm@hpl.hp.com>
|
||||
|
||||
23 September 1999
|
||||
23 September 1999
|
||||
|
||||
|
||||
Copyright (c) 1999-2007 Hewlett-Packard Co.
|
||||
Copyright (c) 2006-2010 Intel Co.
|
||||
Copyright (c) 1999-2007 Hewlett-Packard Co.
|
||||
|
||||
Copyright (c) 2006-2010 Intel Co.
|
||||
|
||||
Last update (DD/MM/YYYY): 19/08/2024
|
||||
|
||||
* Introduction
|
||||
# Introduction
|
||||
|
||||
This document has two parts: the first part describes how to develop
|
||||
EFI applications for IA-64,x86 and x86_64 using the GNU toolchain and the EFI
|
||||
@ -22,76 +23,72 @@ environment works.
|
||||
|
||||
|
||||
|
||||
* Part 1: Developing EFI Applications
|
||||
# Part 1: Developing EFI Applications
|
||||
|
||||
|
||||
** Prerequisites:
|
||||
## Prerequisites:
|
||||
|
||||
To develop x86 and x86_64 EFI applications, the following tools are needed:
|
||||
|
||||
- gcc-3.0 or newer (gcc 2.7.2 is NOT sufficient!)
|
||||
As of gnu-efi-3.0b, the Redhat 8.0 toolchain is known to work,
|
||||
but the Redhat 9.0 toolchain is not currently supported.
|
||||
- gcc-3.0 or newer (gcc 2.7.2 is NOT sufficient!)
|
||||
As of gnu-efi-3.0b, the Redhat 8.0 toolchain is known to work,
|
||||
but the Redhat 9.0 toolchain is not currently supported.
|
||||
|
||||
- A version of "objcopy" that supports EFI applications. To
|
||||
check if your version includes EFI support, issue the
|
||||
command:
|
||||
- A version of "objcopy" that supports EFI applications. To
|
||||
check if your version includes EFI support, issue the
|
||||
command: `objcopy --help`
|
||||
|
||||
objcopy --help
|
||||
Verify that the line "supported targets" contains the string
|
||||
"efi-app-ia32" and "efi-app-x86_64" and that the "-j" option
|
||||
accepts wildcards. The binutils release binutils-2.24
|
||||
supports Intel64 EFI and accepts wildcard section names.
|
||||
|
||||
Verify that the line "supported targets" contains the string
|
||||
"efi-app-ia32" and "efi-app-x86_64" and that the "-j" option
|
||||
accepts wildcards. The binutils release binutils-2.24
|
||||
supports Intel64 EFI and accepts wildcard section names.
|
||||
|
||||
- For debugging purposes, it's useful to have a version of
|
||||
"objdump" that supports EFI applications as well. This
|
||||
allows inspect and disassemble EFI binaries.
|
||||
- For debugging purposes, it's useful to have a version of
|
||||
"objdump" that supports EFI applications as well. This
|
||||
allows inspect and disassemble EFI binaries.
|
||||
|
||||
To develop IA-64 EFI applications, the following tools are needed:
|
||||
|
||||
- A version of gcc newer than July 30th 1999 (older versions
|
||||
had problems with generating position independent code).
|
||||
As of gnu-efi-3.0b, gcc-3.1 is known to work well.
|
||||
- A version of gcc newer than July 30th 1999 (older versions
|
||||
had problems with generating position independent code).
|
||||
As of gnu-efi-3.0b, gcc-3.1 is known to work well.
|
||||
|
||||
- A version of "objcopy" that supports EFI applications. To
|
||||
check if your version includes EFI support, issue the
|
||||
command:
|
||||
- A version of "objcopy" that supports EFI applications. To
|
||||
check if your version includes EFI support, issue the
|
||||
command: `objcopy --help`
|
||||
|
||||
objcopy --help
|
||||
Verify that the line "supported targets" contains the string
|
||||
"efi-app-ia64" and that the "-j" option accepts wildcards.
|
||||
|
||||
Verify that the line "supported targets" contains the string
|
||||
"efi-app-ia64" and that the "-j" option accepts wildcards.
|
||||
|
||||
- For debugging purposes, it's useful to have a version of
|
||||
"objdump" that supports EFI applications as well. This
|
||||
allows inspect and disassemble EFI binaries.
|
||||
- For debugging purposes, it's useful to have a version of
|
||||
"objdump" that supports EFI applications as well. This
|
||||
allows inspect and disassemble EFI binaries.
|
||||
|
||||
|
||||
** Directory Structure
|
||||
## Directory Structure
|
||||
|
||||
This EFI development environment contains the following
|
||||
subdirectories:
|
||||
|
||||
inc: This directory contains the EFI-related include files. The
|
||||
- inc: This directory contains the EFI-related include files. The
|
||||
files are taken from Intel's EFI source distribution, except
|
||||
that various fixes were applied to make it compile with the
|
||||
GNU toolchain.
|
||||
|
||||
lib: This directory contains the source code for Intel's EFI library.
|
||||
- lib: This directory contains the source code for Intel's EFI library.
|
||||
Again, the files are taken from Intel's EFI source
|
||||
distribution, with changes to make them compile with the GNU
|
||||
toolchain.
|
||||
|
||||
gnuefi: This directory contains the glue necessary to convert ELF64
|
||||
- gnuefi: This directory contains the glue necessary to convert ELF64
|
||||
binaries to EFI binaries. Various runtime code bits, such as
|
||||
a self-relocator are included as well. This code has been
|
||||
contributed by the Hewlett-Packard Company and is distributed
|
||||
under the GNU GPL.
|
||||
|
||||
apps: This directory contains a few simple EFI test apps.
|
||||
- apps: This directory contains a few simple EFI test apps.
|
||||
|
||||
** Setup
|
||||
## Setup
|
||||
|
||||
It is necessary to edit the Makefile in the directory containing this
|
||||
README file before EFI applications can be built. Specifically, you
|
||||
@ -105,7 +102,7 @@ x86_64 and "ia64" for IA-64). For convenience, this can also be done from
|
||||
the make command line (e.g., "make ARCH=ia64").
|
||||
|
||||
|
||||
** Building
|
||||
## Building
|
||||
|
||||
To build the sample EFI applications provided in subdirectory "apps",
|
||||
simply invoke "make" in the toplevel directory (the directory
|
||||
@ -114,7 +111,7 @@ gnuefi/libgnuefi.a first and then all the EFI applications such as a
|
||||
apps/t6.efi.
|
||||
|
||||
|
||||
** Running
|
||||
## Running
|
||||
|
||||
Just copy the EFI application (e.g., apps/t6.efi) to the EFI
|
||||
filesystem, boot EFI, and then select "Invoke EFI application" to run
|
||||
@ -123,7 +120,7 @@ Intel-provided "nshell" application and then invoke your test binary
|
||||
via the command line interface that "nshell" provides.
|
||||
|
||||
|
||||
** Writing Your Own EFI Application
|
||||
## Writing Your Own EFI Application
|
||||
|
||||
Suppose you have your own EFI application in a file called
|
||||
"apps/myefiapp.c". To get this application built by the GNU EFI build
|
||||
@ -150,7 +147,7 @@ described in Intel's EFI documentation, except for two differences:
|
||||
ensures appropriate parameter passing for the architecture.
|
||||
|
||||
|
||||
* Part 2: Inner Workings
|
||||
# Part 2: Inner Workings
|
||||
|
||||
WARNING: This part contains all the gory detail of how the GNU EFI
|
||||
toolchain works. Normal users do not have to worry about such
|
||||
@ -175,16 +172,14 @@ and each has there own subsystem id and are identical otherwise. At
|
||||
present, the GNU EFI build environment supports the building of EFI
|
||||
applications only, though it would be trivial to generate drivers, as
|
||||
the only difference is the subsystem id. For more details on PE32+,
|
||||
see the spec at
|
||||
|
||||
http://msdn.microsoft.com/library/specs/msdn_pecoff.htm.
|
||||
see the [Specification](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format).
|
||||
|
||||
In theory, converting a suitable ELF64 binary to PE32+ is easy and
|
||||
could be accomplished with the "objcopy" utility by specifying option
|
||||
--target=efi-app-ia32 (x86) or --target=efi-app-ia64 (IA-64). But
|
||||
life never is that easy, so here some complicating factors:
|
||||
|
||||
(1) COFF sections are very different from ELF sections.
|
||||
1. COFF sections are very different from ELF sections.
|
||||
|
||||
ELF binaries distinguish between program headers and sections.
|
||||
The program headers describe the memory segments that need to
|
||||
@ -195,7 +190,7 @@ life never is that easy, so here some complicating factors:
|
||||
(4KB for EFI), whereas ELF allows sections at arbitrary
|
||||
addresses and with arbitrary sizes.
|
||||
|
||||
(2) EFI binaries should be relocatable.
|
||||
2. EFI binaries should be relocatable.
|
||||
|
||||
Since EFI binaries are executed in physical mode, EFI cannot
|
||||
guarantee that a given binary can be loaded at its preferred
|
||||
@ -204,10 +199,10 @@ life never is that easy, so here some complicating factors:
|
||||
address and then relocate the binary using the contents of the
|
||||
.reloc section.
|
||||
|
||||
(3) On IA-64, the EFI entry point needs to point to a function
|
||||
3. On IA-64, the EFI entry point needs to point to a function
|
||||
descriptor, not to the code address of the entry point.
|
||||
|
||||
(4) The EFI specification assumes that wide characters use UNICODE
|
||||
4. The EFI specification assumes that wide characters use UNICODE
|
||||
encoding.
|
||||
|
||||
ANSI C does not specify the size or encoding that a wide
|
||||
@ -220,7 +215,7 @@ In the following sections, we address how the GNU EFI build
|
||||
environment addresses each of these issues.
|
||||
|
||||
|
||||
** (1) Accommodating COFF Sections
|
||||
## (1) Accommodating COFF Sections
|
||||
|
||||
In order to satisfy the COFF constraint of page-sized and page-aligned
|
||||
sections, the GNU EFI build environment uses the special linker script
|
||||
@ -231,10 +226,12 @@ and page sized.These eight sections are used to group together the much
|
||||
greater number of sections that are typically present in ELF object files.
|
||||
Specifically:
|
||||
|
||||
.text
|
||||
- .text
|
||||
|
||||
Collects all sections containing executable code.
|
||||
|
||||
.data
|
||||
- .data
|
||||
|
||||
Collects read-write data, literal string data,
|
||||
global offset tables, the uninitialized data segment (bss)
|
||||
and various other sections containing data.
|
||||
@ -243,7 +240,8 @@ Specifically:
|
||||
that the EFI loader appears to be unable to handle sections
|
||||
that are allocated but not loaded from the binary.
|
||||
|
||||
.rodata
|
||||
- .rodata
|
||||
|
||||
Collects read-only data to retain the correct memory
|
||||
permissions
|
||||
|
||||
@ -253,14 +251,16 @@ Specifically:
|
||||
EFI binaries execute in physical mode, differences in page
|
||||
protection do not matter.
|
||||
|
||||
.dynamic, .rela, .rel, .reloc, .areloc
|
||||
- .dynamic, .rela, .rel, .reloc, .areloc
|
||||
|
||||
These sections contains the dynamic information necessary to
|
||||
self-relocate the binary (see below).
|
||||
|
||||
|
||||
Unnecessary sections:
|
||||
### Unnecessary sections:
|
||||
|
||||
- .hash (and/or .gnu.hash)
|
||||
|
||||
.hash (and/or .gnu.hash)
|
||||
Collects the ELF .hash info (this section _must_ be the first
|
||||
section in order to build a shared object file; the section is
|
||||
not actually loaded or used at runtime).
|
||||
@ -271,13 +271,14 @@ Unnecessary sections:
|
||||
both. In order to generate correct output linker script preserves
|
||||
both types of hash sections.
|
||||
|
||||
.dynsym, .symtab
|
||||
- .dynsym, .symtab
|
||||
|
||||
The symbol tables used for ELF debugging
|
||||
|
||||
|
||||
A couple of more points worth noting about the linker script:
|
||||
|
||||
o On IA-64, the global pointer symbol (__gp) needs to be placed such
|
||||
- On IA-64, the global pointer symbol (__gp) needs to be placed such
|
||||
that the _entire_ EFI binary can be addressed using the signed
|
||||
22-bit offset that the "addl" instruction affords. Specifically,
|
||||
this means that __gp should be placed at ImageBase + 0x200000.
|
||||
@ -287,17 +288,17 @@ A couple of more points worth noting about the linker script:
|
||||
to be addressable in this fashion, grep the assembly files in
|
||||
directory gnuefi for the string "@gprel".
|
||||
|
||||
o The link address (ImageBase) of the binary is (arbitrarily) set to
|
||||
- The link address (ImageBase) of the binary is (arbitrarily) set to
|
||||
zero. This could be set to something larger to increase the chance
|
||||
of EFI being able to load the binary without requiring relocation.
|
||||
However, a start address of 0 makes debugging a wee bit easier
|
||||
(great for those of us who can add, but not subtract... ;-).
|
||||
|
||||
o The relocation related sections (.dynamic, .rel, .rela, .reloc)
|
||||
- The relocation related sections (.dynamic, .rel, .rela, .reloc)
|
||||
cannot be placed inside .data because some tools in the GNU
|
||||
toolchain rely on the existence of these sections.
|
||||
|
||||
o Some sections in the ELF binary intentionally get dropped when
|
||||
- Some sections in the ELF binary intentionally get dropped when
|
||||
building the EFI binary. Particularly noteworthy are the dynamic
|
||||
relocation sections for the .plabel and .reloc sections. It would
|
||||
be _wrong_ to include these sections in the EFI binary because it
|
||||
@ -308,7 +309,7 @@ A couple of more points worth noting about the linker script:
|
||||
retained in the EFI binary (see Make.rules).
|
||||
|
||||
|
||||
** (2) Building Relocatable Binaries
|
||||
## (2) Building Relocatable Binaries
|
||||
|
||||
ELF binaries are normally linked for a fixed load address and are thus
|
||||
not relocatable. The only kind of ELF object that is relocatable are
|
||||
@ -320,13 +321,13 @@ normally require relocation of the global offset table.
|
||||
The approach to building relocatable binaries in the GNU EFI build
|
||||
environment is to:
|
||||
|
||||
(a) build an ELF shared object
|
||||
1. build an ELF shared object
|
||||
|
||||
(b) link it together with a self-relocator that takes care of
|
||||
2. link it together with a self-relocator that takes care of
|
||||
applying the dynamic relocations that may be present in the
|
||||
ELF shared object
|
||||
|
||||
(c) convert the resulting image to an EFI binary
|
||||
3. convert the resulting image to an EFI binary
|
||||
|
||||
The self-relocator is of course architecture dependent. The x86
|
||||
version can be found in gnuefi/reloc_ia32.c, the x86_64 version
|
||||
@ -361,12 +362,12 @@ and the application recompiled. An easy way to count the number of
|
||||
function descriptors required by an EFI application is to run the
|
||||
command:
|
||||
|
||||
objdump --dynamic-reloc example.so | fgrep FPTR64 | wc -l
|
||||
`objdump --dynamic-reloc example.so | fgrep FPTR64 | wc -l`
|
||||
|
||||
assuming "example" is the name of the desired EFI application.
|
||||
|
||||
|
||||
** (3) Creating the Function Descriptor for the IA-64 EFI Binaries
|
||||
## (3) Creating the Function Descriptor for the IA-64 EFI Binaries
|
||||
|
||||
As mentioned above, the IA-64 PE32+ format assumes that the entry
|
||||
point of the binary is a function descriptor. A function descriptors
|
||||
@ -401,7 +402,7 @@ its own section so that the objcopy program can recognize it and can
|
||||
create the correct directory entries in the PE32+ binary.
|
||||
|
||||
|
||||
** (4) Convenient and Portable Generation of UNICODE String Literals
|
||||
## (4) Convenient and Portable Generation of UNICODE String Literals
|
||||
|
||||
From gnu-efi-3.0, we made use (and somewhat abused) the gcc option
|
||||
that forces wide characters (WCHAR_T) to use short integers (2 bytes)
|
||||
@ -416,4 +417,4 @@ The gcc option to force short wide characters is : -fshort-wchar
|
||||
We have since defined CHAR16 to be char16_t which allows us to use the C11
|
||||
'u' string literals instead hence avoiding abuse of short wide characters
|
||||
|
||||
* * * The End * * *
|
||||
***The End***
|
||||
|
Loading…
Reference in New Issue
Block a user