blob: 87dc9328c674bda7f13773e3183b7b2ba9983208 [file] [log] [blame]
Maxime Ripard0e31a112016-07-05 10:26:46 +02001/*
2 * Copyright (c) 2016 NextThing Co
3 * Copyright (c) 2016 Free Electrons
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <command.h>
10#include <errno.h>
11#include <malloc.h>
12
13#include <linux/sizes.h>
14
15#include <test/ut.h>
16#include <test/overlay.h>
17
18/* 4k ought to be enough for anybody */
19#define FDT_COPY_SIZE (4 * SZ_1K)
20
21extern u32 __dtb_test_fdt_base_begin;
22extern u32 __dtb_test_fdt_overlay_begin;
23
24static int fdt_getprop_u32_by_index(void *fdt, const char *path,
25 const char *name, int index,
26 u32 *out)
27{
28 const fdt32_t *val;
29 int node_off;
30 int len;
31
32 node_off = fdt_path_offset(fdt, path);
33 if (node_off < 0)
34 return node_off;
35
36 val = fdt_getprop(fdt, node_off, name, &len);
37 if (!val || (len < (sizeof(uint32_t) * (index + 1))))
38 return -FDT_ERR_NOTFOUND;
39
40 *out = fdt32_to_cpu(*(val + index));
41
42 return 0;
43}
44
45static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
46 u32 *out)
47{
48 return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
49}
50
51static int fdt_getprop_str(void *fdt, const char *path, const char *name,
52 const char **out)
53{
54 int node_off;
55
56 node_off = fdt_path_offset(fdt, path);
57 if (node_off < 0)
58 return node_off;
59
60 return fdt_get_string(fdt, node_off, name, out);
61}
62
63static int fdt_overlay_change_int_property(struct unit_test_state *uts)
64{
65 void *fdt = uts->priv;
66 u32 val = 0;
67
68 ut_assertok(fdt_getprop_u32(fdt, "/test-node", "test-int-property",
69 &val));
70 ut_asserteq(43, val);
71
72 return CMD_RET_SUCCESS;
73}
74OVERLAY_TEST(fdt_overlay_change_int_property, 0);
75
76static int fdt_overlay_change_str_property(struct unit_test_state *uts)
77{
78 void *fdt = uts->priv;
79 const char *val = NULL;
80
81 ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
82 &val));
83 ut_asserteq_str("foobar", val);
84
85 return CMD_RET_SUCCESS;
86}
87OVERLAY_TEST(fdt_overlay_change_str_property, 0);
88
89static int fdt_overlay_add_str_property(struct unit_test_state *uts)
90{
91 void *fdt = uts->priv;
92 const char *val = NULL;
93
94 ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
95 &val));
96 ut_asserteq_str("foobar2", val);
97
98 return CMD_RET_SUCCESS;
99}
100OVERLAY_TEST(fdt_overlay_add_str_property, 0);
101
102static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
103{
104 void *fdt = uts->priv;
105 int off;
106
107 off = fdt_path_offset(fdt, "/test-node/new-node");
108 ut_assert(off >= 0);
109
110 ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
111
112 return CMD_RET_SUCCESS;
113}
114OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
115
116static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
117{
118 void *fdt = uts->priv;
119 int off;
120
121 off = fdt_path_offset(fdt, "/new-node");
122 ut_assert(off >= 0);
123
124 ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
125
126 return CMD_RET_SUCCESS;
127}
128OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
129
130static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
131{
132 void *fdt = uts->priv;
133 int off;
134
135 off = fdt_path_offset(fdt, "/test-node/sub-test-node");
136 ut_assert(off >= 0);
137
138 ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
139 ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
140
141 return CMD_RET_SUCCESS;
142}
143OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
144
145static int fdt_overlay_local_phandle(struct unit_test_state *uts)
146{
147 uint32_t local_phandle;
148 void *fdt = uts->priv;
149 u32 val = 0;
150 int off;
151
152 off = fdt_path_offset(fdt, "/new-local-node");
153 ut_assert(off >= 0);
154
155 local_phandle = fdt_get_phandle(fdt, off);
156 ut_assert(local_phandle);
157
158 ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
159 0, &val));
160 ut_asserteq(local_phandle, val);
161
162 ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle",
163 1, &val));
164 ut_asserteq(local_phandle, val);
165
166 return CMD_RET_SUCCESS;
167}
168OVERLAY_TEST(fdt_overlay_local_phandle, 0);
169
170static int fdt_overlay_local_phandles(struct unit_test_state *uts)
171{
172 uint32_t local_phandle, test_phandle;
173 void *fdt = uts->priv;
174 u32 val = 0;
175 int off;
176
177 off = fdt_path_offset(fdt, "/new-local-node");
178 ut_assert(off >= 0);
179
180 local_phandle = fdt_get_phandle(fdt, off);
181 ut_assert(local_phandle);
182
183 off = fdt_path_offset(fdt, "/test-node");
184 ut_assert(off >= 0);
185
186 test_phandle = fdt_get_phandle(fdt, off);
187 ut_assert(test_phandle);
188
189 ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 0,
190 &val));
191 ut_asserteq(test_phandle, val);
192
193 ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 1,
194 &val));
195 ut_asserteq(local_phandle, val);
196
197 return CMD_RET_SUCCESS;
198}
199OVERLAY_TEST(fdt_overlay_local_phandles, 0);
200
201int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
202{
203 struct unit_test *tests = ll_entry_start(struct unit_test,
204 overlay_test);
205 const int n_ents = ll_entry_count(struct unit_test, overlay_test);
206 struct unit_test_state *uts;
207 struct unit_test *test;
208 void *fdt_base = &__dtb_test_fdt_base_begin;
209 void *fdt_overlay = &__dtb_test_fdt_overlay_begin;
210 void *fdt_base_copy, *fdt_overlay_copy;
211
212 uts = calloc(1, sizeof(*uts));
213 if (!uts)
214 return -ENOMEM;
215
216 ut_assertok(fdt_check_header(fdt_base));
217 ut_assertok(fdt_check_header(fdt_overlay));
218
219 fdt_base_copy = malloc(FDT_COPY_SIZE);
220 if (!fdt_base_copy)
221 return -ENOMEM;
222 uts->priv = fdt_base_copy;
223
224 fdt_overlay_copy = malloc(FDT_COPY_SIZE);
225 if (!fdt_overlay_copy)
226 return -ENOMEM;
227
228 /*
229 * Resize the FDT to 4k so that we have room to operate on
230 *
231 * (and relocate it since the memory might be mapped
232 * read-only)
233 */
234 ut_assertok(fdt_open_into(fdt_base, fdt_base_copy, FDT_COPY_SIZE));
235
236 /*
237 * Resize the overlay to 4k so that we have room to operate on
238 *
239 * (and relocate it since the memory might be mapped
240 * read-only)
241 */
242 ut_assertok(fdt_open_into(fdt_overlay, fdt_overlay_copy,
243 FDT_COPY_SIZE));
244
245 /* Apply the overlay */
246 ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
247
248 if (argc == 1)
249 printf("Running %d environment tests\n", n_ents);
250
251 for (test = tests; test < tests + n_ents; test++) {
252 if (argc > 1 && strcmp(argv[1], test->name))
253 continue;
254 printf("Test: %s\n", test->name);
255
256 uts->start = mallinfo();
257
258 test->func(uts);
259 }
260
261 printf("Failures: %d\n", uts->fail_count);
262
263 free(fdt_overlay_copy);
264 free(fdt_base_copy);
265 free(uts);
266
267 return uts->fail_count ? CMD_RET_FAILURE : 0;
268}