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