1 /* 2 * efi_selftest_start_image 3 * 4 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 * 8 * This test checks the StartImage boot service. 9 * The efi_selftest_miniapp_exit.efi application is loaded into memory 10 * and started. 11 */ 12 13 #include <efi_selftest.h> 14 /* Include containing the miniapp.efi application */ 15 #include "efi_miniapp_file_image_exit.h" 16 17 /* Block size of compressed disk image */ 18 #define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8 19 20 /* Binary logarithm of the block size */ 21 #define LB_BLOCK_SIZE 9 22 23 static efi_handle_t image_handle; 24 static struct efi_boot_services *boottime; 25 26 /* One 8 byte block of the compressed disk image */ 27 struct line { 28 size_t addr; 29 char *line; 30 }; 31 32 /* Compressed file image */ 33 struct compressed_file_image { 34 size_t length; 35 struct line lines[]; 36 }; 37 38 static struct compressed_file_image img = EFI_ST_DISK_IMG; 39 40 /* Decompressed file image */ 41 static u8 *image; 42 43 /* 44 * Decompress the disk image. 45 * 46 * @image decompressed disk image 47 * @return status code 48 */ 49 static efi_status_t decompress(u8 **image) 50 { 51 u8 *buf; 52 size_t i; 53 size_t addr; 54 size_t len; 55 efi_status_t ret; 56 57 ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length, 58 (void **)&buf); 59 if (ret != EFI_SUCCESS) { 60 efi_st_error("Out of memory\n"); 61 return ret; 62 } 63 boottime->set_mem(buf, img.length, 0); 64 65 for (i = 0; ; ++i) { 66 if (!img.lines[i].line) 67 break; 68 addr = img.lines[i].addr; 69 len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE; 70 if (addr + len > img.length) 71 len = img.length - addr; 72 boottime->copy_mem(buf + addr, img.lines[i].line, len); 73 } 74 *image = buf; 75 return ret; 76 } 77 78 /* 79 * Setup unit test. 80 * 81 * @handle: handle of the loaded image 82 * @systable: system table 83 * @return: EFI_ST_SUCCESS for success 84 */ 85 static int setup(const efi_handle_t handle, 86 const struct efi_system_table *systable) 87 { 88 image_handle = handle; 89 boottime = systable->boottime; 90 91 /* Load the application image into memory */ 92 decompress(&image); 93 94 return EFI_ST_SUCCESS; 95 } 96 97 /* 98 * Tear down unit test. 99 * 100 * @return: EFI_ST_SUCCESS for success 101 */ 102 static int teardown(void) 103 { 104 efi_status_t r = EFI_ST_SUCCESS; 105 106 if (image) { 107 r = efi_free_pool(image); 108 if (r != EFI_SUCCESS) { 109 efi_st_error("Failed to free image\n"); 110 return EFI_ST_FAILURE; 111 } 112 } 113 return r; 114 } 115 116 /* 117 * Execute unit test. 118 * 119 * Load and start the application image. 120 * 121 * @return: EFI_ST_SUCCESS for success 122 */ 123 static int execute(void) 124 { 125 efi_status_t ret; 126 efi_handle_t handle; 127 128 ret = boottime->load_image(false, image_handle, NULL, image, 129 img.length, &handle); 130 if (ret != EFI_SUCCESS) { 131 efi_st_error("Failed to load image\n"); 132 return EFI_ST_FAILURE; 133 } 134 ret = boottime->start_image(handle, NULL, NULL); 135 if (ret != EFI_UNSUPPORTED) { 136 efi_st_error("Wrong return value from application\n"); 137 return EFI_ST_FAILURE; 138 } 139 140 return EFI_ST_SUCCESS; 141 } 142 143 EFI_UNIT_TEST(startimage_exit) = { 144 .name = "start image exit", 145 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, 146 .setup = setup, 147 .execute = execute, 148 .teardown = teardown, 149 }; 150