efi_loader: validate load option
[oweals/u-boot.git] / lib / efi_selftest / efi_selftest_crc32.c
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
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  */
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  */
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 };