// SPDX-License-Identifier: GPL-2.0+ /* * efi_selftest_exception * * Copyright (c) 2019 Heinrich Schuchardt * * 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; /* 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; } /* * 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, &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("Exception not triggered\n"); return EFI_ST_FAILURE; } EFI_UNIT_TEST(exception) = { .name = "exception", .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, .setup = setup, .execute = execute, .on_request = true, };