diff options
-rw-r--r-- | tests/lib/Makefile.inc | 10 | ||||
-rw-r--r-- | tests/lib/cbmem_stage_cache-test.c | 194 |
2 files changed, 204 insertions, 0 deletions
diff --git a/tests/lib/Makefile.inc b/tests/lib/Makefile.inc index 0792776fb8..6750353321 100644 --- a/tests/lib/Makefile.inc +++ b/tests/lib/Makefile.inc @@ -30,6 +30,7 @@ tests-y += coreboot_table-test tests-y += rtc-test tests-y += spd_cache-ddr3-test tests-y += spd_cache-ddr4-test +tests-y += cbmem_stage_cache-test string-test-srcs += tests/lib/string-test.c string-test-srcs += src/lib/string.c @@ -167,3 +168,12 @@ spd_cache-ddr4-test-config += CONFIG_SPD_CACHE_FMAP_NAME=\"RW_SPD_CACHE\" \ CONFIG_DIMM_MAX=4 CONFIG_DIMM_SPD_SIZE=512 \ CONFIG_BOOT_DEVICE_MEMORY_MAPPED=1 spd_cache-ddr4-test-cflags += -D__TEST_SPD_CACHE_DDR=4 + +cbmem_stage_cache-test-srcs += tests/lib/cbmem_stage_cache-test.c +cbmem_stage_cache-test-srcs += tests/stubs/console.c +cbmem_stage_cache-test-srcs += src/lib/cbmem_stage_cache.c +cbmem_stage_cache-test-srcs += src/lib/imd_cbmem.c +cbmem_stage_cache-test-srcs += src/lib/imd.c +cbmem_stage_cache-test-cflags += -I 3rdparty/vboot/firmware/include +cbmem_stage_cache-test-cflags += -I $(src)/commonlib/include +cbmem_stage_cache-test-config += CONFIG_CBMEM_STAGE_CACHE=1 diff --git a/tests/lib/cbmem_stage_cache-test.c b/tests/lib/cbmem_stage_cache-test.c new file mode 100644 index 0000000000..24ba095420 --- /dev/null +++ b/tests/lib/cbmem_stage_cache-test.c @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <tests/test.h> +#include <cbmem.h> +#include <commonlib/cbmem_id.h> +#include <stage_cache.h> + +#define CBMEM_SIZE (32 * KiB) + +/* CBMEM top pointer used by implementation. */ +extern uintptr_t _cbmem_top_ptr; + +void cbmem_run_init_hooks(int is_recovery) +{ +} + +static void *get_cbmem_ptr(void) +{ + void *cbmem_top_ptr = (void *)_cbmem_top_ptr; + if (cbmem_top_ptr) + return cbmem_top_ptr - CBMEM_SIZE; + else + return NULL; +} + +static void clear_cbmem(void) +{ + void *ptr = get_cbmem_ptr(); + if (ptr) + memset(ptr, 0, CBMEM_SIZE); +} + +int setup_test(void **state) +{ + void *cbmem_top_ptr = malloc(CBMEM_SIZE); + + if (!cbmem_top_ptr) + return -1; + + _cbmem_top_ptr = (uintptr_t)cbmem_top_ptr + CBMEM_SIZE; + clear_cbmem(); + cbmem_initialize_empty(); + return 0; +} + +int teardown_test(void **state) +{ + if (_cbmem_top_ptr && (_cbmem_top_ptr - CBMEM_SIZE)) + free((void *)(_cbmem_top_ptr - CBMEM_SIZE)); + + _cbmem_top_ptr = 0; + return 0; +} + +/* This function is used as prog_entry of struct prog to prevent potential calls to unaccessible + or incorrect addresses. */ +void prog_entry_mock(void *arg) +{ +} + +/* This test checks if stage_cache_add() correctly adds CBMEM_ID_STAGE_x_META + and CBMEM_ID_STAGEx_CACHE entries to cbmem. stage_cache_add() must create meta + entry containing load address, entry address and argument for it. It also must + copy buffer pointer pointed by start pointer of prog struct to cache entry. */ +void test_stage_cache_add(void **state) +{ + const int id = 12; + int arg = 0xC14; + struct stage_cache *meta = NULL; + uint8_t *prog_data_buf = NULL; + const size_t data_sz = 4 * KiB; + uint8_t *data = malloc(data_sz); + struct prog prog_data = {0}; + + assert_non_null(data); + memset(data, 0xDB, data_sz); + prog_data = (struct prog)PROG_INIT(PROG_ROMSTAGE, "test_prog"); + prog_set_area(&prog_data, data, data_sz); + prog_set_entry(&prog_data, prog_entry_mock, &arg); + + stage_cache_add(id, &prog_data); + + meta = cbmem_find(CBMEM_ID_STAGEx_META + id); + assert_non_null(meta); + assert_int_equal(meta->load_addr, (uintptr_t)prog_start(&prog_data)); + assert_int_equal(meta->entry_addr, (uintptr_t)prog_entry(&prog_data)); + assert_int_equal(meta->arg, (uintptr_t)prog_entry_arg(&prog_data)); + + prog_data_buf = cbmem_find(CBMEM_ID_STAGEx_CACHE + id); + assert_non_null(prog_data_buf); + assert_memory_equal(data, prog_data_buf, data_sz); + + free(data); +} + +/* This test checks if stage_cache_add_raw() correctly creates entry with data from + provided buffer. Data should be accessible using cbmem_find() with + (CBMEM_ID_STAGEx_RAW + id) parameter. */ +void test_stage_cache_add_raw(void **state) +{ + const int id = 55; + const size_t data_sz = 8 * KiB; + uint8_t *data = malloc(data_sz); + uint8_t *data_raw = NULL; + + assert_non_null(data); + memset(data, 0x91, data_sz); + + stage_cache_add_raw(id, data, data_sz); + + data_raw = cbmem_find(CBMEM_ID_STAGEx_RAW + id); + assert_non_null(data_raw); + assert_memory_equal(data_raw, data, data_sz); + + free(data); +} + + +/* This test checks if stage_cache_get_raw() correctly extracts base and size of previously + added entry. */ +void test_stage_cache_get_raw(void **state) +{ + const int id = 23; + const size_t data_sz = 3 * KiB; + uint8_t *data = malloc(data_sz); + size_t data_out_sz = 0; + uint8_t *data_out = NULL; + + assert_non_null(data); + memset(data, 0x3c, data_sz); + stage_cache_add_raw(id, data, data_sz); + + stage_cache_get_raw(id, (void **)&data_out, &data_out_sz); + + assert_int_equal(data_sz, data_out_sz); + assert_memory_equal(data, data_out, data_sz); + + free(data); +} + +/* This test checks if stage_cache_load_stage() correctly loads previously added stage data + and its metadata. */ +void test_stage_cache_load_stage(void **state) +{ + int id = 0xCC; + struct prog prog_out = {0}; + const size_t data_sz = 7 * KiB; + uint8_t *data = malloc(data_sz); + uint8_t *data_bak = malloc(data_sz); + struct prog prog_data = {0}; + int arg = 0x33224455; + + assert_non_null(data); + assert_non_null(data_bak); + memset(data, 0x45, data_sz); + + prog_data = (struct prog)PROG_INIT(PROG_RAMSTAGE, "test_prog"); + prog_set_area(&prog_data, data, data_sz); + prog_set_entry(&prog_data, prog_entry_mock, &arg); + stage_cache_add(id, &prog_data); + + /* Copy current data to backup buffer and clear current buffer */ + memcpy(data_bak, data, data_sz); + memset(data, 0, data_sz); + + /* Load stage data. Data should be returned to the same buffer. */ + stage_cache_load_stage(id, &prog_out); + + /* Data should be same as it was before */ + assert_memory_equal(data, data_bak, data_sz); + assert_int_equal(prog_start(&prog_data), prog_start(&prog_out)); + assert_int_equal(prog_size(&prog_data), prog_size(&prog_out)); + assert_ptr_equal(prog_entry(&prog_data), prog_entry(&prog_out)); + assert_ptr_equal(prog_entry_arg(&prog_data), prog_entry_arg(&prog_out)); + + free(data_bak); + free(data); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_stage_cache_add, + setup_test, teardown_test), + cmocka_unit_test_setup_teardown(test_stage_cache_add_raw, + setup_test, teardown_test), + cmocka_unit_test_setup_teardown(test_stage_cache_get_raw, + setup_test, teardown_test), + cmocka_unit_test_setup_teardown(test_stage_cache_load_stage, + setup_test, teardown_test), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} |