1 // 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> 12 13 static const struct efi_system_table *sys_table; 14 static struct efi_boot_services *boottime; 15 16 static efi_guid_t table_guid = 17 EFI_GUID(0xff1c3f9e, 0x795b, 0x1529, 0xf1, 0x55, 18 0x17, 0x2e, 0x51, 0x6b, 0x49, 0x75); 19 20 /* 21 * Notification function, increments the notfication count if parameter 22 * context is provided. 23 * 24 * @event notified event 25 * @context pointer to the notification count 26 */ 27 static void EFIAPI notify(struct efi_event *event, void *context) 28 { 29 unsigned int *count = context; 30 31 if (count) 32 ++*count; 33 } 34 35 /* 36 * Check crc32 of a table. 37 */ 38 static int check_table(const void *table) 39 { 40 efi_status_t ret; 41 u32 crc32, res; 42 /* Casting from const to not const */ 43 struct efi_table_hdr *hdr = (struct efi_table_hdr *)table; 44 45 crc32 = hdr->crc32; 46 /* 47 * Setting the crc32 of the 'const' table to zero is easier than 48 * copying 49 */ 50 hdr->crc32 = 0; 51 ret = boottime->calculate_crc32(table, hdr->headersize, &res); 52 /* Reset table crc32 so it stays constant */ 53 hdr->crc32 = crc32; 54 if (ret != EFI_ST_SUCCESS) { 55 efi_st_error("CalculateCrc32 failed\n"); 56 return EFI_ST_FAILURE; 57 } 58 if (res != crc32) { 59 efi_st_error("Incorrect CRC32\n"); 60 return EFI_ST_FAILURE; 61 } 62 return EFI_ST_SUCCESS; 63 } 64 65 /* 66 * Setup unit test. 67 * 68 * @handle: handle of the loaded image 69 * @systable: system table 70 * @return: EFI_ST_SUCCESS for success 71 */ 72 static int setup(const efi_handle_t handle, 73 const struct efi_system_table *systable) 74 { 75 sys_table = systable; 76 boottime = systable->boottime; 77 78 return EFI_ST_SUCCESS; 79 } 80 81 /* 82 * Execute unit test. 83 * 84 * A table is installed, updated, removed. The table entry and the 85 * triggering of events is checked. 86 * 87 * @return: EFI_ST_SUCCESS for success 88 */ 89 static int execute(void) 90 { 91 efi_status_t ret; 92 unsigned int counter = 0; 93 struct efi_event *event; 94 void *table; 95 const unsigned int tables[2]; 96 efi_uintn_t i; 97 efi_uintn_t tabcnt; 98 efi_uintn_t table_count = sys_table->nr_tables; 99 100 ret = boottime->create_event_ex(0, TPL_NOTIFY, 101 notify, (void *)&counter, 102 &table_guid, &event); 103 if (ret != EFI_SUCCESS) { 104 efi_st_error("Failed to create event\n"); 105 return EFI_ST_FAILURE; 106 } 107 108 /* Try to delete non-existent table */ 109 ret = boottime->install_configuration_table(&table_guid, NULL); 110 if (ret != EFI_NOT_FOUND) { 111 efi_st_error("Failed to detect missing table\n"); 112 return EFI_ST_FAILURE; 113 } 114 if (counter) { 115 efi_st_error("Notification function was called.\n"); 116 return EFI_ST_FAILURE; 117 } 118 /* Check if the event was signaled */ 119 ret = boottime->check_event(event); 120 if (ret == EFI_SUCCESS) { 121 efi_st_error("Event was signaled on EFI_NOT_FOUND\n"); 122 return EFI_ST_FAILURE; 123 } 124 if (counter != 1) { 125 efi_st_error("Notification function was not called.\n"); 126 return EFI_ST_FAILURE; 127 } 128 if (table_count != sys_table->nr_tables) { 129 efi_st_error("Incorrect table count %u, expected %u\n", 130 (unsigned int)sys_table->nr_tables, 131 (unsigned int)table_count); 132 return EFI_ST_FAILURE; 133 } 134 135 /* Install table */ 136 ret = boottime->install_configuration_table(&table_guid, 137 (void *)&tables[0]); 138 if (ret != EFI_SUCCESS) { 139 efi_st_error("Failed to install table\n"); 140 return EFI_ST_FAILURE; 141 } 142 /* Check signaled state */ 143 ret = boottime->check_event(event); 144 if (ret != EFI_SUCCESS) { 145 efi_st_error("Event was not signaled on insert\n"); 146 return EFI_ST_FAILURE; 147 } 148 if (++table_count != sys_table->nr_tables) { 149 efi_st_error("Incorrect table count %u, expected %u\n", 150 (unsigned int)sys_table->nr_tables, 151 (unsigned int)table_count); 152 return EFI_ST_FAILURE; 153 } 154 table = NULL; 155 for (i = 0; i < sys_table->nr_tables; ++i) { 156 if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid, 157 sizeof(efi_guid_t))) 158 table = sys_table->tables[i].table; 159 } 160 if (!table) { 161 efi_st_error("Installed table not found\n"); 162 return EFI_ST_FAILURE; 163 } 164 if (table != &tables[0]) { 165 efi_st_error("Incorrect table address\n"); 166 return EFI_ST_FAILURE; 167 } 168 if (check_table(sys_table) != EFI_ST_SUCCESS) { 169 efi_st_error("Checking system table\n"); 170 return EFI_ST_FAILURE; 171 } 172 173 /* Update table */ 174 ret = boottime->install_configuration_table(&table_guid, 175 (void *)&tables[1]); 176 if (ret != EFI_SUCCESS) { 177 efi_st_error("Failed to update table\n"); 178 return EFI_ST_FAILURE; 179 } 180 /* Check signaled state */ 181 ret = boottime->check_event(event); 182 if (ret != EFI_SUCCESS) { 183 efi_st_error("Event was not signaled on update\n"); 184 return EFI_ST_FAILURE; 185 } 186 if (table_count != sys_table->nr_tables) { 187 efi_st_error("Incorrect table count %u, expected %u\n", 188 (unsigned int)sys_table->nr_tables, 189 (unsigned int)table_count); 190 return EFI_ST_FAILURE; 191 } 192 table = NULL; 193 tabcnt = 0; 194 for (i = 0; i < sys_table->nr_tables; ++i) { 195 if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid, 196 sizeof(efi_guid_t))) { 197 table = sys_table->tables[i].table; 198 ++tabcnt; 199 } 200 } 201 if (!table) { 202 efi_st_error("Installed table not found\n"); 203 return EFI_ST_FAILURE; 204 } 205 if (tabcnt > 1) { 206 efi_st_error("Duplicate table guid\n"); 207 return EFI_ST_FAILURE; 208 } 209 if (table != &tables[1]) { 210 efi_st_error("Incorrect table address\n"); 211 return EFI_ST_FAILURE; 212 } 213 if (check_table(sys_table) != EFI_ST_SUCCESS) { 214 efi_st_error("Checking system table\n"); 215 return EFI_ST_FAILURE; 216 } 217 218 /* Delete table */ 219 ret = boottime->install_configuration_table(&table_guid, NULL); 220 if (ret != EFI_SUCCESS) { 221 efi_st_error("Failed to delete table\n"); 222 return EFI_ST_FAILURE; 223 } 224 /* Check signaled state */ 225 ret = boottime->check_event(event); 226 if (ret != EFI_SUCCESS) { 227 efi_st_error("Event was not signaled on delete\n"); 228 return EFI_ST_FAILURE; 229 } 230 if (--table_count != sys_table->nr_tables) { 231 efi_st_error("Incorrect table count %u, expected %u\n", 232 (unsigned int)sys_table->nr_tables, 233 (unsigned int)table_count); 234 return EFI_ST_FAILURE; 235 } 236 table = NULL; 237 for (i = 0; i < sys_table->nr_tables; ++i) { 238 if (!efi_st_memcmp(&sys_table->tables[i].guid, &table_guid, 239 sizeof(efi_guid_t))) { 240 table = sys_table->tables[i].table; 241 } 242 } 243 if (table) { 244 efi_st_error("Wrong table deleted\n"); 245 return EFI_ST_FAILURE; 246 } 247 248 ret = boottime->close_event(event); 249 if (ret != EFI_SUCCESS) { 250 efi_st_error("Failed to close event\n"); 251 return EFI_ST_FAILURE; 252 } 253 if (check_table(sys_table) != EFI_ST_SUCCESS) { 254 efi_st_error("Checking system table\n"); 255 return EFI_ST_FAILURE; 256 } 257 258 return EFI_ST_SUCCESS; 259 } 260 261 EFI_UNIT_TEST(configtables) = { 262 .name = "configuration tables", 263 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, 264 .setup = setup, 265 .execute = execute, 266 }; 267