summaryrefslogtreecommitdiffstats
path: root/documentation/GNU-efi
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/GNU-efi')
-rw-r--r--documentation/GNU-efi299
1 files changed, 299 insertions, 0 deletions
diff --git a/documentation/GNU-efi b/documentation/GNU-efi
new file mode 100644
index 0000000..40cd91f
--- /dev/null
+++ b/documentation/GNU-efi
@@ -0,0 +1,299 @@
+##################################################################################
+## ##
+## BUILDING HELLOWORLD.EFI WIH GNU-EFI ##
+## ##
+##################################################################################
+
+#################################################################################
+# SUMMARY #
+#################################################################################
+
+Minimal working example:
+
+ hello.c
+---------------------------------------------------------------------------------
+#include <efi.h>
+#include <efilib.h>
+
+EFI_STATUS
+EFIAPI
+efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
+
+ InitializeLib(ImageHandle, SystemTable);
+ Print(L"Hello, world!\n");
+
+ return EFI_SUCCESS;
+}
+
+
+Makefile
+--------------------------------------------------------------------------------
+ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
+
+OBJS = hello.o
+TARGET = hello.efi
+
+EFIINC = /usr/include/efi
+EFFINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
+EFILIB = /usr/lib
+EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(ARCH).o
+EFI_LDS = $(EFILIB)/elf_$(ARCH)_efi.lds
+
+CFLAGS = $(EFFINCS) -fno-stack-protector -fpic \
+ -fshort-wchar -mno-red-zone -Wall
+
+ifeq ($(ARCH),x86_64)
+ CFLAGS += -DEFI_FUNCTION_WRAPPER
+endif
+
+LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \
+ -Bsymbolic -L $(EFILIB) $(EFI_CRT_OBJS)
+
+all: $(TARGET)
+
+hello.so: $(OBJS)
+ ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi
+
+%.efi: %.so
+ objcopy -j .text -j .sdata -j .data -j .dynamic \
+ -j .dynsym -j .rel -j .rela -j .reloc \
+ --target=efi-app-$(ARCH) $^ $@
+
+-----
+Now expanded version in git
+
+Get ImageBase:
+ Run ./test.sh and then hello.efi...this prints ImageBase
+
+Get Offsets:
+ GDB
+ file hello.efi
+ -> get text and data offset
+ file
+ add-symbol-file hello.efi (ImageBase+text-off) -s .data (ImageBase+data-off)
+
+
+#################################################################################
+# https://wiki.osdev.org/GNU-EFI #
+#################################################################################
+
+GNU-EFI is a very lightweight developing environment to create UEFI applications.
+It is a set of libraries and headers for compiling UEFI applications with a
+system's native GCC.
+
+You can use host native compiler, then convert resulting ELF into UEFI-compatible
+PE.
+ OR
+Use GCC Cross-Compiler generating PE directly.
+
+*********************************************************************************
+* $ git clone https://git.code.sf.net/p/gnu-efi/code gnu-efi *
+* $ cd gnu-efi *
+* $ make *
+*********************************************************************************
+
+This should create
+* crt0-efi-x86_64.o:
+ A CRT0 (C runtime initialization code) that will call the
+ "efi_main" function
+
+* libgnuefi.a:
+ A library containing a single function (_relocate)
+ that is used by the CRT0
+
+* (optional) libefi.a:
+ A library containing convenience functions like CRC computation, string
+ length calculation, and easy text printing
+
+HEADERS can be used from:
+* /usr/include/efi (updated to the latest)
+* from EDK2 package
+* Or from gnu-efi/inc
+
+LINKER SCRIPT:
+* gnu-efi/gnuefi/elf_x86_64_efi.lds
+ OR
+* /usr/lib/elf_x86_64_efi.lds
+
+COMPILATION:
+$ gcc
+ -Ignu-efi-dir/inc || set this to the efi headers directory
+
+ -fpic || UEFI PE executable must be relocatable
+
+ -ffreestanding || there's no hosted gcc environment,
+ we don't have libc
+ -fno-stack-protector =
+ -fno-stack-check || stack must be strictly used,
+ || no additional canaries or
+ || pre-allocated local variable
+ || space allowed
+ -mno-red-zone =
+
+ -fshort-wchar || It is very important that UEFI
+ || uses 16bit characters
+ || (wide-characters or wchar_t,
+ || defined as CHAR16 in efi headers
+
+ -maccumulate-outgoing-args || function calls must include the
+ || number of argumnets passed to the
+ || functions
+
+ -c main.c -o main.o
+
+LINKING:
+$ ld -shared -Bsymbolic -Lgnu-efi-dir/x86_64/lib -Lgnu-efi-dir/x86_64/gnuefi \
+ -Tgnu-efi-dir/gnuefi/elf_x86_64_efi.lds \
+ gnu-efi-dir/x86_64/gnuefi/crt0-efi-x86_64.o \
+ main.o -o main.so -lgnuefi -lefi
+
+ -shared -Bsymbolic || tell GNU ld to create so (shared library)
+
+ -L and -T || Where to find the static GNU-EFI libraries
+ || (.a) and the linker script
+
+ .o || it is important to specify crt0 as the
+ || first. Should work as the last too, but
+ || some had problems
+
+ -l || linking with gnuefi is a must, as that
+ || contains the relocation code. Linking
+ || with efi is optional, but recommended
+
+CONVERT CHARED OBJECT TO EFI EXECUTABLE
+$ objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.*
+ -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 main.so main.efi
+
+ -j || which sections to keep during convertion
+
+ --target efi-app-x86_64 || tells objcop to generate a PE32+ format,
+ || with architecture code 0x8664
+
+ --subsystem=10: || most important. Sets file type to UEFI
+ || executable in the PE header
+
+Now you can copy main.efi to your EFI System Partition, and after boot run it
+from the EFI Shell. Or you can rename it to EFI\BOOT\BOOTX64.EFI and it should
+be executed automatically on boot.
+
+
+LIBEFI.A
+
+Has wrappers for the most common UEFI functions, but you might need to call
+something not covered. For completeness, it provides:
+
+uefi_call_wrapper(func, numarg, ...);
+
+For example, the "Print" function used in our main.c and which accepts printf
+compatible arguments, is under the hood nothing else than a call to:
+
+uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, buffer);
+
+The biggest advantage of 'uefi_call_wrapper_ is that doesn't matter what ABI
+your gcc is using, it will always correctly translate thet into UEFI ABI. If,
+and only if you've used the correct gcc options, then you should be able to
+make the same call as:
+
+ST->ConOut->OutputString(ST->ConOut, buffer);
+
+
+#################################################################################
+# https://wiki.osdev.org/Debugging_UEFI_applications_with_GDB #
+#################################################################################
+
+Makefile at:
+https://sourceforge.net/p/ast-phoenix/code/ci/master/tree/kernel/boot/Makefile#l72
+
+EFI firmware is unable to launch binaries with debug sections. What you need is
+to create two EFI binaries - one with only required sections to upload it to
+target system and another one with debug symbols to use with GDB. Actually you
+just need to run objcopy utility twice with different set of sections to copy and
+different output files. (See Makefile example)
+
+To load image with symbols to relocated addresses for .text and .data sections,
+you need to add ImageBase address to their offsets:
+
+*********************************************************************************
+* # gdb hello.efi *
+* (gdb) info files *
+* ... *
+* Entry point: 0x3000 *
+* 3000 - ... is .text *
+* c00 - ... is .data *
+* (gdb) file || unload file *
+* add-symbol-file hello.efi (ImageBase+text-off) -s .data (ImageBase+data-off) *
+*********************************************************************************
+
+#################################################################################
+# https://www.rodsbooks.com/efi-programming/hello.html #
+#################################################################################
+
+You should not normally include regular C header files, such as stdlib.h,
+because most of these header files define data types and functions that are used
+by the C library. This library is not available in EFI.
+
+************************************
+* efi.h and efilib.h always needed *
+************************************
+
+Entry point: efi_main() in GNU-efi
+
+CFLAGS:
+* -fno-stack-protector:
+ Stack protection isn't suppoerted by EFI, so there's no point in
+ building a binary with this feature active.
+
+* -fpic:
+ EFI requires that code be position-independet, hence the use
+ of this option.
+
+* -fshort-wchar:
+ GCC defines the wchar_t type to be 32 bits by default, but EFI requires
+ it to be 16 bits for 16-bit strings to work correctly.
+
+* fmno-red-zone:
+ On x86-64 systems, the red zone is an area that follows the stack pointer
+ that can be used for temporary variables. The EFI may modify this area,
+ though, so it's not safe to use, and you must compile EFI binaries with
+ this option.
+
+* -Wall:
+ When developing EFI applications, you might want to pay extra attention to
+ compiler warnings, and this switch (which causes warnings to be treated as
+ errors) can help.
+
+* -DEFI_FUNCTION_WRAPPER:
+ This option is required on the x86_64 platform, but is not defined on the
+ 32-bit x86 platform. It relates to th calling conventions for EFI functions,
+ described on the Using EFI Services page.
+
+LDFLAGS:
+* -nostdlib:
+ An EFI application should not be linked against standard libraries, and this
+ argument accomplishes this goal.
+
+* -nocombreloc:
+ This argument causes the linker to not combine relocation sections.
+
+* -T $(EFI_LDS):
+ To create an EFI binary, a non-standard linker script must be used, and this
+ option tells ld where to find it.
+
+* -shared:
+ Even with GNU-EFI's new linker script, ld can't create the final executable.
+ Instead, it creates a shared library, which is subsequently
+ turned into the final binary.
+
+* -Bsymbolic:
+ This option causes references to global symbols to be bound to the
+ definitions within the shared library.
+
+
+
+
+
+
+
+
+
+