efi_loader: validate load option
[oweals/u-boot.git] / lib / efi_selftest / efi_selftest_exception.c
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  */
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  */
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  */
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 };