efi: Add support for a hello world test program
authorSimon Glass <sjg@chromium.org>
Mon, 7 Nov 2016 15:47:08 +0000 (08:47 -0700)
committerAlexander Graf <agraf@suse.de>
Mon, 14 Nov 2016 22:24:03 +0000 (23:24 +0100)
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>
cmd/Kconfig
cmd/bootefi.c
doc/README.efi
include/asm-generic/sections.h
lib/efi_loader/Makefile
lib/efi_loader/helloworld.c [new file with mode: 0644]
scripts/Makefile.lib

index e339d8638aa5a4a4881f98b7c8bbeb9d4b7530df..ebcfd6ddaf0af181aa9c2a5065695345b9abf63d 100644 (file)
@@ -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 && 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
index 3ab256ec51faafc925ca63d2d404c29b77561c89..ae1b713197cbc91a06d6b072660a30941937614f 100644 (file)
@@ -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(
index 1fd3f004c3999f1d5b90e502be984be5a33846c8..66259f3e260ec33c6b5317b1aad9392d32fdc3c2 100644 (file)
@@ -310,6 +310,20 @@ 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.
+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
 -----------
 
index d69bc6035be944d41228cec5d420be2f951740ed..daf021b647e6fdfa6d6baf091eaad707f58b55bb 100644 (file)
@@ -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[];
index 12159dd5ce84a03535e789a15a55b6388d404e41..f4664085e57257ccb4da963204e419f2ee3a3ff3 100644 (file)
@@ -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 (file)
index 0000000..03e65ab
--- /dev/null
@@ -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;
+}
index 45a0e1d486c0f50d8c8948b99257ca46046d6b53..956a8a9b04471fceabdc8ca659a577da6360af78 100644 (file)
@@ -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     $<