
This test checks the StartImage boottime service. An EFI application is loaded into memory and started.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- 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 xypron.glpk@gmx.de + * + * 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, +};