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