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