| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * efi_selftest_exception |
| * |
| * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de> |
| * |
| * This test checks the handling of exceptions. |
| * |
| * The efi_selftest_miniapp_exception.efi application is loaded into memory |
| * and started. |
| */ |
| |
| #include <efi_selftest.h> |
| /* 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), |
| }, |
| u"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, |
| }; |