[U-Boot] [PATCH v4 00/14] efi: x86: Add EFI hello world and loader support for x86

This series adds EFI loader support for x86. Since U-Boot already supports running as an EFI app (and as a payload) this is relatively straightforward, requiring just moving files into place and updating a few compiler flags.
One problem with the EFI loader is that it lacks even rudimentary test support within U-Boot. At present the only way to test it is to boot an EFI application. As a step towards correcting this, this series also adds support for a 'hello world' test program which can be used to make sure that EFI loader support works correctly on a supported architecture. It is only a very simple program (it makes just two API calls!) but it does provide a sanity check and can be expanded as needed.
No attempt is made to create a pytest with this, but it should be fairly straightforward to do so.
Changes in v4: - Move hello world test program into new patch - Add new patch to add EFI app support - Add new patch to add EFI app support on aarch64 - Use the build-generated 'hello world' program instead of a binary blob - Add new patch to adjust EFI files support efi_loader - Drop the binary 'hello world' program
Changes in v3: - Include a link to the program instead of adding it to the tree - Fix several typos - Align backslashes to the same column
Changes in v2: - Add new patch to tidy up selection of building the EFI stub - Remove EFI support from README.x86 TODO list
Simon Glass (14): x86: Correct a build warning in x86 tables efi: Correct cache flush alignment efi: Fix debug message address format x86: Tidy up selection of building the EFI stub efi: Makefile: Export variables for use with EFI efi: Add support for a hello world test program elf: arm: Add a few ARM relocation types efi: arm: Add EFI app support efi: arm: Add aarch64 EFI app support efi: arm: Enable the hello world test program x86: Move efi .lds files into the 'lib' directory x86: Move efi .S files into the 'lib' directory efi: x86: Adjust EFI files support efi_loader x86: Enable EFI loader support
Makefile | 11 +- arch/arm/config.mk | 7 ++ arch/arm/cpu/armv8/config.mk | 4 + arch/arm/lib/Makefile | 10 ++ arch/arm/lib/crt0_aarch64_efi.S | 135 ++++++++++++++++++++ arch/arm/lib/crt0_arm_efi.S | 138 +++++++++++++++++++++ arch/arm/lib/elf_aarch64_efi.lds | 70 +++++++++++ arch/arm/lib/elf_arm_efi.lds | 70 +++++++++++ arch/arm/lib/reloc_aarch64_efi.c | 87 +++++++++++++ arch/arm/lib/reloc_arm_efi.c | 66 ++++++++++ arch/arm/lib/relocate.S | 3 +- arch/arm/lib/relocate_64.S | 3 +- arch/x86/config.mk | 20 ++- arch/x86/lib/Makefile | 23 ++++ .../lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} | 0 .../{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} | 0 arch/x86/lib/efi/Makefile | 18 --- arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds | 2 - arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds | 2 - .../x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} | 0 .../lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} | 0 arch/x86/lib/tables.c | 2 + cmd/Kconfig | 10 ++ cmd/bootefi.c | 29 +++-- configs/efi-x86_defconfig | 1 + configs/qemu-x86_efi_payload64_defconfig | 1 + configs/stm32f429-discovery_defconfig | 1 + doc/README.efi | 22 ++++ doc/README.x86 | 1 - include/asm-generic/sections.h | 2 + include/efi.h | 7 +- include/elf.h | 13 ++ lib/efi/Makefile | 4 +- lib/efi_loader/Kconfig | 2 +- lib/efi_loader/Makefile | 4 + lib/efi_loader/efi_image_loader.c | 3 +- lib/efi_loader/helloworld.c | 24 ++++ scripts/Makefile.lib | 33 +++++ 38 files changed, 787 insertions(+), 41 deletions(-) create mode 100644 arch/arm/lib/crt0_aarch64_efi.S create mode 100644 arch/arm/lib/crt0_arm_efi.S create mode 100644 arch/arm/lib/elf_aarch64_efi.lds create mode 100644 arch/arm/lib/elf_arm_efi.lds create mode 100644 arch/arm/lib/reloc_aarch64_efi.c create mode 100644 arch/arm/lib/reloc_arm_efi.c rename arch/x86/lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} (100%) rename arch/x86/lib/{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} (100%) rename arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds (98%) rename arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds (98%) rename arch/x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} (100%) rename arch/x86/lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} (100%) create mode 100644 lib/efi_loader/helloworld.c

There is a build warning for three x86 boards since write_smbios_table_wrapper() is not used. Fix it.
Fixes: e824cf3f (smbios: Allow compilation on 64bit systems) Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
arch/x86/lib/tables.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 025b183..5966e58 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -12,10 +12,12 @@ #include <asm/acpi_table.h> #include <asm/coreboot_tables.h>
+#ifdef CONFIG_GENERATE_SMBIOS_TABLE static u32 write_smbios_table_wrapper(u32 addr) { return write_smbios_table(addr); } +#endif
/** * Function prototype to write a specific configuration table

There is a build warning for three x86 boards since write_smbios_table_wrapper() is not used. Fix it.
Fixes: e824cf3f (smbios: Allow compilation on 64bit systems) Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

Make sure that the cache flushes correctly by ensuring that the end address is correctly aligned.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
lib/efi_loader/efi_image_loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 5165377..3262d76 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -174,7 +174,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) efi_loader_relocate(rel, rel_size, efi_reloc);
/* Flush cache */ - flush_cache((ulong)efi_reloc, virt_size); + flush_cache((ulong)efi_reloc, + ALIGN(virt_size, CONFIG_SYS_CACHELINE_SIZE)); invalidate_icache_all();
/* Populate the loaded image interface bits */

Make sure that the cache flushes correctly by ensuring that the end address is correctly aligned.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

This should use U-Boot's standard format for hex address. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
cmd/bootefi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index c8079c4..3ab256e 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -248,7 +248,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) fdt_addr = simple_strtoul(sfdt, NULL, 16); }
- printf("## Starting EFI application at 0x%08lx ...\n", addr); + printf("## Starting EFI application at %08lx ...\n", addr); r = do_bootefi_exec((void *)addr, (void*)fdt_addr); printf("## Application terminated, r = %d\n", r);

This should use U-Boot's standard format for hex address. Fix it.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

At present we use a CONFIG option in efi.h to determine whether we are building the EFI stub or not. This means that the same header cannot be used for EFI_LOADER support. The CONFIG option will be enabled for the whole build, even when not building the stub.
Use a different define instead, set up just for the files that make up the stub.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v4: None Changes in v3: None Changes in v2: - Add new patch to tidy up selection of building the EFI stub
include/efi.h | 7 +++++-- lib/efi/Makefile | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/include/efi.h b/include/efi.h index d07187c..3d58780 100644 --- a/include/efi.h +++ b/include/efi.h @@ -30,8 +30,11 @@ struct efi_device_path;
#define EFI_BITS_PER_LONG BITS_PER_LONG
-/* With 64-bit EFI stub, EFI_BITS_PER_LONG has to be 64 */ -#ifdef CONFIG_EFI_STUB_64BIT +/* + * With 64-bit EFI stub, EFI_BITS_PER_LONG has to be 64. EFI_STUB is set + * in lib/efi/Makefile, when building the stub. + */ +#if defined(CONFIG_EFI_STUB_64BIT) && defined(EFI_STUB) #undef EFI_BITS_PER_LONG #define EFI_BITS_PER_LONG 64 #endif diff --git a/lib/efi/Makefile b/lib/efi/Makefile index e32dc14..9449600 100644 --- a/lib/efi/Makefile +++ b/lib/efi/Makefile @@ -9,9 +9,9 @@ obj-$(CONFIG_EFI_STUB) += efi_info.o
CFLAGS_REMOVE_efi_stub.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) -CFLAGS_efi_stub.o := -fpic -fshort-wchar +CFLAGS_efi_stub.o := -fpic -fshort-wchar -DEFI_STUB CFLAGS_REMOVE_efi.o := -mregparm=3 \ $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) -CFLAGS_efi.o := -fpic -fshort-wchar +CFLAGS_efi.o := -fpic -fshort-wchar -DEFI_STUB
extra-$(CONFIG_EFI_STUB) += efi_stub.o efi.o

At present we use a CONFIG option in efi.h to determine whether we are building the EFI stub or not. This means that the same header cannot be used for EFI_LOADER support. The CONFIG option will be enabled for the whole build, even when not building the stub.
Use a different define instead, set up just for the files that make up the stub.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Thanks, applied to efi-next
Alex

When building an EFI app we need three things:
- start-up code - relocation code - link script
These are all different for each architecture. We also need special compiler flags in some cases.
Add top-level Makefile variables for these along with documentation.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
Makefile | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/Makefile b/Makefile index 37cbcb2..d3a6a12 100644 --- a/Makefile +++ b/Makefile @@ -527,6 +527,15 @@ endif endif endif
+# These are set by the arch-specific config.mk. Make sure they are exported +# so they can be used when building an EFI application. +export EFI_LDS # Filename of EFI link script in arch/$(ARCH)/lib +export EFI_CRT0 # Filename of EFI CRT0 in arch/$(ARCH)/lib +export EFI_RELOC # Filename of EFU relocation code in arch/$(ARCH)/lib +export CFLAGS_EFI # Compiler flags to add when building EFI app +export CFLAGS_NON_EFI # Compiler flags to remove when building EFI app +export EFI_TARGET # binutils target if EFI is natively supported + # If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use # that (or fail if absent). Otherwise, search for a linker script in a # standard location.

When building an EFI app we need three things:
- start-up code
- relocation code
- link script
These are all different for each architecture. We also need special compiler flags in some cases.
Add top-level Makefile variables for these along with documentation.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

It is useful to have a basic sanity check for EFI loader support. Add a 'bootefi hello' command which loads HelloWord.efi and runs it under U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Move hello world test program into new patch
Changes in v3: None Changes in v2: None
cmd/Kconfig | 9 +++++++++ cmd/bootefi.c | 27 +++++++++++++++++++++------ doc/README.efi | 22 ++++++++++++++++++++++ include/asm-generic/sections.h | 2 ++ lib/efi_loader/Makefile | 4 ++++ lib/efi_loader/helloworld.c | 24 ++++++++++++++++++++++++ scripts/Makefile.lib | 33 +++++++++++++++++++++++++++++++++ 7 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 lib/efi_loader/helloworld.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index e339d86..a5d030b 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -181,6 +181,15 @@ config CMD_BOOTEFI help Boot an EFI image from memory.
+config CMD_BOOTEFI_HELLO + bool "Allow booting a standard EFI hello world for testing" + depends on CMD_BOOTEFI + help + This adds a standard EFI hello world application to U-Boot so that + it can be used with the 'bootefi hello' command. This is useful + for testing that EFI is working at a basic level, and for bringing + up EFI support on a new architecture. + config CMD_ELF bool "bootelf, bootvx" default y diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3ab256e..ae1b713 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -239,13 +239,23 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc < 2) return CMD_RET_USAGE; - saddr = argv[1]; +#ifdef CONFIG_CMD_BOOTEFI_HELLO + if (!strcmp(argv[1], "hello")) { + ulong size = __efi_hello_world_end - __efi_hello_world_begin;
- addr = simple_strtoul(saddr, NULL, 16); + addr = CONFIG_SYS_LOAD_ADDR; + memcpy((char *)addr, __efi_hello_world_begin, size); + } else +#endif + { + saddr = argv[1];
- if (argc > 2) { - sfdt = argv[2]; - fdt_addr = simple_strtoul(sfdt, NULL, 16); + addr = simple_strtoul(saddr, NULL, 16); + + if (argc > 2) { + sfdt = argv[2]; + fdt_addr = simple_strtoul(sfdt, NULL, 16); + } }
printf("## Starting EFI application at %08lx ...\n", addr); @@ -263,7 +273,12 @@ static char bootefi_help_text[] = "<image address> [fdt address]\n" " - boot EFI payload stored at address <image address>.\n" " If specified, the device tree located at <fdt address> gets\n" - " exposed as EFI configuration table.\n"; + " exposed as EFI configuration table.\n" +#ifdef CONFIG_CMD_BOOTEFI_HELLO + "hello\n" + " - boot a sample Hello World application stored within U-Boot" +#endif + ; #endif
U_BOOT_CMD( diff --git a/doc/README.efi b/doc/README.efi index 1fd3f00..6e76310 100644 --- a/doc/README.efi +++ b/doc/README.efi @@ -310,6 +310,28 @@ Removable media booting (search for /efi/boot/boota{a64,arm}.efi) is supported. Simple use cases like "Plug this SD card into my ARM device and it just boots into grub which boots into Linux", work very well.
+ +Running HelloWord.efi +--------------------- + +You can run a simple 'hello world' EFI program in U-Boot. This is not +distributed in the U-Boot source, but you can download this patch: + + https://goo.gl/vihiZS + +Then apply it, e.g.: + + $ git am ~/Downloads/0001-efi-Add-test-program-binaries.patch + +and enable the option CONFIG_CMD_BOOTEFI_HELLO + +Then you can boot into U-Boot and type: + + > bootefi hello + +The 'hello world EFI' program will then run, print a message and exit. + + Future work -----------
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index d69bc60..daf021b 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -22,6 +22,8 @@ extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __entry_text_start[], __entry_text_end[]; extern char __initdata_begin[], __initdata_end[]; extern char __start_rodata[], __end_rodata[]; +extern char __efi_hello_world_begin[]; +extern char __efi_hello_world_end[];
/* Start and end of .ctors section - used for constructor calls. */ extern char __ctors_start[], __ctors_end[]; diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 12159dd..f466408 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -7,6 +7,10 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it
+CFLAGS_helloworld.o := $(CFLAGS_EFI) +CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) + +obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o obj-$(CONFIG_LCD) += efi_gop.o diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c new file mode 100644 index 0000000..03e65ab --- /dev/null +++ b/lib/efi_loader/helloworld.c @@ -0,0 +1,24 @@ +/* + * EFI hello world + * + * Copyright (c) 2016 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <part_efi.h> +#include <efi_api.h> + +efi_status_t EFIAPI efi_main(efi_handle_t handle, + struct efi_system_table *systable) +{ + struct efi_simple_text_output_protocol *con_out = systable->con_out; + struct efi_boot_services *boottime = systable->boottime; + + con_out->output_string(con_out, L"Hello, world!\n"); + boottime->exit(handle, 0, 0, NULL); + + return EFI_SUCCESS; +} diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 45a0e1d..956a8a9 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -321,6 +321,39 @@ cmd_S_ttf= \ $(obj)/%.S: $(src)/%.ttf $(call cmd,S_ttf)
+# EFI Hello World application +# --------------------------------------------------------------------------- + +# Generate an assembly file to wrap the EFI app +cmd_S_efi= \ +( \ + echo '.section .rodata.efi.init,"a"'; \ + echo '.balign 16'; \ + echo '.global __efi_hello_world_begin'; \ + echo '__efi_hello_world_begin:'; \ + echo '.incbin "$<" '; \ + echo '__efi_hello_world_end:'; \ + echo '.global __efi_hello_world_end'; \ + echo '.balign 16'; \ +) > $@ + +$(obj)/%_efi.S: $(obj)/%.efi + $(call cmd,S_efi) + +$(obj)/%.efi: $(obj)/%.so + $(OBJCOPY) -j .header -j .text -j .sdata -j .data -j .dynamic \ + -j .dynsym -j .rel* -j .rela* -j .reloc \ + $(if $(EFI_TARGET),$(EFI_TARGET),-O binary) $^ $@ + +EFI_LDS_PATH = $(srctree)/arch/$(ARCH)/lib/$(EFI_LDS) + +$(obj)/helloworld.so: $(EFI_LDS_PATH) + +$(obj)/helloworld.so: $(obj)/helloworld.o arch/$(ARCH)/lib/$(EFI_CRT0) \ + arch/$(ARCH)/lib/$(EFI_RELOC) + $(LD) -nostdlib -znocombreloc -T $(EFI_LDS_PATH) -shared -Bsymbolic \ + $^ -o $@ + # ACPI # --------------------------------------------------------------------------- quiet_cmd_acpi_c_asl= ASL $<

It is useful to have a basic sanity check for EFI loader support. Add a 'bootefi hello' command which loads HelloWord.efi and runs it under U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

Rather than hard-coding the relocation type, add it to the ELF header file and use it from there.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
arch/arm/lib/relocate.S | 3 ++- arch/arm/lib/relocate_64.S | 3 ++- include/elf.h | 13 +++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S index 475d503..a6fb07c 100644 --- a/arch/arm/lib/relocate.S +++ b/arch/arm/lib/relocate.S @@ -8,6 +8,7 @@
#include <asm-offsets.h> #include <config.h> +#include <elf.h> #include <linux/linkage.h> #ifdef CONFIG_CPU_V7M #include <asm/armv7m.h> @@ -96,7 +97,7 @@ copy_loop: fixloop: ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ and r1, r1, #0xff - cmp r1, #23 /* relative fixup? */ + cmp r1, #R_ARM_RELATIVE bne fixnext
/* relative fix: increase location by offset */ diff --git a/arch/arm/lib/relocate_64.S b/arch/arm/lib/relocate_64.S index 5c51cae..242e56e 100644 --- a/arch/arm/lib/relocate_64.S +++ b/arch/arm/lib/relocate_64.S @@ -10,6 +10,7 @@
#include <asm-offsets.h> #include <config.h> +#include <elf.h> #include <linux/linkage.h> #include <asm/macro.h>
@@ -47,7 +48,7 @@ fixloop: ldp x0, x1, [x2], #16 /* (x0,x1) <- (SRC location, fixup) */ ldr x4, [x2], #8 /* x4 <- addend */ and x1, x1, #0xffffffff - cmp x1, #1027 /* relative fixup? */ + cmp x1, #R_AARCH64_RELATIVE bne fixnext
/* relative fix: store addend plus offset at dest location */ diff --git a/include/elf.h b/include/elf.h index bcc5eb7..aaecac7 100644 --- a/include/elf.h +++ b/include/elf.h @@ -13,6 +13,7 @@ #ifndef _ELF_H #define _ELF_H
+#ifndef __ASSEMBLER__ #include "compiler.h"
/* @@ -517,6 +518,8 @@ unsigned long elf_hash(const unsigned char *name);
#define ELF_TARG_VER 1 /* The ver for which this code is intended */
+#endif /* __ASSEMBLER */ + /* * XXX - PowerPC defines really don't belong in here, * but we'll put them in for simplicity. @@ -602,6 +605,16 @@ unsigned long elf_hash(const unsigned char *name); that may still be in object files. */ #define R_PPC_TOC16 255
+ /* ARM relocs */ +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ + +/* AArch64 relocs */ +#define R_AARCH64_NONE 0 /* No relocation. */ +#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ + +#ifndef __ASSEMBLER__ int valid_elf_image(unsigned long addr); +#endif
#endif /* _ELF_H */

Rather than hard-coding the relocation type, add it to the ELF header file and use it from there.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

Add support for EFI apps on ARM. This includes start-up and relocation code, plus a link script and some compiler setting changes.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Add new patch to add EFI app support
Changes in v3: None Changes in v2: None
arch/arm/config.mk | 7 +++ arch/arm/lib/Makefile | 10 ++++ arch/arm/lib/crt0_arm_efi.S | 138 +++++++++++++++++++++++++++++++++++++++++++ arch/arm/lib/elf_arm_efi.lds | 70 ++++++++++++++++++++++ arch/arm/lib/reloc_arm_efi.c | 66 +++++++++++++++++++++ lib/efi_loader/Kconfig | 2 +- 6 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 arch/arm/lib/crt0_arm_efi.S create mode 100644 arch/arm/lib/elf_arm_efi.lds create mode 100644 arch/arm/lib/reloc_arm_efi.c
diff --git a/arch/arm/config.mk b/arch/arm/config.mk index 542b897..27914a9 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -13,6 +13,9 @@ CONFIG_STANDALONE_LOAD_ADDR = 0xc100000 endif endif
+CFLAGS_NON_EFI := -fno-pic -ffixed-r9 -ffunction-sections -fdata-sections +CFLAGS_EFI := -fpic -fshort-wchar + LDFLAGS_FINAL += --gc-sections PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \ -fno-common -ffixed-r9 @@ -148,3 +151,7 @@ ifneq ($(CONFIG_VF610),) ALL-y += u-boot.vyb endif endif + +EFI_LDS := elf_arm_efi.lds +EFI_CRT0 := crt0_arm_efi.o +EFI_RELOC := reloc_arm_efi.o diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index caa62c6..a812306 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -92,3 +92,13 @@ AFLAGS_memset.o := -DMEMSET_NO_THUMB_BUILD AFLAGS_memcpy.o := -DMEMCPY_NO_THUMB_BUILD endif endif + +# For building EFI apps +CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) +CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI) + +CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI) +CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI) + +extra-$(CONFIG_CMD_BOOTEFI_HELLO) += $(EFI_CRT0) $(EFI_RELOC) +extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC) diff --git a/arch/arm/lib/crt0_arm_efi.S b/arch/arm/lib/crt0_arm_efi.S new file mode 100644 index 0000000..967c885 --- /dev/null +++ b/arch/arm/lib/crt0_arm_efi.S @@ -0,0 +1,138 @@ +/* + * crt0-efi-arm.S - PE/COFF header for ARM EFI applications + * + * Copright (C) 2014 Linaro Ltd. ard.biesheuvel@linaro.org + * + * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause + * + * This file is taken and modified from the gnu-efi project. + */ + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl image_base +image_base: + .ascii "MZ" + .skip 58 /* 'MZ' + pad + offset == 64 */ + .long pe_header - image_base /* Offset to the PE header */ +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0x1c2 /* Mixed ARM/Thumb */ + .short 2 /* nr_sections */ + .long 0 /* TimeDateStamp */ + .long 0 /* PointerToSymbolTable */ + .long 1 /* NumberOfSymbols */ + .short section_table - optional_header /* SizeOfOptionalHeader */ + /* + * Characteristics: IMAGE_FILE_32BIT_MACHINE | + * IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | + * IMAGE_FILE_LINE_NUMS_STRIPPED + */ + .short 0x306 +optional_header: + .short 0x10b /* PE32+ format */ + .byte 0x02 /* MajorLinkerVersion */ + .byte 0x14 /* MinorLinkerVersion */ + .long _edata - _start /* SizeOfCode */ + .long 0 /* SizeOfInitializedData */ + .long 0 /* SizeOfUninitializedData */ + .long _start - image_base /* AddressOfEntryPoint */ + .long _start - image_base /* BaseOfCode */ + .long 0 /* BaseOfData */ + +extra_header_fields: + .long 0 /* image_base */ + .long 0x20 /* SectionAlignment */ + .long 0x8 /* FileAlignment */ + .short 0 /* MajorOperatingSystemVersion */ + .short 0 /* MinorOperatingSystemVersion */ + .short 0 /* MajorImageVersion */ + .short 0 /* MinorImageVersion */ + .short 0 /* MajorSubsystemVersion */ + .short 0 /* MinorSubsystemVersion */ + .long 0 /* Win32VersionValue */ + + .long _edata - image_base /* SizeOfImage */ + + /* + * Everything before the kernel image is considered part of the header + */ + .long _start - image_base /* SizeOfHeaders */ + .long 0 /* CheckSum */ + .short EFI_SUBSYSTEM /* Subsystem */ + .short 0 /* DllCharacteristics */ + .long 0 /* SizeOfStackReserve */ + .long 0 /* SizeOfStackCommit */ + .long 0 /* SizeOfHeapReserve */ + .long 0 /* SizeOfHeapCommit */ + .long 0 /* LoaderFlags */ + .long 0x6 /* NumberOfRvaAndSizes */ + + .quad 0 /* ExportTable */ + .quad 0 /* ImportTable */ + .quad 0 /* ResourceTable */ + .quad 0 /* ExceptionTable */ + .quad 0 /* CertificationTable */ + .quad 0 /* BaseRelocationTable */ + +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long 0 + .long 0 + .long 0 /* SizeOfRawData */ + .long 0 /* PointerToRawData */ + .long 0 /* PointerToRelocations */ + .long 0 /* PointerToLineNumbers */ + .short 0 /* NumberOfRelocations */ + .short 0 /* NumberOfLineNumbers */ + .long 0x42100040 /* Characteristics (section flags) */ + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long _edata - _start /* VirtualSize */ + .long _start - image_base /* VirtualAddress */ + .long _edata - _start /* SizeOfRawData */ + .long _start - image_base /* PointerToRawData */ + + .long 0 /* PointerToRelocations (0 for executables) */ + .long 0 /* PointerToLineNumbers (0 for executables) */ + .short 0 /* NumberOfRelocations (0 for executables) */ + .short 0 /* NumberOfLineNumbers (0 for executables) */ + .long 0xe0500020 /* Characteristics (section flags) */ + +_start: + stmfd sp!, {r0-r2, lr} + + mov r2, r0 + mov r3, r1 + adr r1, .L_DYNAMIC + ldr r0, [r1] + add r1, r0, r1 + adr r0, image_base + bl _relocate + teq r0, #0 + bne 0f + + ldmfd sp, {r0-r1} + bl efi_main + +0: add sp, sp, #12 + ldr pc, [sp], #4 + +.L_DYNAMIC: + .word _DYNAMIC - . diff --git a/arch/arm/lib/elf_arm_efi.lds b/arch/arm/lib/elf_arm_efi.lds new file mode 100644 index 0000000..59f66a1 --- /dev/null +++ b/arch/arm/lib/elf_arm_efi.lds @@ -0,0 +1,70 @@ +/* + * U-Boot ARM EFI linker script + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Modified from elf_arm_efi.lds in gnu-efi + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * The EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + _edata = .; + } + .rel.dyn : { *(.rel.dyn) } + .rel.plt : { *(.rel.plt) } + .rel.got : { *(.rel.got) } + .rel.data : { *(.rel.data) *(.rel.data*) } + _data_size = . - _etext; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/arch/arm/lib/reloc_arm_efi.c b/arch/arm/lib/reloc_arm_efi.c new file mode 100644 index 0000000..d2f96ee --- /dev/null +++ b/arch/arm/lib/reloc_arm_efi.c @@ -0,0 +1,66 @@ +/* + * reloc_arm.c - position-independent ARM ELF shared object relocator + * + * Copyright (C) 2014 Linaro Ltd. ard.biesheuvel@linaro.org + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger davidm@hpl.hp.com. + * + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * This file is taken and modified from the gnu-efi project. + */ + +#include <efi.h> +#include <elf.h> + +efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, + struct efi_system_table *systab) +{ + long relsz = 0, relent = 0; + Elf32_Rel *rel = 0; + ulong *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf32_Rel *)((ulong)dyn[i].d_un.d_ptr + + ldbase); + break; + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_NONE: + break; + case R_ARM_RELATIVE: + addr = (ulong *)(ldbase + rel->r_offset); + *addr += ldbase; + break; + default: + break; + } + rel = (Elf32_Rel *)((char *)rel + relent); + relsz -= relent; + } + + return EFI_SUCCESS; +} diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 37a0dd6..48563aa 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,6 +1,6 @@ config EFI_LOADER bool "Support running EFI Applications in U-Boot" - depends on (ARM64 ||Â ARM) && OF_LIBFDT + depends on (ARM64 || ARM) && OF_LIBFDT default y help Select this option if you want to run EFI applications (like grub2)

Add support for EFI apps on ARM. This includes start-up and relocation code, plus a link script and some compiler setting changes.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

Add support for EFI apps on aarch64. This includes start-up and relocation code plus a link script.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Add new patch to add EFI app support on aarch64
Changes in v3: None Changes in v2: None
arch/arm/cpu/armv8/config.mk | 4 ++ arch/arm/lib/crt0_aarch64_efi.S | 135 +++++++++++++++++++++++++++++++++++++++ arch/arm/lib/elf_aarch64_efi.lds | 70 ++++++++++++++++++++ arch/arm/lib/reloc_aarch64_efi.c | 87 +++++++++++++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 arch/arm/lib/crt0_aarch64_efi.S create mode 100644 arch/arm/lib/elf_aarch64_efi.lds create mode 100644 arch/arm/lib/reloc_aarch64_efi.c
diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk index 6850258..27b66d4 100644 --- a/arch/arm/cpu/armv8/config.mk +++ b/arch/arm/cpu/armv8/config.mk @@ -8,3 +8,7 @@ PLATFORM_RELFLAGS += -fno-common -ffixed-x18
PF_NO_UNALIGNED := $(call cc-option, -mstrict-align) PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED) + +EFI_LDS := elf_aarch64_efi.lds +EFI_CRT0 := crt0_aarch64_efi.o +EFI_RELOC := reloc_aarch64_efi.o diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S new file mode 100644 index 0000000..5205646 --- /dev/null +++ b/arch/arm/lib/crt0_aarch64_efi.S @@ -0,0 +1,135 @@ +/* + * crt0-efi-aarch64.S - PE/COFF header for aarch64 EFI applications + * + * Copright (C) 2014 Linaro Ltd. ard.biesheuvel@linaro.org + * + * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause + * + * This file is taken and modified from the gnu-efi project. + */ + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .ascii "MZ" + .skip 58 /* 'MZ' + pad + offset == 64 */ + .long pe_header - ImageBase /* Offset to the PE header */ +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0xaa64 /* AArch64 */ + .short 2 /* nr_sections */ + .long 0 /* TimeDateStamp */ + .long 0 /* PointerToSymbolTable */ + .long 1 /* NumberOfSymbols */ + .short section_table - optional_header /* SizeOfOptionalHeader */ + /* + * Characteristics: IMAGE_FILE_DEBUG_STRIPPED | + * IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED + */ + .short 0x206 +optional_header: + .short 0x20b /* PE32+ format */ + .byte 0x02 /* MajorLinkerVersion */ + .byte 0x14 /* MinorLinkerVersion */ + .long _edata - _start /* SizeOfCode */ + .long 0 /* SizeOfInitializedData */ + .long 0 /* SizeOfUninitializedData */ + .long _start - ImageBase /* AddressOfEntryPoint */ + .long _start - ImageBase /* BaseOfCode */ + +extra_header_fields: + .quad 0 /* ImageBase */ + .long 0x20 /* SectionAlignment */ + .long 0x8 /* FileAlignment */ + .short 0 /* MajorOperatingSystemVersion */ + .short 0 /* MinorOperatingSystemVersion */ + .short 0 /* MajorImageVersion */ + .short 0 /* MinorImageVersion */ + .short 0 /* MajorSubsystemVersion */ + .short 0 /* MinorSubsystemVersion */ + .long 0 /* Win32VersionValue */ + + .long _edata - ImageBase /* SizeOfImage */ + + /* + * Everything before the kernel image is considered part of the header + */ + .long _start - ImageBase /* SizeOfHeaders */ + .long 0 /* CheckSum */ + .short EFI_SUBSYSTEM /* Subsystem */ + .short 0 /* DllCharacteristics */ + .quad 0 /* SizeOfStackReserve */ + .quad 0 /* SizeOfStackCommit */ + .quad 0 /* SizeOfHeapReserve */ + .quad 0 /* SizeOfHeapCommit */ + .long 0 /* LoaderFlags */ + .long 0x6 /* NumberOfRvaAndSizes */ + + .quad 0 /* ExportTable */ + .quad 0 /* ImportTable */ + .quad 0 /* ResourceTable */ + .quad 0 /* ExceptionTable */ + .quad 0 /* CertificationTable */ + .quad 0 /* BaseRelocationTable */ + + /* Section table */ +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long 0 + .long 0 + .long 0 /* SizeOfRawData */ + .long 0 /* PointerToRawData */ + .long 0 /* PointerToRelocations */ + .long 0 /* PointerToLineNumbers */ + .short 0 /* NumberOfRelocations */ + .short 0 /* NumberOfLineNumbers */ + .long 0x42100040 /* Characteristics (section flags) */ + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long _edata - _start /* VirtualSize */ + .long _start - ImageBase /* VirtualAddress */ + .long _edata - _start /* SizeOfRawData */ + .long _start - ImageBase /* PointerToRawData */ + + .long 0 /* PointerToRelocations (0 for executables) */ + .long 0 /* PointerToLineNumbers (0 for executables) */ + .short 0 /* NumberOfRelocations (0 for executables) */ + .short 0 /* NumberOfLineNumbers (0 for executables) */ + .long 0xe0500020 /* Characteristics (section flags) */ + +_start: + stp x29, x30, [sp, #-32]! + mov x29, sp + + stp x0, x1, [sp, #16] + mov x2, x0 + mov x3, x1 + adr x0, ImageBase + adrp x1, _DYNAMIC + add x1, x1, #:lo12:_DYNAMIC + bl _relocate + cbnz x0, 0f + + ldp x0, x1, [sp, #16] + bl efi_main + +0: ldp x29, x30, [sp], #32 + ret diff --git a/arch/arm/lib/elf_aarch64_efi.lds b/arch/arm/lib/elf_aarch64_efi.lds new file mode 100644 index 0000000..47cce1d --- /dev/null +++ b/arch/arm/lib/elf_aarch64_efi.lds @@ -0,0 +1,70 @@ +/* + * U-Boot aarch64 EFI linker script + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Modified from elf_aarch64_efi.lds in gnu-efi + */ + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * The EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + _edata = .; + } + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + .rela.got : { *(.rela.got) } + .rela.data : { *(.rela.data) *(.rela.data*) } + _data_size = . - _etext; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/arch/arm/lib/reloc_aarch64_efi.c b/arch/arm/lib/reloc_aarch64_efi.c new file mode 100644 index 0000000..38c13d3 --- /dev/null +++ b/arch/arm/lib/reloc_aarch64_efi.c @@ -0,0 +1,87 @@ +/* reloc_aarch64.c - position independent x86 ELF shared object relocator + Copyright (C) 2014 Linaro Ltd. ard.biesheuvel@linaro.org + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger davidm@hpl.hp.com. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include <efi.h> + +#include <elf.h> + +efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t image, + struct efi_system_table *systab) +{ + long relsz = 0, relent = 0; + Elf64_Rela *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rela *)((ulong)dyn[i].d_un.d_ptr + ldbase); + break; + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE(rel->r_info)) { + case R_AARCH64_NONE: + break; + case R_AARCH64_RELATIVE: + addr = (ulong *)(ldbase + rel->r_offset); + *addr = ldbase + rel->r_addend; + break; + default: + break; + } + rel = (Elf64_Rela *)((char *)rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +}

Add support for EFI apps on aarch64. This includes start-up and relocation code plus a link script.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

It is useful to have a basic sanity check for EFI loader support. Enable this for ARM.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Use the build-generated 'hello world' program instead of a binary blob
Changes in v3: - Include a link to the program instead of adding it to the tree - Fix several typos - Align backslashes to the same column
Changes in v2: None
cmd/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/cmd/Kconfig b/cmd/Kconfig index a5d030b..d3b675c 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -184,6 +184,7 @@ config CMD_BOOTEFI config CMD_BOOTEFI_HELLO bool "Allow booting a standard EFI hello world for testing" depends on CMD_BOOTEFI + default y if CMD_BOOTEFI help This adds a standard EFI hello world application to U-Boot so that it can be used with the 'bootefi hello' command. This is useful

These files now need to be in a standard place so that they can be located by generic Makefile rules. Move them to the 'lib' directory.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
arch/x86/config.mk | 2 +- arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds | 0 arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds (100%) rename arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds (100%)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index d7addd8..a17abbb 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -45,7 +45,7 @@ endif
EFIPAYLOAD_BFDARCH = i386
-LDSCRIPT_EFI := $(srctree)/$(CPUDIR)/efi/elf_$(EFIARCH)_efi.lds +LDSCRIPT_EFI := $(srctree)/arch/x86/lib/elf_$(EFIARCH)_efi.lds EFISTUB := crt0-efi-$(EFIARCH).o reloc_$(EFIARCH).o OBJCOPYFLAGS_EFI += --target=efi-app-$(EFIARCH)
diff --git a/arch/x86/cpu/efi/elf_ia32_efi.lds b/arch/x86/lib/elf_ia32_efi.lds similarity index 100% rename from arch/x86/cpu/efi/elf_ia32_efi.lds rename to arch/x86/lib/elf_ia32_efi.lds diff --git a/arch/x86/cpu/efi/elf_x86_64_efi.lds b/arch/x86/lib/elf_x86_64_efi.lds similarity index 100% rename from arch/x86/cpu/efi/elf_x86_64_efi.lds rename to arch/x86/lib/elf_x86_64_efi.lds

These files now need to be in a standard place so that they can be located by generic Makefile rules. Move them to the 'lib' directory.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

These files now need to be in a standard place so that they can be located by generic Makefile rules. Move them to the 'lib' directory.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None Changes in v3: None Changes in v2: None
Makefile | 2 +- arch/x86/config.mk | 2 +- arch/x86/lib/Makefile | 18 ++++++++++++++++++ arch/x86/lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} | 0 .../lib/{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} | 0 arch/x86/lib/efi/Makefile | 18 ------------------ arch/x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} | 0 .../x86/lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} | 0 8 files changed, 20 insertions(+), 20 deletions(-) rename arch/x86/lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} (100%) rename arch/x86/lib/{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} (100%) rename arch/x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} (100%) rename arch/x86/lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} (100%)
diff --git a/Makefile b/Makefile index d3a6a12..c868fa2 100644 --- a/Makefile +++ b/Makefile @@ -1140,7 +1140,7 @@ quiet_cmd_u-boot_payload ?= LD $@ cmd_u-boot_payload ?= $(LD) $(LDFLAGS_EFI_PAYLOAD) -o $@ \ -T u-boot-payload.lds arch/x86/cpu/call32.o \ lib/efi/efi.o lib/efi/efi_stub.o u-boot.bin.o \ - $(addprefix arch/$(ARCH)/lib/efi/,$(EFISTUB)) + $(addprefix arch/$(ARCH)/lib/,$(EFISTUB))
u-boot-payload: u-boot.bin.o u-boot-payload.lds FORCE $(call if_changed,u-boot_payload) diff --git a/arch/x86/config.mk b/arch/x86/config.mk index a17abbb..12a8d73 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -46,7 +46,7 @@ endif EFIPAYLOAD_BFDARCH = i386
LDSCRIPT_EFI := $(srctree)/arch/x86/lib/elf_$(EFIARCH)_efi.lds -EFISTUB := crt0-efi-$(EFIARCH).o reloc_$(EFIARCH).o +EFISTUB := crt0_$(EFIARCH)_efi.o reloc_$(EFIARCH)_efi.o OBJCOPYFLAGS_EFI += --target=efi-app-$(EFIARCH)
CPPFLAGS_REMOVE_crt0-efi-$(EFIARCH).o += $(CFLAGS_NON_EFI) diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b9c2922..aad6555 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -44,3 +44,21 @@ NORMAL_LIBGCC = $(shell $(CC) $(PLATFORM_CPPFLAGS) -print-libgcc-file-name) OBJCOPYFLAGS := --prefix-symbols=__normal_ $(obj)/lib.a: $(NORMAL_LIBGCC) FORCE $(call if_changed,objcopy) + +obj-$(CONFIG_EFI_APP) += crt0_ia32_efi.o reloc_ia32_efi.o + +ifneq ($(CONFIG_EFI_STUB),) + +CFLAGS_REMOVE_reloc_ia32_efi.o += -mregparm=3 +CFLAGS_reloc_ia32_efi.o += -fpic -fshort-wchar + +# When building for 64-bit we must remove the i386-specific flags +CFLAGS_REMOVE_reloc_x86_64_efi.o += -mregparm=3 -march=i386 -m32 +CFLAGS_reloc_x86_64_efi.o += -fpic -fshort-wchar + +AFLAGS_REMOVE_crt0_x86_64_efi.o += -mregparm=3 -march=i386 -m32 +AFLAGS_crt0_x86_64_efi.o += -fpic -fshort-wchar + +extra-$(CONFIG_EFI_STUB_32BIT) += crt0_ia32_efi.o reloc_ia32_efi.o +extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o +endif diff --git a/arch/x86/lib/efi/crt0-efi-ia32.S b/arch/x86/lib/crt0_ia32_efi.S similarity index 100% rename from arch/x86/lib/efi/crt0-efi-ia32.S rename to arch/x86/lib/crt0_ia32_efi.S diff --git a/arch/x86/lib/efi/crt0-efi-x86_64.S b/arch/x86/lib/crt0_x86_64_efi.S similarity index 100% rename from arch/x86/lib/efi/crt0-efi-x86_64.S rename to arch/x86/lib/crt0_x86_64_efi.S diff --git a/arch/x86/lib/efi/Makefile b/arch/x86/lib/efi/Makefile index af4503e..43aadfc 100644 --- a/arch/x86/lib/efi/Makefile +++ b/arch/x86/lib/efi/Makefile @@ -7,21 +7,3 @@
obj-$(CONFIG_EFI_STUB) += car.o obj-$(CONFIG_EFI_STUB) += efi.o - -obj-$(CONFIG_EFI_APP) += crt0-efi-ia32.o reloc_ia32.o - -ifneq ($(CONFIG_EFI_STUB),) - -CFLAGS_REMOVE_reloc_ia32.o += -mregparm=3 -CFLAGS_reloc_ia32.o += -fpic -fshort-wchar - -# When building for 64-bit we must remove the i386-specific flags -CFLAGS_REMOVE_reloc_x86_64.o += -mregparm=3 -march=i386 -m32 -CFLAGS_reloc_x86_64.o += -fpic -fshort-wchar - -AFLAGS_REMOVE_crt0-efi-x86_64.o += -mregparm=3 -march=i386 -m32 -AFLAGS_crt0-efi-x86_64.o += -fpic -fshort-wchar - -extra-$(CONFIG_EFI_STUB_32BIT) += crt0-efi-ia32.o reloc_ia32.o -extra-$(CONFIG_EFI_STUB_64BIT) += crt0-efi-x86_64.o reloc_x86_64.o -endif diff --git a/arch/x86/lib/efi/reloc_ia32.c b/arch/x86/lib/reloc_ia32_efi.c similarity index 100% rename from arch/x86/lib/efi/reloc_ia32.c rename to arch/x86/lib/reloc_ia32_efi.c diff --git a/arch/x86/lib/efi/reloc_x86_64.c b/arch/x86/lib/reloc_x86_64_efi.c similarity index 100% rename from arch/x86/lib/efi/reloc_x86_64.c rename to arch/x86/lib/reloc_x86_64_efi.c

These files now need to be in a standard place so that they can be located by generic Makefile rules. Move them to the 'lib' directory.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

Add compiler flags and make a few minor adjustments to support the efi loader.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Add new patch to adjust EFI files support efi_loader
Changes in v3: None Changes in v2: None
arch/x86/config.mk | 16 ++++++++++++++++ arch/x86/lib/Makefile | 5 +++++ arch/x86/lib/elf_ia32_efi.lds | 2 -- arch/x86/lib/elf_x86_64_efi.lds | 2 -- 4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 12a8d73..03c71f7 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -65,3 +65,19 @@ PLATFORM_LDFLAGS += --emit-relocs LDFLAGS_FINAL += --gc-sections -pie
endif + +ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO),) + +ifneq ($(CONFIG_EFI_STUB_64BIT),) +EFI_LDS := elf_x86_64_efi.lds +EFI_CRT0 := crt0_x86_64_efi.o +EFI_RELOC := reloc_x86_64_efi.o +EFI_TARGET := --target=efi-app-ia32 +else +EFI_LDS := elf_ia32_efi.lds +EFI_CRT0 := crt0_ia32_efi.o +EFI_RELOC := reloc_ia32_efi.o +EFI_TARGET := --target=efi-app-x86_64 +endif + +endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index aad6555..ff402dc 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -61,4 +61,9 @@ AFLAGS_crt0_x86_64_efi.o += -fpic -fshort-wchar
extra-$(CONFIG_EFI_STUB_32BIT) += crt0_ia32_efi.o reloc_ia32_efi.o extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o + +endif + +ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO),) +extra-y += $(EFI_CRT0) $(EFI_RELOC) endif diff --git a/arch/x86/lib/elf_ia32_efi.lds b/arch/x86/lib/elf_ia32_efi.lds index cd3b0a9..174d36f 100644 --- a/arch/x86/lib/elf_ia32_efi.lds +++ b/arch/x86/lib/elf_ia32_efi.lds @@ -6,8 +6,6 @@ * Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi */
-#include <config.h> - OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start) diff --git a/arch/x86/lib/elf_x86_64_efi.lds b/arch/x86/lib/elf_x86_64_efi.lds index 9d9f057..70c7c52 100644 --- a/arch/x86/lib/elf_x86_64_efi.lds +++ b/arch/x86/lib/elf_x86_64_efi.lds @@ -6,8 +6,6 @@ * Modified from usr/lib32/elf_x86_64_efi.lds in gnu-efi */
-#include <config.h> - OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(_start)

Add compiler flags and make a few minor adjustments to support the efi loader.
Signed-off-by: Simon Glass sjg@chromium.org
Thanks, applied to efi-next
Alex

Enable this so that EFI applications (notably grub) can be run under U-Boot on x86 platforms.
At present the 'hello world' EFI application is not supported for the qemu-x86_efi_payload64 board. That board builds a payload consisting of a 64-bit header and a 32-bit U-Boot, which is incompatible with the way the EFI loader builds its EFI application. The following error is obtained:
x86_64-linux-ld.bfd: i386 architecture of input file `lib/efi_loader/helloworld.o' is incompatible with i386:x86-64 output
This could be corrected with additional Makefile rules. For now, this feature is disabled for that board.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v4: - Drop the binary 'hello world' program
Changes in v3: None Changes in v2: - Remove EFI support from README.x86 TODO list
configs/efi-x86_defconfig | 1 + configs/qemu-x86_efi_payload64_defconfig | 1 + configs/stm32f429-discovery_defconfig | 1 + doc/README.x86 | 1 - lib/efi_loader/Kconfig | 2 +- 5 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/configs/efi-x86_defconfig b/configs/efi-x86_defconfig index b31c73b..1fe6142 100644 --- a/configs/efi-x86_defconfig +++ b/configs/efi-x86_defconfig @@ -34,3 +34,4 @@ CONFIG_USB=y CONFIG_USB_STORAGE=y CONFIG_USB_KEYBOARD=y CONFIG_EFI=y +# CONFIG_EFI_LOADER is not set diff --git a/configs/qemu-x86_efi_payload64_defconfig b/configs/qemu-x86_efi_payload64_defconfig index c081ead..a9ffd92 100644 --- a/configs/qemu-x86_efi_payload64_defconfig +++ b/configs/qemu-x86_efi_payload64_defconfig @@ -52,3 +52,4 @@ CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_EFI=y CONFIG_EFI_STUB=y CONFIG_EFI_STUB_64BIT=y +# CONFIG_CMD_BOOTEFI_HELLO is not set diff --git a/configs/stm32f429-discovery_defconfig b/configs/stm32f429-discovery_defconfig index 24e2221..a68494b 100644 --- a/configs/stm32f429-discovery_defconfig +++ b/configs/stm32f429-discovery_defconfig @@ -10,3 +10,4 @@ CONFIG_SYS_PROMPT="U-Boot > " # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIMER=y CONFIG_OF_LIBFDT=y +# CONFIG_CMD_BOOTEFI_HELLO is not set diff --git a/doc/README.x86 b/doc/README.x86 index 6799559..a38cc1b 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -1077,7 +1077,6 @@ TODO List --------- - Audio - Chrome OS verified boot -- Support for CONFIG_EFI_LOADER - Building U-Boot to run in 64-bit mode
References diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 48563aa..8e7e8a5 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,6 +1,6 @@ config EFI_LOADER bool "Support running EFI Applications in U-Boot" - depends on (ARM64 || ARM) && OF_LIBFDT + depends on (ARM64 || ARM || X86) && OF_LIBFDT default y help Select this option if you want to run EFI applications (like grub2)

Enable this so that EFI applications (notably grub) can be run under U-Boot on x86 platforms.
At present the 'hello world' EFI application is not supported for the qemu-x86_efi_payload64 board. That board builds a payload consisting of a 64-bit header and a 32-bit U-Boot, which is incompatible with the way the EFI loader builds its EFI application. The following error is obtained:
x86_64-linux-ld.bfd: i386 architecture of input file `lib/efi_loader/helloworld.o' is incompatible with i386:x86-64 output
This could be corrected with additional Makefile rules. For now, this feature is disabled for that board.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Thanks, applied to efi-next
Alex

Resend attempt...
On 7 November 2016 at 08:47, Simon Glass sjg@chromium.org wrote:
This series adds EFI loader support for x86. Since U-Boot already supports running as an EFI app (and as a payload) this is relatively straightforward, requiring just moving files into place and updating a few compiler flags.
One problem with the EFI loader is that it lacks even rudimentary test support within U-Boot. At present the only way to test it is to boot an EFI application. As a step towards correcting this, this series also adds support for a 'hello world' test program which can be used to make sure that EFI loader support works correctly on a supported architecture. It is only a very simple program (it makes just two API calls!) but it does provide a sanity check and can be expanded as needed.
No attempt is made to create a pytest with this, but it should be fairly straightforward to do so.
Changes in v4:
- Move hello world test program into new patch
- Add new patch to add EFI app support
- Add new patch to add EFI app support on aarch64
- Use the build-generated 'hello world' program instead of a binary blob
- Add new patch to adjust EFI files support efi_loader
- Drop the binary 'hello world' program
Changes in v3:
- Include a link to the program instead of adding it to the tree
- Fix several typos
- Align backslashes to the same column
Changes in v2:
- Add new patch to tidy up selection of building the EFI stub
- Remove EFI support from README.x86 TODO list
Simon Glass (14): x86: Correct a build warning in x86 tables efi: Correct cache flush alignment efi: Fix debug message address format x86: Tidy up selection of building the EFI stub efi: Makefile: Export variables for use with EFI efi: Add support for a hello world test program elf: arm: Add a few ARM relocation types efi: arm: Add EFI app support efi: arm: Add aarch64 EFI app support efi: arm: Enable the hello world test program x86: Move efi .lds files into the 'lib' directory x86: Move efi .S files into the 'lib' directory efi: x86: Adjust EFI files support efi_loader x86: Enable EFI loader support
Makefile | 11 +- arch/arm/config.mk | 7 ++ arch/arm/cpu/armv8/config.mk | 4 + arch/arm/lib/Makefile | 10 ++ arch/arm/lib/crt0_aarch64_efi.S | 135 ++++++++++++++++++++ arch/arm/lib/crt0_arm_efi.S | 138 +++++++++++++++++++++ arch/arm/lib/elf_aarch64_efi.lds | 70 +++++++++++ arch/arm/lib/elf_arm_efi.lds | 70 +++++++++++ arch/arm/lib/reloc_aarch64_efi.c | 87 +++++++++++++ arch/arm/lib/reloc_arm_efi.c | 66 ++++++++++ arch/arm/lib/relocate.S | 3 +- arch/arm/lib/relocate_64.S | 3 +- arch/x86/config.mk | 20 ++- arch/x86/lib/Makefile | 23 ++++ .../lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} | 0 .../{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} | 0 arch/x86/lib/efi/Makefile | 18 --- arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds | 2 - arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds | 2 - .../x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} | 0 .../lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} | 0 arch/x86/lib/tables.c | 2 + cmd/Kconfig | 10 ++ cmd/bootefi.c | 29 +++-- configs/efi-x86_defconfig | 1 + configs/qemu-x86_efi_payload64_defconfig | 1 + configs/stm32f429-discovery_defconfig | 1 + doc/README.efi | 22 ++++ doc/README.x86 | 1 - include/asm-generic/sections.h | 2 + include/efi.h | 7 +- include/elf.h | 13 ++ lib/efi/Makefile | 4 +- lib/efi_loader/Kconfig | 2 +- lib/efi_loader/Makefile | 4 + lib/efi_loader/efi_image_loader.c | 3 +- lib/efi_loader/helloworld.c | 24 ++++ scripts/Makefile.lib | 33 +++++ 38 files changed, 787 insertions(+), 41 deletions(-) create mode 100644 arch/arm/lib/crt0_aarch64_efi.S create mode 100644 arch/arm/lib/crt0_arm_efi.S create mode 100644 arch/arm/lib/elf_aarch64_efi.lds create mode 100644 arch/arm/lib/elf_arm_efi.lds create mode 100644 arch/arm/lib/reloc_aarch64_efi.c create mode 100644 arch/arm/lib/reloc_arm_efi.c rename arch/x86/lib/{efi/crt0-efi-ia32.S => crt0_ia32_efi.S} (100%) rename arch/x86/lib/{efi/crt0-efi-x86_64.S => crt0_x86_64_efi.S} (100%) rename arch/x86/{cpu/efi => lib}/elf_ia32_efi.lds (98%) rename arch/x86/{cpu/efi => lib}/elf_x86_64_efi.lds (98%) rename arch/x86/lib/{efi/reloc_ia32.c => reloc_ia32_efi.c} (100%) rename arch/x86/lib/{efi/reloc_x86_64.c => reloc_x86_64_efi.c} (100%) create mode 100644 lib/efi_loader/helloworld.c
-- 2.8.0.rc3.226.g39d4020
participants (2)
-
Alexander Graf
-
Simon Glass