1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * efi_selftest_exception
4 *
5 * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 *
7 * This test checks the handling of exceptions.
8 *
9 * The efi_selftest_miniapp_exception.efi application is loaded into memory
10 * and started.
11 */
12
13 #include <efi_selftest.h>
14 /* Include containing the UEFI application */
15 #include "efi_miniapp_file_image_exception.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 /* File device path for LoadImage() */
24 static struct {
25 struct efi_device_path dp;
26 u16 filename[8];
27 struct efi_device_path end;
28 } dp = {
29 {
30 DEVICE_PATH_TYPE_MEDIA_DEVICE,
31 DEVICE_PATH_SUB_TYPE_FILE_PATH,
32 sizeof(dp.dp) + sizeof(dp.filename),
33 },
34 L"bug.efi",
35 {
36 DEVICE_PATH_TYPE_END,
37 DEVICE_PATH_SUB_TYPE_END,
38 sizeof(dp.end),
39 }
40 };
41
42 static efi_handle_t image_handle;
43 static struct efi_boot_services *boottime;
44
45 /* One 8 byte block of the compressed disk image */
46 struct line {
47 size_t addr;
48 char *line;
49 };
50
51 /* Compressed file image */
52 struct compressed_file_image {
53 size_t length;
54 struct line lines[];
55 };
56
57 static struct compressed_file_image img = EFI_ST_DISK_IMG;
58
59 /* Decompressed file image */
60 static u8 *image;
61
62 /*
63 * Decompress the disk image.
64 *
65 * @image decompressed disk image
66 * @return status code
67 */
decompress(u8 ** image)68 static efi_status_t decompress(u8 **image)
69 {
70 u8 *buf;
71 size_t i;
72 size_t addr;
73 size_t len;
74 efi_status_t ret;
75
76 ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
77 (void **)&buf);
78 if (ret != EFI_SUCCESS) {
79 efi_st_error("Out of memory\n");
80 return ret;
81 }
82 boottime->set_mem(buf, img.length, 0);
83
84 for (i = 0; ; ++i) {
85 if (!img.lines[i].line)
86 break;
87 addr = img.lines[i].addr;
88 len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
89 if (addr + len > img.length)
90 len = img.length - addr;
91 boottime->copy_mem(buf + addr, img.lines[i].line, len);
92 }
93 *image = buf;
94 return ret;
95 }
96
97 /*
98 * Setup unit test.
99 *
100 * @handle: handle of the loaded image
101 * @systable: system table
102 * @return: EFI_ST_SUCCESS for success
103 */
setup(const efi_handle_t handle,const struct efi_system_table * systable)104 static int setup(const efi_handle_t handle,
105 const struct efi_system_table *systable)
106 {
107 image_handle = handle;
108 boottime = systable->boottime;
109
110 /* Load the application image into memory */
111 decompress(&image);
112
113 return EFI_ST_SUCCESS;
114 }
115
116 /*
117 * Execute unit test.
118 *
119 * Load and start the application image.
120 *
121 * @return: EFI_ST_SUCCESS for success
122 */
execute(void)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, &dp.dp, 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
136 efi_st_error("Exception not triggered\n");
137
138 return EFI_ST_FAILURE;
139 }
140
141 EFI_UNIT_TEST(exception) = {
142 .name = "exception",
143 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
144 .setup = setup,
145 .execute = execute,
146 .on_request = true,
147 };
148