| /* SPDX-License-Identifier: GPL-2.0-only */ |
| |
| #include <tests/test.h> |
| #include <cbmem.h> |
| #include <commonlib/bsd/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 cb_run_group_tests(tests, NULL, NULL); |
| } |