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