162045b0eSHeinrich Schuchardt // SPDX-License-Identifier: GPL-2.0+
262045b0eSHeinrich Schuchardt /*
362045b0eSHeinrich Schuchardt * efi_selftest_crc32
462045b0eSHeinrich Schuchardt *
562045b0eSHeinrich Schuchardt * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
662045b0eSHeinrich Schuchardt *
762045b0eSHeinrich Schuchardt * This unit test checks the CalculateCrc32 bootservice and checks the
8*d8b2216cSHeinrich Schuchardt * headers of the system table, the boot services table, and the runtime
962045b0eSHeinrich Schuchardt * services table before and after ExitBootServices().
1062045b0eSHeinrich Schuchardt */
1162045b0eSHeinrich Schuchardt
1262045b0eSHeinrich Schuchardt #include <efi_selftest.h>
1362045b0eSHeinrich Schuchardt
1462045b0eSHeinrich Schuchardt const struct efi_system_table *st;
1562045b0eSHeinrich Schuchardt efi_status_t (EFIAPI *bs_crc32)(const void *data, efi_uintn_t data_size,
1662045b0eSHeinrich Schuchardt u32 *crc32);
1762045b0eSHeinrich Schuchardt
check_table(const void * table)1862045b0eSHeinrich Schuchardt static int check_table(const void *table)
1962045b0eSHeinrich Schuchardt {
2062045b0eSHeinrich Schuchardt efi_status_t ret;
2162045b0eSHeinrich Schuchardt u32 crc32, res;
22*d8b2216cSHeinrich Schuchardt /* Casting from constant to not constant */
2362045b0eSHeinrich Schuchardt struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
2462045b0eSHeinrich Schuchardt
2562045b0eSHeinrich Schuchardt if (!hdr->signature) {
2662045b0eSHeinrich Schuchardt efi_st_error("Missing header signature\n");
2762045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
2862045b0eSHeinrich Schuchardt }
2962045b0eSHeinrich Schuchardt if (!hdr->revision) {
3062045b0eSHeinrich Schuchardt efi_st_error("Missing header revision\n");
3162045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
3262045b0eSHeinrich Schuchardt }
3362045b0eSHeinrich Schuchardt if (hdr->headersize <= sizeof(struct efi_table_hdr)) {
3462045b0eSHeinrich Schuchardt efi_st_error("Incorrect headersize value\n");
3562045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
3662045b0eSHeinrich Schuchardt }
3762045b0eSHeinrich Schuchardt if (hdr->reserved) {
3862045b0eSHeinrich Schuchardt efi_st_error("Reserved header field is not zero\n");
3962045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
4062045b0eSHeinrich Schuchardt }
4162045b0eSHeinrich Schuchardt
4262045b0eSHeinrich Schuchardt crc32 = hdr->crc32;
4362045b0eSHeinrich Schuchardt /*
4462045b0eSHeinrich Schuchardt * Setting the crc32 of the 'const' table to zero is easier than
4562045b0eSHeinrich Schuchardt * copying
4662045b0eSHeinrich Schuchardt */
4762045b0eSHeinrich Schuchardt hdr->crc32 = 0;
4862045b0eSHeinrich Schuchardt ret = bs_crc32(table, hdr->headersize, &res);
4962045b0eSHeinrich Schuchardt /* Reset table crc32 so it stays constant */
5062045b0eSHeinrich Schuchardt hdr->crc32 = crc32;
5162045b0eSHeinrich Schuchardt if (ret != EFI_ST_SUCCESS) {
5262045b0eSHeinrich Schuchardt efi_st_error("CalculateCrc32 failed\n");
5362045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
5462045b0eSHeinrich Schuchardt }
5562045b0eSHeinrich Schuchardt if (res != crc32) {
5662045b0eSHeinrich Schuchardt efi_st_error("Incorrect CRC32\n");
5762045b0eSHeinrich Schuchardt // return EFI_ST_FAILURE;
5862045b0eSHeinrich Schuchardt }
5962045b0eSHeinrich Schuchardt return EFI_ST_SUCCESS;
6062045b0eSHeinrich Schuchardt }
6162045b0eSHeinrich Schuchardt
6262045b0eSHeinrich Schuchardt /*
6362045b0eSHeinrich Schuchardt * Setup unit test.
6462045b0eSHeinrich Schuchardt *
6562045b0eSHeinrich Schuchardt * Check that CalculateCrc32 is working correctly.
6662045b0eSHeinrich Schuchardt * Check tables before ExitBootServices().
6762045b0eSHeinrich Schuchardt *
6862045b0eSHeinrich Schuchardt * @handle: handle of the loaded image
6962045b0eSHeinrich Schuchardt * @systable: system table
7062045b0eSHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success
7162045b0eSHeinrich Schuchardt */
setup(const efi_handle_t handle,const struct efi_system_table * systable)7262045b0eSHeinrich Schuchardt static int setup(const efi_handle_t handle,
7362045b0eSHeinrich Schuchardt const struct efi_system_table *systable)
7462045b0eSHeinrich Schuchardt {
7562045b0eSHeinrich Schuchardt efi_status_t ret;
7662045b0eSHeinrich Schuchardt u32 res;
7762045b0eSHeinrich Schuchardt
7862045b0eSHeinrich Schuchardt st = systable;
7962045b0eSHeinrich Schuchardt bs_crc32 = systable->boottime->calculate_crc32;
8062045b0eSHeinrich Schuchardt
8162045b0eSHeinrich Schuchardt /* Check that CalculateCrc32 is working */
8262045b0eSHeinrich Schuchardt ret = bs_crc32("U-Boot", 6, &res);
8362045b0eSHeinrich Schuchardt if (ret != EFI_ST_SUCCESS) {
8462045b0eSHeinrich Schuchardt efi_st_error("CalculateCrc32 failed\n");
8562045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
8662045b0eSHeinrich Schuchardt }
8762045b0eSHeinrich Schuchardt if (res != 0x134b0db4) {
8862045b0eSHeinrich Schuchardt efi_st_error("Incorrect CRC32\n");
8962045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
9062045b0eSHeinrich Schuchardt }
9162045b0eSHeinrich Schuchardt
9262045b0eSHeinrich Schuchardt /* Check tables before ExitBootServices() */
9362045b0eSHeinrich Schuchardt if (check_table(st) != EFI_ST_SUCCESS) {
9462045b0eSHeinrich Schuchardt efi_st_error("Checking system table\n");
9562045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
9662045b0eSHeinrich Schuchardt }
9762045b0eSHeinrich Schuchardt if (check_table(st->boottime) != EFI_ST_SUCCESS) {
9862045b0eSHeinrich Schuchardt efi_st_error("Checking boottime table\n");
9962045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
10062045b0eSHeinrich Schuchardt }
10162045b0eSHeinrich Schuchardt if (check_table(st->runtime) != EFI_ST_SUCCESS) {
10262045b0eSHeinrich Schuchardt efi_st_error("Checking runtime table\n");
10362045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
10462045b0eSHeinrich Schuchardt }
10562045b0eSHeinrich Schuchardt
10662045b0eSHeinrich Schuchardt return EFI_ST_SUCCESS;
10762045b0eSHeinrich Schuchardt }
10862045b0eSHeinrich Schuchardt
10962045b0eSHeinrich Schuchardt /*
11062045b0eSHeinrich Schuchardt * Execute unit test
11162045b0eSHeinrich Schuchardt *
11262045b0eSHeinrich Schuchardt * Check tables after ExitBootServices()
11362045b0eSHeinrich Schuchardt *
11462045b0eSHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success
11562045b0eSHeinrich Schuchardt */
execute(void)11662045b0eSHeinrich Schuchardt static int execute(void)
11762045b0eSHeinrich Schuchardt {
11862045b0eSHeinrich Schuchardt if (check_table(st) != EFI_ST_SUCCESS) {
11962045b0eSHeinrich Schuchardt efi_st_error("Checking system table\n");
12062045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
12162045b0eSHeinrich Schuchardt }
12262045b0eSHeinrich Schuchardt if (check_table(st->runtime) != EFI_ST_SUCCESS) {
12362045b0eSHeinrich Schuchardt efi_st_error("Checking runtime table\n");
12462045b0eSHeinrich Schuchardt return EFI_ST_FAILURE;
12562045b0eSHeinrich Schuchardt }
12662045b0eSHeinrich Schuchardt
12762045b0eSHeinrich Schuchardt /*
12862045b0eSHeinrich Schuchardt * We cannot call SetVirtualAddressMap() and recheck the runtime
12962045b0eSHeinrich Schuchardt * table afterwards because this would invalidate the addresses of the
13062045b0eSHeinrich Schuchardt * unit tests.
13162045b0eSHeinrich Schuchardt */
13262045b0eSHeinrich Schuchardt
13362045b0eSHeinrich Schuchardt return EFI_ST_SUCCESS;
13462045b0eSHeinrich Schuchardt }
13562045b0eSHeinrich Schuchardt
13662045b0eSHeinrich Schuchardt EFI_UNIT_TEST(crc32) = {
13762045b0eSHeinrich Schuchardt .name = "crc32",
13862045b0eSHeinrich Schuchardt .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
13962045b0eSHeinrich Schuchardt .setup = setup,
14062045b0eSHeinrich Schuchardt .execute = execute,
14162045b0eSHeinrich Schuchardt };
142