xref: /openbmc/u-boot/lib/efi_selftest/efi_selftest_crc32.c (revision 62045b0eb43285424712875b92ddc683cd00991e)
1*62045b0eSHeinrich Schuchardt // SPDX-License-Identifier: GPL-2.0+
2*62045b0eSHeinrich Schuchardt /*
3*62045b0eSHeinrich Schuchardt  * efi_selftest_crc32
4*62045b0eSHeinrich Schuchardt  *
5*62045b0eSHeinrich Schuchardt  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
6*62045b0eSHeinrich Schuchardt  *
7*62045b0eSHeinrich Schuchardt  * This unit test checks the CalculateCrc32 bootservice and checks the
8*62045b0eSHeinrich Schuchardt  * headers of the system table, the boot services tablle, and the runtime
9*62045b0eSHeinrich Schuchardt  * services table before and after ExitBootServices().
10*62045b0eSHeinrich Schuchardt  */
11*62045b0eSHeinrich Schuchardt 
12*62045b0eSHeinrich Schuchardt #include <efi_selftest.h>
13*62045b0eSHeinrich Schuchardt 
14*62045b0eSHeinrich Schuchardt const struct efi_system_table *st;
15*62045b0eSHeinrich Schuchardt efi_status_t (EFIAPI *bs_crc32)(const void *data, efi_uintn_t data_size,
16*62045b0eSHeinrich Schuchardt 				u32 *crc32);
17*62045b0eSHeinrich Schuchardt 
18*62045b0eSHeinrich Schuchardt static int check_table(const void *table)
19*62045b0eSHeinrich Schuchardt {
20*62045b0eSHeinrich Schuchardt 	efi_status_t ret;
21*62045b0eSHeinrich Schuchardt 	u32 crc32, res;
22*62045b0eSHeinrich Schuchardt 	/* Casting from const to not const */
23*62045b0eSHeinrich Schuchardt 	struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
24*62045b0eSHeinrich Schuchardt 
25*62045b0eSHeinrich Schuchardt 	if (!hdr->signature) {
26*62045b0eSHeinrich Schuchardt 		efi_st_error("Missing header signature\n");
27*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
28*62045b0eSHeinrich Schuchardt 	}
29*62045b0eSHeinrich Schuchardt 	if (!hdr->revision) {
30*62045b0eSHeinrich Schuchardt 		efi_st_error("Missing header revision\n");
31*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
32*62045b0eSHeinrich Schuchardt 	}
33*62045b0eSHeinrich Schuchardt 	if (hdr->headersize <= sizeof(struct efi_table_hdr)) {
34*62045b0eSHeinrich Schuchardt 		efi_st_error("Incorrect headersize value\n");
35*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
36*62045b0eSHeinrich Schuchardt 	}
37*62045b0eSHeinrich Schuchardt 	if (hdr->reserved) {
38*62045b0eSHeinrich Schuchardt 		efi_st_error("Reserved header field is not zero\n");
39*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
40*62045b0eSHeinrich Schuchardt 	}
41*62045b0eSHeinrich Schuchardt 
42*62045b0eSHeinrich Schuchardt 	crc32 = hdr->crc32;
43*62045b0eSHeinrich Schuchardt 	/*
44*62045b0eSHeinrich Schuchardt 	 * Setting the crc32 of the 'const' table to zero is easier than
45*62045b0eSHeinrich Schuchardt 	 * copying
46*62045b0eSHeinrich Schuchardt 	 */
47*62045b0eSHeinrich Schuchardt 	hdr->crc32 = 0;
48*62045b0eSHeinrich Schuchardt 	ret = bs_crc32(table, hdr->headersize, &res);
49*62045b0eSHeinrich Schuchardt 	/* Reset table crc32 so it stays constant */
50*62045b0eSHeinrich Schuchardt 	hdr->crc32 = crc32;
51*62045b0eSHeinrich Schuchardt 	if (ret != EFI_ST_SUCCESS) {
52*62045b0eSHeinrich Schuchardt 		efi_st_error("CalculateCrc32 failed\n");
53*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
54*62045b0eSHeinrich Schuchardt 	}
55*62045b0eSHeinrich Schuchardt 	if (res != crc32) {
56*62045b0eSHeinrich Schuchardt 		efi_st_error("Incorrect CRC32\n");
57*62045b0eSHeinrich Schuchardt 		// return EFI_ST_FAILURE;
58*62045b0eSHeinrich Schuchardt 	}
59*62045b0eSHeinrich Schuchardt 	return EFI_ST_SUCCESS;
60*62045b0eSHeinrich Schuchardt }
61*62045b0eSHeinrich Schuchardt 
62*62045b0eSHeinrich Schuchardt /*
63*62045b0eSHeinrich Schuchardt  * Setup unit test.
64*62045b0eSHeinrich Schuchardt  *
65*62045b0eSHeinrich Schuchardt  * Check that CalculateCrc32 is working correctly.
66*62045b0eSHeinrich Schuchardt  * Check tables before ExitBootServices().
67*62045b0eSHeinrich Schuchardt  *
68*62045b0eSHeinrich Schuchardt  * @handle:	handle of the loaded image
69*62045b0eSHeinrich Schuchardt  * @systable:	system table
70*62045b0eSHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
71*62045b0eSHeinrich Schuchardt  */
72*62045b0eSHeinrich Schuchardt static int setup(const efi_handle_t handle,
73*62045b0eSHeinrich Schuchardt 		 const struct efi_system_table *systable)
74*62045b0eSHeinrich Schuchardt {
75*62045b0eSHeinrich Schuchardt 	efi_status_t ret;
76*62045b0eSHeinrich Schuchardt 	u32 res;
77*62045b0eSHeinrich Schuchardt 
78*62045b0eSHeinrich Schuchardt 	st = systable;
79*62045b0eSHeinrich Schuchardt 	bs_crc32 = systable->boottime->calculate_crc32;
80*62045b0eSHeinrich Schuchardt 
81*62045b0eSHeinrich Schuchardt 	/* Check that CalculateCrc32 is working */
82*62045b0eSHeinrich Schuchardt 	ret = bs_crc32("U-Boot", 6, &res);
83*62045b0eSHeinrich Schuchardt 	if (ret != EFI_ST_SUCCESS) {
84*62045b0eSHeinrich Schuchardt 		efi_st_error("CalculateCrc32 failed\n");
85*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
86*62045b0eSHeinrich Schuchardt 	}
87*62045b0eSHeinrich Schuchardt 	if (res != 0x134b0db4) {
88*62045b0eSHeinrich Schuchardt 		efi_st_error("Incorrect CRC32\n");
89*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
90*62045b0eSHeinrich Schuchardt 	}
91*62045b0eSHeinrich Schuchardt 
92*62045b0eSHeinrich Schuchardt 	/* Check tables before ExitBootServices() */
93*62045b0eSHeinrich Schuchardt 	if (check_table(st) != EFI_ST_SUCCESS) {
94*62045b0eSHeinrich Schuchardt 		efi_st_error("Checking system table\n");
95*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
96*62045b0eSHeinrich Schuchardt 	}
97*62045b0eSHeinrich Schuchardt 	if (check_table(st->boottime) != EFI_ST_SUCCESS) {
98*62045b0eSHeinrich Schuchardt 		efi_st_error("Checking boottime table\n");
99*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
100*62045b0eSHeinrich Schuchardt 	}
101*62045b0eSHeinrich Schuchardt 	if (check_table(st->runtime) != EFI_ST_SUCCESS) {
102*62045b0eSHeinrich Schuchardt 		efi_st_error("Checking runtime table\n");
103*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
104*62045b0eSHeinrich Schuchardt 	}
105*62045b0eSHeinrich Schuchardt 
106*62045b0eSHeinrich Schuchardt 	return EFI_ST_SUCCESS;
107*62045b0eSHeinrich Schuchardt }
108*62045b0eSHeinrich Schuchardt 
109*62045b0eSHeinrich Schuchardt /*
110*62045b0eSHeinrich Schuchardt  * Execute unit test
111*62045b0eSHeinrich Schuchardt  *
112*62045b0eSHeinrich Schuchardt  * Check tables after ExitBootServices()
113*62045b0eSHeinrich Schuchardt  *
114*62045b0eSHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
115*62045b0eSHeinrich Schuchardt  */
116*62045b0eSHeinrich Schuchardt static int execute(void)
117*62045b0eSHeinrich Schuchardt {
118*62045b0eSHeinrich Schuchardt 	if (check_table(st) != EFI_ST_SUCCESS) {
119*62045b0eSHeinrich Schuchardt 		efi_st_error("Checking system table\n");
120*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
121*62045b0eSHeinrich Schuchardt 	}
122*62045b0eSHeinrich Schuchardt 	if (check_table(st->runtime) != EFI_ST_SUCCESS) {
123*62045b0eSHeinrich Schuchardt 		efi_st_error("Checking runtime table\n");
124*62045b0eSHeinrich Schuchardt 		return EFI_ST_FAILURE;
125*62045b0eSHeinrich Schuchardt 	}
126*62045b0eSHeinrich Schuchardt 
127*62045b0eSHeinrich Schuchardt 	/*
128*62045b0eSHeinrich Schuchardt 	 * We cannot call SetVirtualAddressMap() and recheck the runtime
129*62045b0eSHeinrich Schuchardt 	 * table afterwards because this would invalidate the addresses of the
130*62045b0eSHeinrich Schuchardt 	 * unit tests.
131*62045b0eSHeinrich Schuchardt 	 */
132*62045b0eSHeinrich Schuchardt 
133*62045b0eSHeinrich Schuchardt 	return EFI_ST_SUCCESS;
134*62045b0eSHeinrich Schuchardt }
135*62045b0eSHeinrich Schuchardt 
136*62045b0eSHeinrich Schuchardt EFI_UNIT_TEST(crc32) = {
137*62045b0eSHeinrich Schuchardt 	.name = "crc32",
138*62045b0eSHeinrich Schuchardt 	.phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
139*62045b0eSHeinrich Schuchardt 	.setup = setup,
140*62045b0eSHeinrich Schuchardt 	.execute = execute,
141*62045b0eSHeinrich Schuchardt };
142