blob: 71833e5f6ab9da5a3c70d4e9b698bfdb16e4cf19 [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}
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +020084
85static int optee_fdt_protected_memory(struct unit_test_state *uts)
86{
87 int offs, subnode;
88 bool found;
89
90 offs = fdt_path_offset(fdt, "/firmware/optee");
91 ut_assert(expect_success ? offs >= 0 : offs < 0);
92
93 /* only continue if we have an optee node */
94 if (offs < 0)
95 return CMD_RET_SUCCESS;
96
97 /* optee inserts its memory regions as reserved-memory nodes */
98 offs = fdt_subnode_offset(fdt, 0, "reserved-memory");
99 ut_assert(offs >= 0);
100
101 subnode = fdt_first_subnode(fdt, offs);
102 ut_assert(subnode);
103
104 found = 0;
105 while (subnode >= 0) {
106 const char *name = fdt_get_name(fdt, subnode, NULL);
107 struct fdt_resource res;
108
109 ut_assert(name);
110
111 /* only handle optee reservations */
112 if (strncmp(name, "optee", 5))
113 continue;
114
115 found = true;
116
117 /* check if this subnode has a reg property */
118 ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res));
119 subnode = fdt_next_subnode(fdt, subnode);
120 }
121
122 ut_assert(found);
123
124 return CMD_RET_SUCCESS;
125}
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200126
Simon Glasse6ed3de2025-02-07 11:30:51 -0700127/* (1) Try to copy optee nodes from empty dt */
128static int optee_fdt_copy_empty(struct unit_test_state *uts)
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200129{
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200130 void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200131
Simon Glasse6ed3de2025-02-07 11:30:51 -0700132 /* This should still run successfully */
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200133 ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt));
134
135 expect_success = false;
Simon Glasse6ed3de2025-02-07 11:30:51 -0700136 ut_assertok(optee_fdt_firmware(uts));
137 ut_assertok(optee_fdt_protected_memory(uts));
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200138
Simon Glasse6ed3de2025-02-07 11:30:51 -0700139 return 0;
140}
141OPTEE_TEST(optee_fdt_copy_empty, 0);
142
143/* (2) Try to copy optee nodes from prefilled dt */
144static int optee_fdt_copy_prefilled(struct unit_test_state *uts)
145{
146 void *fdt_optee = &__dtb_test_optee_optee_begin;
147
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200148 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
149
150 expect_success = true;
Simon Glasse6ed3de2025-02-07 11:30:51 -0700151 ut_assertok(optee_fdt_firmware(uts));
152 ut_assertok(optee_fdt_protected_memory(uts));
153
154 return 0;
155}
156OPTEE_TEST(optee_fdt_copy_prefilled, 0);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200157
Simon Glasse6ed3de2025-02-07 11:30:51 -0700158/* (3) Try to copy OP-TEE nodes into a already filled DT */
159static int optee_fdt_copy_already_filled(struct unit_test_state *uts)
160{
161 void *fdt_optee = &__dtb_test_optee_optee_begin;
162
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200163 ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE));
164 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
165
166 expect_success = true;
Simon Glasse6ed3de2025-02-07 11:30:51 -0700167 ut_assertok(optee_fdt_firmware(uts));
168 ut_assertok(optee_fdt_protected_memory(uts));
169
170 return 0;
171}
172OPTEE_TEST(optee_fdt_copy_already_filled, 0);
173
174int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
175{
176 struct unit_test *tests = UNIT_TEST_SUITE_START(optee);
177 const int n_ents = UNIT_TEST_SUITE_COUNT(optee);
178 struct unit_test_state *uts;
179 void *fdt_base = &__dtb_test_optee_base_begin;
180 int ret = -ENOMEM;
181
Philippe Reynes1f99f842019-12-17 19:07:04 +0100182 ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200183
184 free(fdt);
185 return ret;
186}