blob: 7256a270c1217e5db0931475143f30da893928ee [file] [log] [blame]
/* 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);
}