162045b0eSHeinrich Schuchardt // SPDX-License-Identifier: GPL-2.0+ 262045b0eSHeinrich Schuchardt /* 362045b0eSHeinrich Schuchardt * efi_selftest_crc32 462045b0eSHeinrich Schuchardt * 562045b0eSHeinrich Schuchardt * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> 662045b0eSHeinrich Schuchardt * 762045b0eSHeinrich Schuchardt * This unit test checks the CalculateCrc32 bootservice and checks the 8*d8b2216cSHeinrich Schuchardt * headers of the system table, the boot services table, and the runtime 962045b0eSHeinrich Schuchardt * services table before and after ExitBootServices(). 1062045b0eSHeinrich Schuchardt */ 1162045b0eSHeinrich Schuchardt 1262045b0eSHeinrich Schuchardt #include <efi_selftest.h> 1362045b0eSHeinrich Schuchardt 1462045b0eSHeinrich Schuchardt const struct efi_system_table *st; 1562045b0eSHeinrich Schuchardt efi_status_t (EFIAPI *bs_crc32)(const void *data, efi_uintn_t data_size, 1662045b0eSHeinrich Schuchardt u32 *crc32); 1762045b0eSHeinrich Schuchardt 1862045b0eSHeinrich Schuchardt static int check_table(const void *table) 1962045b0eSHeinrich Schuchardt { 2062045b0eSHeinrich Schuchardt efi_status_t ret; 2162045b0eSHeinrich Schuchardt u32 crc32, res; 22*d8b2216cSHeinrich Schuchardt /* Casting from constant to not constant */ 2362045b0eSHeinrich Schuchardt struct efi_table_hdr *hdr = (struct efi_table_hdr *)table; 2462045b0eSHeinrich Schuchardt 2562045b0eSHeinrich Schuchardt if (!hdr->signature) { 2662045b0eSHeinrich Schuchardt efi_st_error("Missing header signature\n"); 2762045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 2862045b0eSHeinrich Schuchardt } 2962045b0eSHeinrich Schuchardt if (!hdr->revision) { 3062045b0eSHeinrich Schuchardt efi_st_error("Missing header revision\n"); 3162045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 3262045b0eSHeinrich Schuchardt } 3362045b0eSHeinrich Schuchardt if (hdr->headersize <= sizeof(struct efi_table_hdr)) { 3462045b0eSHeinrich Schuchardt efi_st_error("Incorrect headersize value\n"); 3562045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 3662045b0eSHeinrich Schuchardt } 3762045b0eSHeinrich Schuchardt if (hdr->reserved) { 3862045b0eSHeinrich Schuchardt efi_st_error("Reserved header field is not zero\n"); 3962045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 4062045b0eSHeinrich Schuchardt } 4162045b0eSHeinrich Schuchardt 4262045b0eSHeinrich Schuchardt crc32 = hdr->crc32; 4362045b0eSHeinrich Schuchardt /* 4462045b0eSHeinrich Schuchardt * Setting the crc32 of the 'const' table to zero is easier than 4562045b0eSHeinrich Schuchardt * copying 4662045b0eSHeinrich Schuchardt */ 4762045b0eSHeinrich Schuchardt hdr->crc32 = 0; 4862045b0eSHeinrich Schuchardt ret = bs_crc32(table, hdr->headersize, &res); 4962045b0eSHeinrich Schuchardt /* Reset table crc32 so it stays constant */ 5062045b0eSHeinrich Schuchardt hdr->crc32 = crc32; 5162045b0eSHeinrich Schuchardt if (ret != EFI_ST_SUCCESS) { 5262045b0eSHeinrich Schuchardt efi_st_error("CalculateCrc32 failed\n"); 5362045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 5462045b0eSHeinrich Schuchardt } 5562045b0eSHeinrich Schuchardt if (res != crc32) { 5662045b0eSHeinrich Schuchardt efi_st_error("Incorrect CRC32\n"); 5762045b0eSHeinrich Schuchardt // return EFI_ST_FAILURE; 5862045b0eSHeinrich Schuchardt } 5962045b0eSHeinrich Schuchardt return EFI_ST_SUCCESS; 6062045b0eSHeinrich Schuchardt } 6162045b0eSHeinrich Schuchardt 6262045b0eSHeinrich Schuchardt /* 6362045b0eSHeinrich Schuchardt * Setup unit test. 6462045b0eSHeinrich Schuchardt * 6562045b0eSHeinrich Schuchardt * Check that CalculateCrc32 is working correctly. 6662045b0eSHeinrich Schuchardt * Check tables before ExitBootServices(). 6762045b0eSHeinrich Schuchardt * 6862045b0eSHeinrich Schuchardt * @handle: handle of the loaded image 6962045b0eSHeinrich Schuchardt * @systable: system table 7062045b0eSHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success 7162045b0eSHeinrich Schuchardt */ 7262045b0eSHeinrich Schuchardt static int setup(const efi_handle_t handle, 7362045b0eSHeinrich Schuchardt const struct efi_system_table *systable) 7462045b0eSHeinrich Schuchardt { 7562045b0eSHeinrich Schuchardt efi_status_t ret; 7662045b0eSHeinrich Schuchardt u32 res; 7762045b0eSHeinrich Schuchardt 7862045b0eSHeinrich Schuchardt st = systable; 7962045b0eSHeinrich Schuchardt bs_crc32 = systable->boottime->calculate_crc32; 8062045b0eSHeinrich Schuchardt 8162045b0eSHeinrich Schuchardt /* Check that CalculateCrc32 is working */ 8262045b0eSHeinrich Schuchardt ret = bs_crc32("U-Boot", 6, &res); 8362045b0eSHeinrich Schuchardt if (ret != EFI_ST_SUCCESS) { 8462045b0eSHeinrich Schuchardt efi_st_error("CalculateCrc32 failed\n"); 8562045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 8662045b0eSHeinrich Schuchardt } 8762045b0eSHeinrich Schuchardt if (res != 0x134b0db4) { 8862045b0eSHeinrich Schuchardt efi_st_error("Incorrect CRC32\n"); 8962045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 9062045b0eSHeinrich Schuchardt } 9162045b0eSHeinrich Schuchardt 9262045b0eSHeinrich Schuchardt /* Check tables before ExitBootServices() */ 9362045b0eSHeinrich Schuchardt if (check_table(st) != EFI_ST_SUCCESS) { 9462045b0eSHeinrich Schuchardt efi_st_error("Checking system table\n"); 9562045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 9662045b0eSHeinrich Schuchardt } 9762045b0eSHeinrich Schuchardt if (check_table(st->boottime) != EFI_ST_SUCCESS) { 9862045b0eSHeinrich Schuchardt efi_st_error("Checking boottime table\n"); 9962045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 10062045b0eSHeinrich Schuchardt } 10162045b0eSHeinrich Schuchardt if (check_table(st->runtime) != EFI_ST_SUCCESS) { 10262045b0eSHeinrich Schuchardt efi_st_error("Checking runtime table\n"); 10362045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 10462045b0eSHeinrich Schuchardt } 10562045b0eSHeinrich Schuchardt 10662045b0eSHeinrich Schuchardt return EFI_ST_SUCCESS; 10762045b0eSHeinrich Schuchardt } 10862045b0eSHeinrich Schuchardt 10962045b0eSHeinrich Schuchardt /* 11062045b0eSHeinrich Schuchardt * Execute unit test 11162045b0eSHeinrich Schuchardt * 11262045b0eSHeinrich Schuchardt * Check tables after ExitBootServices() 11362045b0eSHeinrich Schuchardt * 11462045b0eSHeinrich Schuchardt * @return: EFI_ST_SUCCESS for success 11562045b0eSHeinrich Schuchardt */ 11662045b0eSHeinrich Schuchardt static int execute(void) 11762045b0eSHeinrich Schuchardt { 11862045b0eSHeinrich Schuchardt if (check_table(st) != EFI_ST_SUCCESS) { 11962045b0eSHeinrich Schuchardt efi_st_error("Checking system table\n"); 12062045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 12162045b0eSHeinrich Schuchardt } 12262045b0eSHeinrich Schuchardt if (check_table(st->runtime) != EFI_ST_SUCCESS) { 12362045b0eSHeinrich Schuchardt efi_st_error("Checking runtime table\n"); 12462045b0eSHeinrich Schuchardt return EFI_ST_FAILURE; 12562045b0eSHeinrich Schuchardt } 12662045b0eSHeinrich Schuchardt 12762045b0eSHeinrich Schuchardt /* 12862045b0eSHeinrich Schuchardt * We cannot call SetVirtualAddressMap() and recheck the runtime 12962045b0eSHeinrich Schuchardt * table afterwards because this would invalidate the addresses of the 13062045b0eSHeinrich Schuchardt * unit tests. 13162045b0eSHeinrich Schuchardt */ 13262045b0eSHeinrich Schuchardt 13362045b0eSHeinrich Schuchardt return EFI_ST_SUCCESS; 13462045b0eSHeinrich Schuchardt } 13562045b0eSHeinrich Schuchardt 13662045b0eSHeinrich Schuchardt EFI_UNIT_TEST(crc32) = { 13762045b0eSHeinrich Schuchardt .name = "crc32", 13862045b0eSHeinrich Schuchardt .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT, 13962045b0eSHeinrich Schuchardt .setup = setup, 14062045b0eSHeinrich Schuchardt .execute = execute, 14162045b0eSHeinrich Schuchardt }; 142