uboot/lib/efi_selftest/efi_selftest_config_table.c
<<
>>
Prefs
   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#include <u-boot/crc.h>
  13
  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/*
  22 * Notification function, increments the notification count if parameter
  23 * 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/*
  37 * Check CRC32 of a table.
  38 */
  39static int check_table(const void *table)
  40{
  41        efi_status_t ret;
  42        u32 crc32, res;
  43        /* Casting from constant to not constant */
  44        struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
  45
  46        crc32 = hdr->crc32;
  47        /*
  48         * Setting the CRC32 of the 'const' table to zero is easier than
  49         * copying
  50         */
  51        hdr->crc32 = 0;
  52        ret = boottime->calculate_crc32(table, hdr->headersize, &res);
  53        /* Reset table CRC32 so it stays constant */
  54        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/*
  67 * 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) {
 157                if (!memcmp(&sys_table->tables[i].guid, &table_guid,
 158                            sizeof(efi_guid_t)))
 159                        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        }
 169        if (check_table(sys_table) != EFI_ST_SUCCESS) {
 170                efi_st_error("Checking system table\n");
 171                return EFI_ST_FAILURE;
 172        }
 173
 174        /* 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) {
 196                if (!memcmp(&sys_table->tables[i].guid, &table_guid,
 197                            sizeof(efi_guid_t))) {
 198                        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) {
 207                efi_st_error("Duplicate table GUID\n");
 208                return EFI_ST_FAILURE;
 209        }
 210        if (table != &tables[1]) {
 211                efi_st_error("Incorrect table address\n");
 212                return EFI_ST_FAILURE;
 213        }
 214        if (check_table(sys_table) != EFI_ST_SUCCESS) {
 215                efi_st_error("Checking system table\n");
 216                return EFI_ST_FAILURE;
 217        }
 218
 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) {
 239                if (!memcmp(&sys_table->tables[i].guid, &table_guid,
 240                            sizeof(efi_guid_t))) {
 241                        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        }
 254        if (check_table(sys_table) != EFI_ST_SUCCESS) {
 255                efi_st_error("Checking system table\n");
 256                return EFI_ST_FAILURE;
 257        }
 258
 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};
 268