tests: add OP-TEE test suite

OP-TEE can get supplied with a devicetree and will then insert
its firmware node and reserved-memory sections into it.
As this devicetree often is not the one supplied to a later
loaded kernel, a previous commit added functionality to transfer
these nodes onto that new devicetree.

To make sure this functionality stays intact, also add a test
for the transfer functionality.

Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Heiko Stuebner 2019-10-23 16:46:41 +02:00 committed by Simon Glass
parent 6ccb05eae0
commit 96383bdfe4
11 changed files with 250 additions and 0 deletions

View file

@ -751,6 +751,7 @@ libs-$(CONFIG_API) += api/
libs-$(CONFIG_HAS_POST) += post/
libs-$(CONFIG_UNIT_TEST) += test/ test/dm/
libs-$(CONFIG_UT_ENV) += test/env/
libs-$(CONFIG_UT_OPTEE) += test/optee/
libs-$(CONFIG_UT_OVERLAY) += test/overlay/
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)

14
include/test/optee.h Normal file
View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
*/
#ifndef __TEST_OPTEE_H__
#define __TEST_OPTEE_H__
#include <test/test.h>
/* Declare a new environment test */
#define OPTEE_TEST(_name, _flags) UNIT_TEST(_name, _flags, optee_test)
#endif /* __TEST_OPTEE_H__ */

View file

@ -28,6 +28,7 @@ int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_lib(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_optee(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);

View file

@ -33,4 +33,5 @@ config UT_UNICODE
source "test/dm/Kconfig"
source "test/env/Kconfig"
source "test/optee/Kconfig"
source "test/overlay/Kconfig"

View file

@ -43,6 +43,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
#if defined(CONFIG_UT_ENV)
U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
#endif
#ifdef CONFIG_UT_OPTEE
U_BOOT_CMD_MKENT(optee, CONFIG_SYS_MAXARGS, 1, do_ut_optee, "", ""),
#endif
#ifdef CONFIG_UT_OVERLAY
U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
#endif
@ -114,6 +117,9 @@ static char ut_help_text[] =
#ifdef CONFIG_UT_LIB
"ut lib [test-name] - test library functions\n"
#endif
#ifdef CONFIG_UT_OPTEE
"ut optee [test-name]\n"
#endif
#ifdef CONFIG_UT_OVERLAY
"ut overlay [test-name]\n"
#endif

7
test/optee/Kconfig Normal file
View file

@ -0,0 +1,7 @@
config UT_OPTEE
bool "Enable OP-TEE Unit Tests"
depends on UNIT_TEST && OF_CONTROL && OPTEE
default y
help
This enables the 'ut optee' command which runs a series of unit
tests on the optee library code..

13
test/optee/Makefile Normal file
View file

@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
# Test files
obj-y += cmd_ut_optee.o
DTC_FLAGS += -@
# DT overlays
obj-y += test-optee-base.dtb.o
obj-y += test-optee-optee.dtb.o
obj-y += test-optee-no-optee.dtb.o

149
test/optee/cmd_ut_optee.c Normal file
View file

@ -0,0 +1,149 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
*/
#include <common.h>
#include <command.h>
#include <errno.h>
#include <fdt_support.h>
#include <malloc.h>
#include <tee/optee.h>
#include <linux/sizes.h>
#include <test/ut.h>
#include <test/optee.h>
#include <test/suites.h>
/* 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_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;
}
OPTEE_TEST(optee_fdt_firmware, 0);
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;
}
OPTEE_TEST(optee_fdt_protected_memory, 0);
int do_ut_optee(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct unit_test *tests = ll_entry_start(struct unit_test,
optee_test);
const int n_ents = ll_entry_count(struct unit_test, optee_test);
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;
uts = calloc(1, sizeof(*uts));
if (!uts)
return -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;
/*
* 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(fdt_base, fdt, FDT_COPY_SIZE));
/*
* (1) Try to copy optee nodes from empty dt.
* This should still run successfully.
*/
ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt));
expect_success = false;
ret = cmd_ut_category("optee", tests, n_ents, argc, argv);
/* (2) Try to copy optee nodes from prefilled dt */
ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
expect_success = true;
ret = cmd_ut_category("optee", tests, n_ents, argc, argv);
/* (3) Try to copy OP-TEE nodes into a already filled DT */
ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE));
ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
expect_success = true;
ret = cmd_ut_category("optee", tests, n_ents, argc, argv);
free(fdt);
return ret;
}

View file

@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
*/
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <2>;
};

View file

@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
*/
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <2>;
};

View file

@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
*/
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <2>;
firmware {
optee {
compatible = "linaro,optee-tz";
method = "smc";
};
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
optee_shm@32000000 {
reg = <0x00 0x32000000 0x00 0x400000>;
};
optee_core@30000000 {
reg = <0x00 0x30000000 0x00 0x2000000>;
};
};
};