xref: /openbmc/u-boot/lib/efi_selftest/efi_selftest_crc32.c (revision f388e3bed7318efe97058b673801dda6f563d319)
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