1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3  * libfdt - Flat Device Tree manipulation
4  *	Testcase for phandle references in dtc
5  * Copyright (C) 2006 David Gibson, IBM Corporation.
6  */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdint.h>
11 
12 #include <libfdt.h>
13 
14 #include "tests.h"
15 #include "testdata.h"
16 
check_ref(const void * fdt,int node,uint32_t checkref)17 static void check_ref(const void *fdt, int node, uint32_t checkref)
18 {
19 	const fdt32_t *p;
20 	uint32_t ref;
21 	int len;
22 
23 	p = fdt_getprop(fdt, node, "ref", &len);
24 	if (!p)
25 		FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len));
26 	if (len != sizeof(*p))
27 		FAIL("'ref' in node at %d has wrong size (%d instead of %zd)",
28 		     node, len, sizeof(*p));
29 	ref = fdt32_to_cpu(*p);
30 	if (ref != checkref)
31 		FAIL("'ref' in node at %d has value 0x%x instead of 0x%x",
32 		     node, ref, checkref);
33 
34 	p = fdt_getprop(fdt, node, "lref", &len);
35 	if (!p)
36 		FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len));
37 	if (len != sizeof(*p))
38 		FAIL("'lref' in node at %d has wrong size (%d instead of %zd)",
39 		     node, len, sizeof(*p));
40 	ref = fdt32_to_cpu(*p);
41 	if (ref != checkref)
42 		FAIL("'lref' in node at %d has value 0x%x instead of 0x%x",
43 		     node, ref, checkref);
44 }
45 
check_rref(const void * fdt)46 static void check_rref(const void *fdt)
47 {
48 	const fdt32_t *p;
49 	uint32_t ref;
50 	int len;
51 
52 	p = fdt_getprop(fdt, 0, "rref", &len);
53 	if (!p)
54 		FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len));
55 	if (len != sizeof(*p))
56 		FAIL("'rref' in root node has wrong size (%d instead of %zd)",
57 		     len, sizeof(*p));
58 	ref = fdt32_to_cpu(*p);
59 	if (ref != fdt_get_phandle(fdt, 0))
60 		FAIL("'rref' in root node has value 0x%x instead of 0x0", ref);
61 }
62 
main(int argc,char * argv[])63 int main(int argc, char *argv[])
64 {
65 	void *fdt;
66 	int n1, n2, n3, n4, n5, n6, err;
67 	uint32_t h1, h2, h4, h5, h6, hn;
68 
69 	test_init(argc, argv);
70 	fdt = load_blob_arg(argc, argv);
71 
72 	n1 = fdt_path_offset(fdt, "/node1");
73 	if (n1 < 0)
74 		FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1));
75 	n2 = fdt_path_offset(fdt, "/node2");
76 	if (n2 < 0)
77 		FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2));
78 	n3 = fdt_path_offset(fdt, "/node3");
79 	if (n3 < 0)
80 		FAIL("fdt_path_offset(/node3): %s", fdt_strerror(n3));
81 	n4 = fdt_path_offset(fdt, "/node4");
82 	if (n4 < 0)
83 		FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
84 	n5 = fdt_path_offset(fdt, "/node5");
85 	if (n5 < 0)
86 		FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5));
87 	n6 = fdt_path_offset(fdt, "/node6");
88 	if (n6 < 0)
89 		FAIL("fdt_path_offset(/node6): %s", fdt_strerror(n6));
90 
91 	h1 = fdt_get_phandle(fdt, n1);
92 	h2 = fdt_get_phandle(fdt, n2);
93 	h4 = fdt_get_phandle(fdt, n4);
94 	h5 = fdt_get_phandle(fdt, n5);
95 	h6 = fdt_get_phandle(fdt, n6);
96 
97 	if (h1 != 0x2000)
98 		FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x",
99 		     h1, 0x2000);
100 	if (h2 != 0x1)
101 		FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x",
102 		     h2, 0x1);
103 	if (h6 != FDT_MAX_PHANDLE)
104 		FAIL("/node6 has wrong phandle, 0x%x instead of 0x%x",
105 		     h6, FDT_MAX_PHANDLE);
106 	if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
107 		FAIL("/node4 has bad phandle, 0x%x", h4);
108 
109 	if ((h5 == 0) || (h5 == -1))
110 		FAIL("/node5 has bad phandle, 0x%x", h5);
111 	if ((h5 == h4) || (h5 == h2) || (h5 == h1))
112 		FAIL("/node5 has duplicate phandle, 0x%x", h5);
113 
114 	/*
115 	 * /node6 has phandle FDT_MAX_PHANDLE, so fdt_generate_phandle() is
116 	 * expected to fail.
117 	 */
118 	err = fdt_generate_phandle(fdt, &hn);
119 	if (err != -FDT_ERR_NOPHANDLES)
120 		FAIL("generated invalid phandle 0x%x\n", hn);
121 
122 	check_ref(fdt, n1, h2);
123 	check_ref(fdt, n2, h1);
124 	check_ref(fdt, n3, h4);
125 
126 	check_rref(fdt);
127 
128 	PASS();
129 }
130