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