[PATCH 0/2] efi_loader: correctly call images

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/2] efi_loader: correctly call images

Heinrich Schuchardt
This patch series fixes various problems with the StartImage boot
time service. It further provides a unit test.

Heinrich Schuchardt (2):
  efi_loader: correctly call images
  efi_selftest: test start image

 lib/efi_loader/efi_boottime.c               |  21 ++--
 lib/efi_selftest/.gitignore                 |   2 +
 lib/efi_selftest/Makefile                   |  14 +++
 lib/efi_selftest/efi_selftest_miniapp.c     |  34 +++++++
 lib/efi_selftest/efi_selftest_start_image.c | 144 ++++++++++++++++++++++++++++
 5 files changed, 208 insertions(+), 7 deletions(-)
 create mode 100644 lib/efi_selftest/.gitignore
 create mode 100644 lib/efi_selftest/efi_selftest_miniapp.c
 create mode 100644 lib/efi_selftest/efi_selftest_start_image.c

--
2.14.2

_______________________________________________
U-Boot mailing list
[hidden email]
https://lists.denx.de/listinfo/u-boot
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/2] efi_loader: correctly call images

Heinrich Schuchardt
Avoid a failed assertion when an EFI app calls an EFI app.

Avoid that the indent level increases when calling 'bootefi hello'
repeatedly.

Avoid negative indent level when an EFI app calls an EFI app that
calls an EFI app (e.g. iPXE loads grub which starts the kernel).

Return the status code of a loaded image that returns without
calling the Exit boot service.

Signed-off-by: Heinrich Schuchardt <[hidden email]>
---
 lib/efi_loader/efi_boottime.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 4b3b63e39a..e13a2ac22e 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1537,6 +1537,7 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
  asmlinkage ulong (*entry)(efi_handle_t image_handle,
   struct efi_system_table *st);
  struct efi_loaded_image *info = image_handle;
+ efi_status_t ret;
 
  EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
  entry = info->reserved;
@@ -1546,17 +1547,23 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
  /* call the image! */
  if (setjmp(&info->exit_jmp)) {
  /* We returned from the child image */
+#ifdef CONFIG_ARM
+ /* efi_exit() called efi_restore_gd() */
+ gd = app_gd;
+#endif
+ /* Execute the return part of EFI_CALL */
+ assert(__efi_entry_check());
+ debug("%sEFI: %lu returned by started image\n",
+      __efi_nesting_dec(),
+      (unsigned long)((uintptr_t)info->exit_status &
+      ~EFI_ERROR_MASK));
  return EFI_EXIT(info->exit_status);
  }
 
- __efi_nesting_dec();
- __efi_exit_check();
- entry(image_handle, &systab);
- __efi_entry_check();
- __efi_nesting_inc();
+ ret = EFI_CALL(entry(image_handle, &systab));
 
  /* Should usually never get here */
- return EFI_EXIT(EFI_SUCCESS);
+ return EFI_EXIT(ret);
 }
 
 /*
@@ -1593,7 +1600,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
   exit_data_size, exit_data);
 
  /* Make sure entry/exit counts for EFI world cross-overs match */
- __efi_exit_check();
+ EFI_EXIT(exit_status);
 
  /*
  * But longjmp out with the U-Boot gd, not the application's, as
--
2.14.2

_______________________________________________
U-Boot mailing list
[hidden email]
https://lists.denx.de/listinfo/u-boot
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/2] efi_selftest: test start image

Heinrich Schuchardt
In reply to this post by Heinrich Schuchardt
This test checks the StartImage boottime service.
An EFI application is loaded into memory and started.

Signed-off-by: Heinrich Schuchardt <[hidden email]>
---
 lib/efi_selftest/.gitignore                 |   2 +
 lib/efi_selftest/Makefile                   |  14 +++
 lib/efi_selftest/efi_selftest_miniapp.c     |  34 +++++++
 lib/efi_selftest/efi_selftest_start_image.c | 144 ++++++++++++++++++++++++++++
 4 files changed, 194 insertions(+)
 create mode 100644 lib/efi_selftest/.gitignore
 create mode 100644 lib/efi_selftest/efi_selftest_miniapp.c
 create mode 100644 lib/efi_selftest/efi_selftest_start_image.c

diff --git a/lib/efi_selftest/.gitignore b/lib/efi_selftest/.gitignore
new file mode 100644
index 0000000000..c527e464e5
--- /dev/null
+++ b/lib/efi_selftest/.gitignore
@@ -0,0 +1,2 @@
+efi_miniapp_file_image.h
+*.efi
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 20f614d6ba..c353a01860 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -7,6 +7,9 @@
 # This file only gets included with CONFIG_EFI_LOADER set, so all
 # object inclusion implicitly depends on it
 
+CFLAGS_efi_selftest_miniapp.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp.o := $(CFLAGS_NON_EFI) -Os
+
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
 efi_selftest.o \
 efi_selftest_controllers.o \
@@ -17,6 +20,7 @@ efi_selftest_exitbootservices.o \
 efi_selftest_gop.o \
 efi_selftest_manageprotocols.o \
 efi_selftest_snp.o \
+efi_selftest_start_image.o \
 efi_selftest_textoutput.o \
 efi_selftest_tpl.o \
 efi_selftest_util.o \
@@ -25,3 +29,13 @@ efi_selftest_watchdog.o
 ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o
 endif
+
+targets += \
+efi_miniapp_file_image.h \
+efi_selftest_miniapp.efi
+
+$(obj)/efi_miniapp_file_image.h: $(obj)/efi_selftest_miniapp.efi
+ $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp.efi > \
+ $(obj)/efi_miniapp_file_image.h
+
+$(obj)/efi_selftest_start_image.o: $(obj)/efi_miniapp_file_image.h
diff --git a/lib/efi_selftest/efi_selftest_miniapp.c b/lib/efi_selftest/efi_selftest_miniapp.c
new file mode 100644
index 0000000000..bcdb37e86b
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp.c
@@ -0,0 +1,34 @@
+/*
+ * efi_selftest_miniapp
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This EFI application is run by the StartImage selftest.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+
+/*
+ * Entry point of the EFI application.
+ *
+ * @handle handle of the loaded image
+ * @systable system table
+ * @return status code
+ */
+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;
+
+ con_out->set_attribute(con_out, EFI_BACKGROUND_BROWN | EFI_WHITE);
+ con_out->output_string(con_out, L"Entering EFI application");
+ con_out->set_attribute(con_out, EFI_LIGHTGRAY);
+ con_out->output_string(con_out, L"\n");
+
+ systable->boottime->exit(handle, EFI_SUCCESS, 0, NULL);
+
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_selftest/efi_selftest_start_image.c b/lib/efi_selftest/efi_selftest_start_image.c
new file mode 100644
index 0000000000..012f64e369
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_start_image.c
@@ -0,0 +1,144 @@
+/*
+ * efi_selftest_start_image
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <[hidden email]>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This test checks the StartImage boottime service.
+ * The efi_selftest_miniapp.efi application is loaded into memory and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the miniapp.efi application */
+#include "efi_miniapp_file_image.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static efi_handle_t image_handle;
+static struct efi_boot_services *boottime;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+ size_t addr;
+ char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+ size_t length;
+ struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed file image */
+static u8 *image;
+
+/*
+ * Decompress the disk image.
+ *
+ * @image decompressed disk image
+ * @return status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+ u8 *buf;
+ size_t i;
+ size_t addr;
+ size_t len;
+ efi_status_t ret;
+
+ ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+      (void **)&buf);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Out of memory\n");
+ return ret;
+ }
+ boottime->set_mem(buf, img.length, 0);
+
+ for (i = 0; ; ++i) {
+ if (!img.lines[i].line)
+ break;
+ addr = img.lines[i].addr;
+ len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+ if (addr + len > img.length)
+ len = img.length - addr;
+ boottime->copy_mem(buf + addr, img.lines[i].line, len);
+ }
+ *image = buf;
+ return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ image_handle = handle;
+ boottime = systable->boottime;
+
+ /* Load the application image into memory */
+ decompress(&image);
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ efi_status_t r = EFI_ST_SUCCESS;
+
+ if (image) {
+ r = efi_free_pool(image);
+ if (r != EFI_SUCCESS) {
+ efi_st_error("Failed to free image\n");
+ return EFI_ST_FAILURE;
+ }
+ }
+ return r;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ efi_handle_t handle;
+
+ ret = boottime->load_image(false, image_handle, NULL, image,
+   img.length, &handle);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to load image\n");
+ return EFI_ST_FAILURE;
+ }
+ ret = boottime->start_image(handle, NULL, NULL);
+
+ return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(startimage) = {
+ .name = "start image",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+};
--
2.14.2

_______________________________________________
U-Boot mailing list
[hidden email]
https://lists.denx.de/listinfo/u-boot