Browse Source

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>
Simon Glass 8 years ago
parent
commit
c7ae3dfdcc
7 changed files with 107 additions and 6 deletions
  1. 9 0
      cmd/Kconfig
  2. 21 6
      cmd/bootefi.c
  3. 14 0
      doc/README.efi
  4. 2 0
      include/asm-generic/sections.h
  5. 4 0
      lib/efi_loader/Makefile
  6. 24 0
      lib/efi_loader/helloworld.c
  7. 33 0
      scripts/Makefile.lib

+ 9 - 0
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 && 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

+ 21 - 6
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(

+ 14 - 0
doc/README.efi

@@ -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
 -----------
 

+ 2 - 0
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[];

+ 4 - 0
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

+ 24 - 0
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;
+}

+ 33 - 0
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     $<