blob: 658621fa2faa180fcba633df5f47b73851f2f44f [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>
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +020017
18/* 4k ought to be enough for anybody */
19#define FDT_COPY_SIZE (4 * SZ_1K)
20
21extern u32 __dtb_test_optee_base_begin;
22extern u32 __dtb_test_optee_optee_begin;
23extern u32 __dtb_test_optee_no_optee_begin;
24
25static void *fdt;
26static bool expect_success;
27
Simon Glassb0f3bbd2025-02-07 11:30:50 -070028static int optee_test_init(struct unit_test_state *uts)
29{
30 void *fdt_optee = &__dtb_test_optee_optee_begin;
31 void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
32 void *fdt_base = &__dtb_test_optee_base_begin;
33 int ret = -ENOMEM;
34
35 ut_assertok(fdt_check_header(fdt_base));
36 ut_assertok(fdt_check_header(fdt_optee));
37 ut_assertok(fdt_check_header(fdt_no_optee));
38
39 fdt = malloc(FDT_COPY_SIZE);
40 if (!fdt)
41 return ret;
42
43 /*
44 * Resize the FDT to 4k so that we have room to operate on
45 *
46 * (and relocate it since the memory might be mapped
47 * read-only)
48 */
49 ut_assertok(fdt_open_into(fdt_base, fdt, FDT_COPY_SIZE));
50
51 return 0;
52}
53OPTEE_TEST_INIT(optee_test_init, 0);
54
55static int optee_test_uninit(struct unit_test_state *uts)
56{
57 free(fdt);
58
59 return 0;
60}
61OPTEE_TEST_UNINIT(optee_test_uninit, 0);
62
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +020063static int optee_fdt_firmware(struct unit_test_state *uts)
64{
65 const void *prop;
66 int offs, len;
67
68 offs = fdt_path_offset(fdt, "/firmware/optee");
69 ut_assert(expect_success ? offs >= 0 : offs < 0);
70
71 /* only continue if we have an optee node */
72 if (offs < 0)
73 return CMD_RET_SUCCESS;
74
75 prop = fdt_getprop(fdt, offs, "compatible", &len);
76 ut_assertok(strncmp((const char *)prop, "linaro,optee-tz", len));
77
78 prop = fdt_getprop(fdt, offs, "method", &len);
79 ut_assert(strncmp(prop, "hvc", 3) == 0 || strncmp(prop, "smc", 3) == 0);
80
81 return CMD_RET_SUCCESS;
82}
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +020083
84static int optee_fdt_protected_memory(struct unit_test_state *uts)
85{
86 int offs, subnode;
87 bool found;
88
89 offs = fdt_path_offset(fdt, "/firmware/optee");
90 ut_assert(expect_success ? offs >= 0 : offs < 0);
91
92 /* only continue if we have an optee node */
93 if (offs < 0)
94 return CMD_RET_SUCCESS;
95
96 /* optee inserts its memory regions as reserved-memory nodes */
97 offs = fdt_subnode_offset(fdt, 0, "reserved-memory");
98 ut_assert(offs >= 0);
99
100 subnode = fdt_first_subnode(fdt, offs);
101 ut_assert(subnode);
102
103 found = 0;
104 while (subnode >= 0) {
105 const char *name = fdt_get_name(fdt, subnode, NULL);
106 struct fdt_resource res;
107
108 ut_assert(name);
109
110 /* only handle optee reservations */
111 if (strncmp(name, "optee", 5))
112 continue;
113
114 found = true;
115
116 /* check if this subnode has a reg property */
117 ut_assertok(fdt_get_resource(fdt, subnode, "reg", 0, &res));
118 subnode = fdt_next_subnode(fdt, subnode);
119 }
120
121 ut_assert(found);
122
123 return CMD_RET_SUCCESS;
124}
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200125
Simon Glasse6ed3de2025-02-07 11:30:51 -0700126/* (1) Try to copy optee nodes from empty dt */
127static int optee_fdt_copy_empty(struct unit_test_state *uts)
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200128{
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200129 void *fdt_no_optee = &__dtb_test_optee_no_optee_begin;
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200130
Simon Glasse6ed3de2025-02-07 11:30:51 -0700131 /* This should still run successfully */
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200132 ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt));
133
134 expect_success = false;
Simon Glasse6ed3de2025-02-07 11:30:51 -0700135 ut_assertok(optee_fdt_firmware(uts));
136 ut_assertok(optee_fdt_protected_memory(uts));
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200137
Simon Glasse6ed3de2025-02-07 11:30:51 -0700138 return 0;
139}
140OPTEE_TEST(optee_fdt_copy_empty, 0);
141
142/* (2) Try to copy optee nodes from prefilled dt */
143static int optee_fdt_copy_prefilled(struct unit_test_state *uts)
144{
145 void *fdt_optee = &__dtb_test_optee_optee_begin;
146
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200147 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
148
149 expect_success = true;
Simon Glasse6ed3de2025-02-07 11:30:51 -0700150 ut_assertok(optee_fdt_firmware(uts));
151 ut_assertok(optee_fdt_protected_memory(uts));
152
153 return 0;
154}
155OPTEE_TEST(optee_fdt_copy_prefilled, 0);
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200156
Simon Glasse6ed3de2025-02-07 11:30:51 -0700157/* (3) Try to copy OP-TEE nodes into a already filled DT */
158static int optee_fdt_copy_already_filled(struct unit_test_state *uts)
159{
160 void *fdt_optee = &__dtb_test_optee_optee_begin;
161
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200162 ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE));
163 ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt));
164
165 expect_success = true;
Simon Glasse6ed3de2025-02-07 11:30:51 -0700166 ut_assertok(optee_fdt_firmware(uts));
167 ut_assertok(optee_fdt_protected_memory(uts));
168
169 return 0;
170}
171OPTEE_TEST(optee_fdt_copy_already_filled, 0);