blob: 2bf12b5bb68e4d8c3be31a94a3b96eda81770216 [file] [log] [blame]
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * efi_selftest_config_tables
4 *
5 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 *
7 * This test checks the following service:
8 * InstallConfigurationTable.
9 */
10
11#include <efi_selftest.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070012#include <u-boot/crc.h>
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +020013
14static const struct efi_system_table *sys_table;
15static struct efi_boot_services *boottime;
16
17static efi_guid_t table_guid =
18 EFI_GUID(0xff1c3f9e, 0x795b, 0x1529, 0xf1, 0x55,
19 0x17, 0x2e, 0x51, 0x6b, 0x49, 0x75);
20
21/*
Heinrich Schuchardt702e7782018-09-27 20:44:40 +020022 * Notification function, increments the notification count if parameter
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +020023 * context is provided.
24 *
25 * @event notified event
26 * @context pointer to the notification count
27 */
28static void EFIAPI notify(struct efi_event *event, void *context)
29{
30 unsigned int *count = context;
31
32 if (count)
33 ++*count;
34}
35
36/*
Heinrich Schuchardt702e7782018-09-27 20:44:40 +020037 * Check CRC32 of a table.
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +020038 */
39static int check_table(const void *table)
40{
41 efi_status_t ret;
42 u32 crc32, res;
Heinrich Schuchardt702e7782018-09-27 20:44:40 +020043 /* Casting from constant to not constant */
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +020044 struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
45
46 crc32 = hdr->crc32;
47 /*
Heinrich Schuchardt702e7782018-09-27 20:44:40 +020048 * Setting the CRC32 of the 'const' table to zero is easier than
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +020049 * copying
50 */
51 hdr->crc32 = 0;
52 ret = boottime->calculate_crc32(table, hdr->headersize, &res);
Heinrich Schuchardt702e7782018-09-27 20:44:40 +020053 /* Reset table CRC32 so it stays constant */
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +020054 hdr->crc32 = crc32;
55 if (ret != EFI_ST_SUCCESS) {
56 efi_st_error("CalculateCrc32 failed\n");
57 return EFI_ST_FAILURE;
58 }
59 if (res != crc32) {
60 efi_st_error("Incorrect CRC32\n");
61 return EFI_ST_FAILURE;
62 }
63 return EFI_ST_SUCCESS;
64}
65
66/*
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +020067 * Setup unit test.
68 *
69 * @handle: handle of the loaded image
70 * @systable: system table
71 * @return: EFI_ST_SUCCESS for success
72 */
73static int setup(const efi_handle_t handle,
74 const struct efi_system_table *systable)
75{
76 sys_table = systable;
77 boottime = systable->boottime;
78
79 return EFI_ST_SUCCESS;
80}
81
82/*
83 * Execute unit test.
84 *
85 * A table is installed, updated, removed. The table entry and the
86 * triggering of events is checked.
87 *
88 * @return: EFI_ST_SUCCESS for success
89 */
90static int execute(void)
91{
92 efi_status_t ret;
93 unsigned int counter = 0;
94 struct efi_event *event;
95 void *table;
96 const unsigned int tables[2];
97 efi_uintn_t i;
98 efi_uintn_t tabcnt;
99 efi_uintn_t table_count = sys_table->nr_tables;
100
101 ret = boottime->create_event_ex(0, TPL_NOTIFY,
102 notify, (void *)&counter,
103 &table_guid, &event);
104 if (ret != EFI_SUCCESS) {
105 efi_st_error("Failed to create event\n");
106 return EFI_ST_FAILURE;
107 }
108
109 /* Try to delete non-existent table */
110 ret = boottime->install_configuration_table(&table_guid, NULL);
111 if (ret != EFI_NOT_FOUND) {
112 efi_st_error("Failed to detect missing table\n");
113 return EFI_ST_FAILURE;
114 }
115 if (counter) {
116 efi_st_error("Notification function was called.\n");
117 return EFI_ST_FAILURE;
118 }
119 /* Check if the event was signaled */
120 ret = boottime->check_event(event);
121 if (ret == EFI_SUCCESS) {
122 efi_st_error("Event was signaled on EFI_NOT_FOUND\n");
123 return EFI_ST_FAILURE;
124 }
125 if (counter != 1) {
126 efi_st_error("Notification function was not called.\n");
127 return EFI_ST_FAILURE;
128 }
129 if (table_count != sys_table->nr_tables) {
130 efi_st_error("Incorrect table count %u, expected %u\n",
131 (unsigned int)sys_table->nr_tables,
132 (unsigned int)table_count);
133 return EFI_ST_FAILURE;
134 }
135
136 /* Install table */
137 ret = boottime->install_configuration_table(&table_guid,
138 (void *)&tables[0]);
139 if (ret != EFI_SUCCESS) {
140 efi_st_error("Failed to install table\n");
141 return EFI_ST_FAILURE;
142 }
143 /* Check signaled state */
144 ret = boottime->check_event(event);
145 if (ret != EFI_SUCCESS) {
146 efi_st_error("Event was not signaled on insert\n");
147 return EFI_ST_FAILURE;
148 }
149 if (++table_count != sys_table->nr_tables) {
150 efi_st_error("Incorrect table count %u, expected %u\n",
151 (unsigned int)sys_table->nr_tables,
152 (unsigned int)table_count);
153 return EFI_ST_FAILURE;
154 }
155 table = NULL;
156 for (i = 0; i < sys_table->nr_tables; ++i) {
Heinrich Schuchardt5f946662019-05-04 19:48:38 +0200157 if (!memcmp(&sys_table->tables[i].guid, &table_guid,
158 sizeof(efi_guid_t)))
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200159 table = sys_table->tables[i].table;
160 }
161 if (!table) {
162 efi_st_error("Installed table not found\n");
163 return EFI_ST_FAILURE;
164 }
165 if (table != &tables[0]) {
166 efi_st_error("Incorrect table address\n");
167 return EFI_ST_FAILURE;
168 }
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +0200169 if (check_table(sys_table) != EFI_ST_SUCCESS) {
170 efi_st_error("Checking system table\n");
171 return EFI_ST_FAILURE;
172 }
173
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200174 /* Update table */
175 ret = boottime->install_configuration_table(&table_guid,
176 (void *)&tables[1]);
177 if (ret != EFI_SUCCESS) {
178 efi_st_error("Failed to update table\n");
179 return EFI_ST_FAILURE;
180 }
181 /* Check signaled state */
182 ret = boottime->check_event(event);
183 if (ret != EFI_SUCCESS) {
184 efi_st_error("Event was not signaled on update\n");
185 return EFI_ST_FAILURE;
186 }
187 if (table_count != sys_table->nr_tables) {
188 efi_st_error("Incorrect table count %u, expected %u\n",
189 (unsigned int)sys_table->nr_tables,
190 (unsigned int)table_count);
191 return EFI_ST_FAILURE;
192 }
193 table = NULL;
194 tabcnt = 0;
195 for (i = 0; i < sys_table->nr_tables; ++i) {
Heinrich Schuchardt5f946662019-05-04 19:48:38 +0200196 if (!memcmp(&sys_table->tables[i].guid, &table_guid,
197 sizeof(efi_guid_t))) {
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200198 table = sys_table->tables[i].table;
199 ++tabcnt;
200 }
201 }
202 if (!table) {
203 efi_st_error("Installed table not found\n");
204 return EFI_ST_FAILURE;
205 }
206 if (tabcnt > 1) {
Heinrich Schuchardt702e7782018-09-27 20:44:40 +0200207 efi_st_error("Duplicate table GUID\n");
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200208 return EFI_ST_FAILURE;
209 }
210 if (table != &tables[1]) {
211 efi_st_error("Incorrect table address\n");
212 return EFI_ST_FAILURE;
213 }
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +0200214 if (check_table(sys_table) != EFI_ST_SUCCESS) {
215 efi_st_error("Checking system table\n");
216 return EFI_ST_FAILURE;
217 }
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200218
219 /* Delete table */
220 ret = boottime->install_configuration_table(&table_guid, NULL);
221 if (ret != EFI_SUCCESS) {
222 efi_st_error("Failed to delete table\n");
223 return EFI_ST_FAILURE;
224 }
225 /* Check signaled state */
226 ret = boottime->check_event(event);
227 if (ret != EFI_SUCCESS) {
228 efi_st_error("Event was not signaled on delete\n");
229 return EFI_ST_FAILURE;
230 }
231 if (--table_count != sys_table->nr_tables) {
232 efi_st_error("Incorrect table count %u, expected %u\n",
233 (unsigned int)sys_table->nr_tables,
234 (unsigned int)table_count);
235 return EFI_ST_FAILURE;
236 }
237 table = NULL;
238 for (i = 0; i < sys_table->nr_tables; ++i) {
Heinrich Schuchardt5f946662019-05-04 19:48:38 +0200239 if (!memcmp(&sys_table->tables[i].guid, &table_guid,
240 sizeof(efi_guid_t))) {
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200241 table = sys_table->tables[i].table;
242 }
243 }
244 if (table) {
245 efi_st_error("Wrong table deleted\n");
246 return EFI_ST_FAILURE;
247 }
248
249 ret = boottime->close_event(event);
250 if (ret != EFI_SUCCESS) {
251 efi_st_error("Failed to close event\n");
252 return EFI_ST_FAILURE;
253 }
Heinrich Schuchardt2a29e8f2018-07-07 15:36:06 +0200254 if (check_table(sys_table) != EFI_ST_SUCCESS) {
255 efi_st_error("Checking system table\n");
256 return EFI_ST_FAILURE;
257 }
Heinrich Schuchardt4a640e32018-06-28 12:45:33 +0200258
259 return EFI_ST_SUCCESS;
260}
261
262EFI_UNIT_TEST(configtables) = {
263 .name = "configuration tables",
264 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
265 .setup = setup,
266 .execute = execute,
267};