blob: 792de304c15fdab27e38e223bf3d946908efb475 [file] [log] [blame]
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
4 */
5
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +02006#include <command.h>
7#include <errno.h>
8#include <fdt_support.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +020010#include <malloc.h>
11#include <tee/optee.h>
12
13#include <linux/sizes.h>
14
15#include <test/ut.h>
16#include <test/optee.h>
17#include <test/suites.h>
18
19/* 4k ought to be enough for anybody */
20#define FDT_COPY_SIZE (4 * SZ_1K)
21
22extern u32 __dtb_test_optee_base_begin;
23extern u32 __dtb_test_optee_optee_begin;
24extern u32 __dtb_test_optee_no_optee_begin;
25
26static void *fdt;
27static bool expect_success;
28
Simon Glassb0f3bbd2025-02-07 11:30:50 -070029static int optee_test_init(struct unit_test_state *uts)
30{
31 void *fdt_optee = &__dtb_test_optee_optee_begin;
32 void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
33 void *fdt_base = &__dtb_test_optee_base_begin;
34 int ret = -ENOMEM;
35
36 ut_assertok(fdt_check_header(fdt_base));
37 ut_assertok(fdt_check_header(fdt_optee));
38 ut_assertok(fdt_check_header(fdt_no_optee));
39
40 fdt = malloc(FDT_COPY_SIZE);
41 if (!fdt)
42 return ret;
43
44 /*
45 * Resize the FDT to 4k so that we have room to operate on
46 *
47 * (and relocate it since the memory might be mapped
48 * read-only)
49 */
50 ut_assertok(fdt_open_into(fdt_base, fdt, FDT_COPY_SIZE));
51
52 return 0;
53}
54OPTEE_TEST_INIT(optee_test_init, 0);
55
56static int optee_test_uninit(struct unit_test_state *uts)
57{
58 free(fdt);
59
60 return 0;
61}
62OPTEE_TEST_UNINIT(optee_test_uninit, 0);
63
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +020064static int optee_fdt_firmware(struct unit_test_state *uts)
65{
66 const void *prop;
67 int offs, len;
68
69 offs = fdt_path_offset(fdt, "/firmware/optee");
70 ut_assert(expect_success ? offs >= 0 : offs < 0);
71
72 /* only continue if we have an optee node */
73 if (offs < 0)
74 return CMD_RET_SUCCESS;
75
76 prop = fdt_getprop(fdt, offs, "compatible", &len);
77 ut_assertok(strncmp((const char *)prop, "linaro,optee-tz", len));
78
79 prop = fdt_getprop(fdt, offs, "method", &len);
80 ut_assert(strncmp(prop, "hvc", 3) == 0 || strncmp(prop, "smc", 3) == 0);
81
82 return CMD_RET_SUCCESS;
83}
84OPTEE_TEST(optee_fdt_firmware, 0);
85
86static int optee_fdt_protected_memory(struct unit_test_state *uts)
87{
88 int offs, subnode;
89 bool found;
90
91 offs = fdt_path_offset(fdt, "/firmware/optee");
92 ut_assert(expect_success ? offs >= 0 : offs < 0);
93
94 /* only continue if we have an optee node */
95 if (offs < 0)
96 return CMD_RET_SUCCESS;
97
98 /* optee inserts its memory regions as reserved-memory nodes */
99 offs = fdt_subnode_offset(fdt, 0, "reserved-memory");
100 ut_assert(offs >= 0);
101
102 subnode = fdt_first_subnode(fdt, offs);
103 ut_assert(subnode);
104
105 found = 0;
106 while (subnode >= 0) {
107 const char *name = fdt_get_name(fdt, subnode, NULL);
108 struct fdt_resource res;
109
110 ut_assert(name);
111
112 /* only handle optee reservations */
113 if (strncmp(name, "optee", 5))
114 continue;
115
116 found = true;
117
118 /* check if this subnode has a reg property */
119 ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res));
120 subnode = fdt_next_subnode(fdt, subnode);
121 }
122
123 ut_assert(found);
124
125 return CMD_RET_SUCCESS;
126}
127OPTEE_TEST(optee_fdt_protected_memory, 0);
128
Simon Glassed38aef2020-05-10 11:40:03 -0600129int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200130{
Simon Glassb15512c2025-01-20 14:25:32 -0700131 struct unit_test *tests = UNIT_TEST_SUITE_START(optee);
132 const int n_ents = UNIT_TEST_SUITE_COUNT(optee);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200133 struct unit_test_state *uts;
134 void *fdt_optee = &__dtb_test_optee_optee_begin;
135 void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
136 void *fdt_base = &__dtb_test_optee_base_begin;
137 int ret = -ENOMEM;
138
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200139 /*
140 * (1) Try to copy optee nodes from empty dt.
141 * This should still run successfully.
142 */
143 ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt));
144
145 expect_success = false;
Philippe Reynes1f99f842019-12-17 19:07:04 +0100146 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200147
148 /* (2) Try to copy optee nodes from prefilled dt */
149 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
150
151 expect_success = true;
Philippe Reynes1f99f842019-12-17 19:07:04 +0100152 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200153
154 /* (3) Try to copy OP-TEE nodes into a already filled DT */
155 ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE));
156 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
157
158 expect_success = true;
Philippe Reynes1f99f842019-12-17 19:07:04 +0100159 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200160
161 free(fdt);
162 return ret;
163}