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