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