efi: Add support for a hello world test program
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>
[agraf: Fix documentation, add unfulfilled kconfig dep]
Signed-off-by: Alexander Graf <agraf@suse.de>
diff --git a/cmd/Kconfig b/cmd/Kconfig
index e339d86..ebcfd6d 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -181,6 +181,15 @@
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 && NEED_CRT0_ENABLEMENT
+ 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 @@
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 @@
"<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..66259f3 100644
--- a/doc/README.efi
+++ b/doc/README.efi
@@ -310,6 +310,20 @@
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.
+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 __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 @@
$(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 $<