// SPDX-License-Identifier: GPL-2.0+ /* * efi_selftest_crc32 * * Copyright (c) 2018 Heinrich Schuchardt * * This unit test checks the CalculateCrc32 bootservice and checks the * headers of the system table, the boot services tablle, and the runtime * services table before and after ExitBootServices(). */ #include const struct efi_system_table *st; efi_status_t (EFIAPI *bs_crc32)(const void *data, efi_uintn_t data_size, u32 *crc32); static int check_table(const void *table) { efi_status_t ret; u32 crc32, res; /* Casting from const to not const */ struct efi_table_hdr *hdr = (struct efi_table_hdr *)table; if (!hdr->signature) { efi_st_error("Missing header signature\n"); return EFI_ST_FAILURE; } if (!hdr->revision) { efi_st_error("Missing header revision\n"); return EFI_ST_FAILURE; } if (hdr->headersize <= sizeof(struct efi_table_hdr)) { efi_st_error("Incorrect headersize value\n"); return EFI_ST_FAILURE; } if (hdr->reserved) { efi_st_error("Reserved header field is not zero\n"); return EFI_ST_FAILURE; } crc32 = hdr->crc32; /* * Setting the crc32 of the 'const' table to zero is easier than * copying */ hdr->crc32 = 0; ret = bs_crc32(table, hdr->headersize, &res); /* Reset table crc32 so it stays constant */ hdr->crc32 = crc32; if (ret != EFI_ST_SUCCESS) { efi_st_error("CalculateCrc32 failed\n"); return EFI_ST_FAILURE; } if (res != crc32) { efi_st_error("Incorrect CRC32\n"); // return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; } /* * Setup unit test. * * Check that CalculateCrc32 is working correctly. * Check tables before ExitBootServices(). * * @handle: handle of the loaded image * @systable: system table * @return: EFI_ST_SUCCESS for success */ static int setup(const efi_handle_t handle, const struct efi_system_table *systable) { efi_status_t ret; u32 res; st = systable; bs_crc32 = systable->boottime->calculate_crc32; /* Check that CalculateCrc32 is working */ ret = bs_crc32("U-Boot", 6, &res); if (ret != EFI_ST_SUCCESS) { efi_st_error("CalculateCrc32 failed\n"); return EFI_ST_FAILURE; } if (res != 0x134b0db4) { efi_st_error("Incorrect CRC32\n"); return EFI_ST_FAILURE; } /* Check tables before ExitBootServices() */ if (check_table(st) != EFI_ST_SUCCESS) { efi_st_error("Checking system table\n"); return EFI_ST_FAILURE; } if (check_table(st->boottime) != EFI_ST_SUCCESS) { efi_st_error("Checking boottime table\n"); return EFI_ST_FAILURE; } if (check_table(st->runtime) != EFI_ST_SUCCESS) { efi_st_error("Checking runtime table\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; } /* * Execute unit test * * Check tables after ExitBootServices() * * @return: EFI_ST_SUCCESS for success */ static int execute(void) { if (check_table(st) != EFI_ST_SUCCESS) { efi_st_error("Checking system table\n"); return EFI_ST_FAILURE; } if (check_table(st->runtime) != EFI_ST_SUCCESS) { efi_st_error("Checking runtime table\n"); return EFI_ST_FAILURE; } /* * We cannot call SetVirtualAddressMap() and recheck the runtime * table afterwards because this would invalidate the addresses of the * unit tests. */ return EFI_ST_SUCCESS; } EFI_UNIT_TEST(crc32) = { .name = "crc32", .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT, .setup = setup, .execute = execute, };