mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-12-19 16:31:27 +01:00
This was apparently not built for several years: Since a2535243e011,
optee_copy_fdt_nodes implicitly works against the U-Boot dt. We
therefore have to tweak its reference before using the function and
restore things afterwards.
If it had been built, actually trying it out would have failed next: We
need CONFIG_OPTEE_LIB to actually build the function that is primarily
being tested here. And we need to re-initialize target fdt, now that the
tests may run in random order.
Fixes: a2535243e011 ("lib: optee: migration optee_copy_fdt_nodes for OF_LIVE support")
Fixes: ba2feaf41435 ("test: Split optee tests into three functions")
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
192 lines
4.6 KiB
C
192 lines
4.6 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
|
|
*/
|
|
|
|
#include <command.h>
|
|
#include <errno.h>
|
|
#include <fdtdec.h>
|
|
#include <fdt_support.h>
|
|
#include <log.h>
|
|
#include <malloc.h>
|
|
#include <tee/optee.h>
|
|
#include <asm/global_data.h>
|
|
|
|
#include <linux/sizes.h>
|
|
|
|
#include <test/ut.h>
|
|
#include <test/optee.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
/* 4k ought to be enough for anybody */
|
|
#define FDT_COPY_SIZE (4 * SZ_1K)
|
|
|
|
extern u32 __dtb_test_optee_base_begin;
|
|
extern u32 __dtb_test_optee_optee_begin;
|
|
extern u32 __dtb_test_optee_no_optee_begin;
|
|
|
|
static void *fdt;
|
|
static bool expect_success;
|
|
|
|
static int optee_test_init(struct unit_test_state *uts)
|
|
{
|
|
void *fdt_optee = &__dtb_test_optee_optee_begin;
|
|
void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
|
|
void *fdt_base = &__dtb_test_optee_base_begin;
|
|
int ret = -ENOMEM;
|
|
|
|
ut_assertok(fdt_check_header(fdt_base));
|
|
ut_assertok(fdt_check_header(fdt_optee));
|
|
ut_assertok(fdt_check_header(fdt_no_optee));
|
|
|
|
fdt = malloc(FDT_COPY_SIZE);
|
|
if (!fdt)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
OPTEE_TEST_INIT(optee_test_init, 0);
|
|
|
|
static int optee_test_uninit(struct unit_test_state *uts)
|
|
{
|
|
free(fdt);
|
|
|
|
return 0;
|
|
}
|
|
OPTEE_TEST_UNINIT(optee_test_uninit, 0);
|
|
|
|
static int optee_fdt_firmware(struct unit_test_state *uts)
|
|
{
|
|
const void *prop;
|
|
int offs, len;
|
|
|
|
offs = fdt_path_offset(fdt, "/firmware/optee");
|
|
ut_assert(expect_success ? offs >= 0 : offs < 0);
|
|
|
|
/* only continue if we have an optee node */
|
|
if (offs < 0)
|
|
return CMD_RET_SUCCESS;
|
|
|
|
prop = fdt_getprop(fdt, offs, "compatible", &len);
|
|
ut_assertok(strncmp((const char *)prop, "linaro,optee-tz", len));
|
|
|
|
prop = fdt_getprop(fdt, offs, "method", &len);
|
|
ut_assert(strncmp(prop, "hvc", 3) == 0 || strncmp(prop, "smc", 3) == 0);
|
|
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
static int optee_fdt_protected_memory(struct unit_test_state *uts)
|
|
{
|
|
int offs, subnode;
|
|
bool found;
|
|
|
|
offs = fdt_path_offset(fdt, "/firmware/optee");
|
|
ut_assert(expect_success ? offs >= 0 : offs < 0);
|
|
|
|
/* only continue if we have an optee node */
|
|
if (offs < 0)
|
|
return CMD_RET_SUCCESS;
|
|
|
|
/* optee inserts its memory regions as reserved-memory nodes */
|
|
offs = fdt_subnode_offset(fdt, 0, "reserved-memory");
|
|
ut_assert(offs >= 0);
|
|
|
|
subnode = fdt_first_subnode(fdt, offs);
|
|
ut_assert(subnode);
|
|
|
|
found = 0;
|
|
while (subnode >= 0) {
|
|
const char *name = fdt_get_name(fdt, subnode, NULL);
|
|
struct fdt_resource res;
|
|
|
|
ut_assert(name);
|
|
|
|
/* only handle optee reservations */
|
|
if (strncmp(name, "optee", 5))
|
|
continue;
|
|
|
|
found = true;
|
|
|
|
/* check if this subnode has a reg property */
|
|
ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res));
|
|
subnode = fdt_next_subnode(fdt, subnode);
|
|
}
|
|
|
|
ut_assert(found);
|
|
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
/* (1) Try to copy optee nodes from empty dt */
|
|
static int optee_fdt_copy_empty(struct unit_test_state *uts)
|
|
{
|
|
void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
|
|
const void *fdt_blob = gd->fdt_blob;
|
|
|
|
/*
|
|
* Resize the FDT to 4k so that we have room to operate on
|
|
*
|
|
* (and relocate it since the memory might be mapped
|
|
* read-only)
|
|
*/
|
|
ut_assertok(fdt_open_into(&__dtb_test_optee_base_begin, fdt,
|
|
FDT_COPY_SIZE));
|
|
|
|
/* This should still run successfully */
|
|
gd->fdt_blob = fdt_no_optee;
|
|
ut_assertok(optee_copy_fdt_nodes(fdt));
|
|
gd->fdt_blob = fdt_blob;
|
|
|
|
expect_success = false;
|
|
ut_assertok(optee_fdt_firmware(uts));
|
|
ut_assertok(optee_fdt_protected_memory(uts));
|
|
|
|
return 0;
|
|
}
|
|
OPTEE_TEST(optee_fdt_copy_empty, 0);
|
|
|
|
/* (2) Try to copy optee nodes from prefilled dt */
|
|
static int optee_fdt_copy_prefilled(struct unit_test_state *uts)
|
|
{
|
|
void *fdt_optee = &__dtb_test_optee_optee_begin;
|
|
const void *fdt_blob = gd->fdt_blob;
|
|
|
|
ut_assertok(fdt_open_into(&__dtb_test_optee_base_begin, fdt,
|
|
FDT_COPY_SIZE));
|
|
|
|
gd->fdt_blob = fdt_optee;
|
|
ut_assertok(optee_copy_fdt_nodes(fdt));
|
|
gd->fdt_blob = fdt_blob;
|
|
|
|
expect_success = true;
|
|
ut_assertok(optee_fdt_firmware(uts));
|
|
ut_assertok(optee_fdt_protected_memory(uts));
|
|
|
|
return 0;
|
|
}
|
|
OPTEE_TEST(optee_fdt_copy_prefilled, 0);
|
|
|
|
/* (3) Try to copy OP-TEE nodes into a already filled DT */
|
|
static int optee_fdt_copy_already_filled(struct unit_test_state *uts)
|
|
{
|
|
void *fdt_optee = &__dtb_test_optee_optee_begin;
|
|
const void *fdt_blob = gd->fdt_blob;
|
|
|
|
ut_assertok(fdt_open_into(&__dtb_test_optee_base_begin, fdt,
|
|
FDT_COPY_SIZE));
|
|
|
|
ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE));
|
|
gd->fdt_blob = fdt_optee;
|
|
ut_assertok(optee_copy_fdt_nodes(fdt));
|
|
gd->fdt_blob = fdt_blob;
|
|
|
|
expect_success = true;
|
|
ut_assertok(optee_fdt_firmware(uts));
|
|
ut_assertok(optee_fdt_protected_memory(uts));
|
|
|
|
return 0;
|
|
}
|
|
OPTEE_TEST(optee_fdt_copy_already_filled, 0);
|