From 53c701720c3d5e5ae107454ea9b9f680bc399006 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 27 Aug 2019 08:16:08 +0200 Subject: [PATCH] efi_selftest: use standalone UEFI program for exception To fully demonstrate crash outputs for UEFI images provide a standalone UEFI application that tries to invoke an illegal opcode. Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/Makefile | 10 +- lib/efi_selftest/efi_selftest_exception.c | 141 ++++++++++++++++++---- lib/efi_selftest/efi_selftest_miniapp_exception.c | 41 +++++++ 3 files changed, 169 insertions(+), 23 deletions(-) create mode 100644 lib/efi_selftest/efi_selftest_miniapp_exception.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index f326ead..8348014 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -20,7 +20,6 @@ efi_selftest_crc32.o \ efi_selftest_devicepath_util.o \ efi_selftest_events.o \ efi_selftest_event_groups.o \ -efi_selftest_exception.o \ efi_selftest_exitbootservices.o \ efi_selftest_gop.o \ efi_selftest_loaded_image.o \ @@ -60,16 +59,23 @@ endif ifeq ($(CONFIG_SANDBOX)$(CONFIG_CPU_V7M),) obj-y += \ +efi_selftest_exception.o \ efi_selftest_loadimage.o \ efi_selftest_startimage_exit.o \ efi_selftest_startimage_return.o targets += \ +efi_miniapp_file_image_exception.h \ efi_miniapp_file_image_exit.h \ efi_miniapp_file_image_return.h \ +efi_selftest_miniapp_exception.efi \ efi_selftest_miniapp_exit.efi \ efi_selftest_miniapp_return.efi +$(obj)/efi_miniapp_file_image_exception.h: $(obj)/efi_selftest_miniapp_exception.efi + $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exception.efi > \ + $(obj)/efi_miniapp_file_image_exception.h + $(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \ $(obj)/efi_miniapp_file_image_exit.h @@ -80,6 +86,8 @@ $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h +$(obj)/efi_selftest_exception.o: $(obj)/efi_miniapp_file_image_exception.h + $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h diff --git a/lib/efi_selftest/efi_selftest_exception.c b/lib/efi_selftest/efi_selftest_exception.c index 76cfb88..6e900a3 100644 --- a/lib/efi_selftest/efi_selftest_exception.c +++ b/lib/efi_selftest/efi_selftest_exception.c @@ -2,42 +2,138 @@ /* * efi_selftest_exception * - * Copyright (c) 2018 Heinrich Schuchardt + * Copyright (c) 2019 Heinrich Schuchardt * - * Test the handling of exceptions by trying to execute an undefined - * instruction. + * This test checks the handling of exceptions. + * + * The efi_selftest_miniapp_exception.efi application is loaded into memory + * and started. */ #include +/* Include containing the UEFI application */ +#include "efi_miniapp_file_image_exception.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 + +/* File device path for LoadImage() */ +static struct { + struct efi_device_path dp; + u16 filename[8]; + struct efi_device_path end; +} dp = { + { + DEVICE_PATH_TYPE_MEDIA_DEVICE, + DEVICE_PATH_SUB_TYPE_FILE_PATH, + sizeof(dp.dp) + sizeof(dp.filename), + }, + L"bug.efi", + { + DEVICE_PATH_TYPE_END, + DEVICE_PATH_SUB_TYPE_END, + sizeof(dp.end), + } +}; + +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; -/** - * undefined_instruction() - try to executed an undefined instruction +/* Decompressed file image */ +static u8 *image; + +/* + * Decompress the disk image. + * + * @image decompressed disk image + * @return status code */ -static void undefined_instruction(void) +static efi_status_t decompress(u8 **image) { -#if defined(CONFIG_ARM) - /* - * 0xe7f...f. is undefined in ARM mode - * 0xde.. is undefined in Thumb mode - */ - asm volatile (".word 0xe7f7defb\n"); -#elif defined(CONFIG_RISCV) - asm volatile (".word 0xffffffff\n"); -#elif defined(CONFIG_X86) - asm volatile (".word 0xffff\n"); -#endif + 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; } -/** - * execute() - execute unit test +/* + * Setup unit test. * - * Return: EFI_ST_SUCCESS for success + * @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; +} + +/* + * Execute unit test. + * + * Load and start the application image. + * + * @return: EFI_ST_SUCCESS for success */ static int execute(void) { - undefined_instruction(); + efi_status_t ret; + efi_handle_t handle; + + ret = boottime->load_image(false, image_handle, &dp.dp, 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); - efi_st_error("An undefined instruction exception was not raised\n"); + efi_st_error("Exception not triggered\n"); return EFI_ST_FAILURE; } @@ -45,6 +141,7 @@ static int execute(void) EFI_UNIT_TEST(exception) = { .name = "exception", .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, .execute = execute, .on_request = true, }; diff --git a/lib/efi_selftest/efi_selftest_miniapp_exception.c b/lib/efi_selftest/efi_selftest_miniapp_exception.c new file mode 100644 index 0000000..63c63d7 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_miniapp_exception.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_miniapp_return + * + * Copyright (c) 2019 Heinrich Schuchardt + * + * This EFI application triggers an exception. + */ + +#include +#include + +/* + * 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->output_string(con_out, + L"EFI application triggers exception.\n"); + +#if defined(CONFIG_ARM) + /* + * 0xe7f...f. is undefined in ARM mode + * 0xde.. is undefined in Thumb mode + */ + asm volatile (".word 0xe7f7defb\n"); +#elif defined(CONFIG_RISCV) + asm volatile (".word 0xffffffff\n"); +#elif defined(CONFIG_X86) + asm volatile (".word 0xffff\n"); +#endif + con_out->output_string(con_out, L"Exception not triggered.\n"); + return EFI_ABORTED; +} -- 2.7.4