1 /* $NetBSD: sw_tree1.c,v 1.1.1.3 2019/12/22 12:34:06 skrll Exp $ */
2
3 // SPDX-License-Identifier: LGPL-2.1-or-later
4 /*
5 * libfdt - Flat Device Tree manipulation
6 * Testcase for fdt_nop_node()
7 * Copyright (C) 2006 David Gibson, IBM Corporation.
8 */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <stdint.h>
15
16 #include <libfdt.h>
17
18 #include "tests.h"
19 #include "testdata.h"
20
21 #define SPACE 65536
22
23 static enum {
24 FIXED = 0,
25 RESIZE,
26 REALLOC,
27 NEWALLOC,
28 } alloc_mode;
29
realloc_fdt(void ** fdt,size_t * size,bool created)30 static void realloc_fdt(void **fdt, size_t *size, bool created)
31 {
32 int err;
33
34 switch (alloc_mode) {
35 case FIXED:
36 if (!(*fdt))
37 *fdt = xmalloc(*size);
38 else
39 FAIL("Ran out of space");
40 return;
41
42 case RESIZE:
43 if (!(*fdt)) {
44 *fdt = xmalloc(SPACE);
45 } else if (*size < SPACE) {
46 *size += 1;
47 err = fdt_resize(*fdt, *fdt, *size);
48 if (err < 0)
49 FAIL("fdt_resize() failed: %s",
50 fdt_strerror(err));
51 } else {
52 FAIL("Ran out of space");
53 }
54 return;
55
56 case REALLOC:
57 *size += 1;
58 *fdt = xrealloc(*fdt, *size);
59 if (created) {
60 err = fdt_resize(*fdt, *fdt, *size);
61 if (err < 0)
62 FAIL("fdt_resize() failed: %s",
63 fdt_strerror(err));
64 }
65 return;
66
67 case NEWALLOC: {
68 void *buf;
69
70 *size += 1;
71 buf = xmalloc(*size);
72 if (created) {
73 err = fdt_resize(*fdt, buf, *size);
74 if (err < 0)
75 FAIL("fdt_resize() failed: %s",
76 fdt_strerror(err));
77 }
78 free(*fdt);
79 *fdt = buf;
80 return;
81 }
82
83 default:
84 CONFIG("Bad allocation mode");
85 }
86 }
87
88 #define CHECK(code) \
89 do { \
90 err = (code); \
91 if (err == -FDT_ERR_NOSPACE) \
92 realloc_fdt(&fdt, &size, created); \
93 else if (err) \
94 FAIL(#code ": %s", fdt_strerror(err)); \
95 } while (err != 0)
96
main(int argc,char * argv[])97 int main(int argc, char *argv[])
98 {
99 void *fdt = NULL;
100 size_t size;
101 int err;
102 bool created = false;
103 void *place;
104 const char place_str[] = "this is a placeholder string\0string2";
105 int place_len = sizeof(place_str);
106 int create_flags;
107
108 test_init(argc, argv);
109
110 alloc_mode = FIXED;
111 size = SPACE;
112 create_flags = 0;
113
114 if (argc == 2 || argc == 3) {
115 if (streq(argv[1], "fixed")) {
116 alloc_mode = FIXED;
117 size = SPACE;
118 } else if (streq(argv[1], "resize")) {
119 alloc_mode = REALLOC;
120 size = 0;
121 } else if (streq(argv[1], "realloc")) {
122 alloc_mode = REALLOC;
123 size = 0;
124 } else if (streq(argv[1], "newalloc")) {
125 alloc_mode = NEWALLOC;
126 size = 0;
127 } else {
128 char *endp;
129
130 size = strtoul(argv[1], &endp, 0);
131 if (*endp == '\0')
132 alloc_mode = FIXED;
133 else
134 CONFIG("Bad allocation mode \"%s\" specified",
135 argv[1]);
136 }
137 }
138 if (argc == 3) {
139 char *str = argv[2], *saveptr, *tok;
140 bool default_flag = false;
141
142 while ((tok = strtok_r(str, ",", &saveptr)) != NULL) {
143 str = NULL;
144 if (streq(tok, "default")) {
145 default_flag = true;
146 } else if (streq(tok, "no_name_dedup")) {
147 create_flags |= FDT_CREATE_FLAG_NO_NAME_DEDUP;
148 } else if (streq(tok, "bad")) {
149 create_flags |= 0xffffffff;
150 } else {
151 CONFIG("Bad creation flags \"%s\" specified",
152 argv[2]);
153 }
154 }
155
156 if (default_flag && create_flags != 0)
157 CONFIG("Bad creation flags \"%s\" specified",
158 argv[2]);
159 }
160
161 if (argc > 3) {
162 CONFIG("sw_tree1 [<allocation mode>] [<create flags>]");
163 }
164
165 fdt = xmalloc(size);
166 CHECK(fdt_create_with_flags(fdt, size, create_flags));
167
168 created = true;
169
170 CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
171
172 CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
173 CHECK(fdt_finish_reservemap(fdt));
174
175 CHECK(fdt_begin_node(fdt, ""));
176 CHECK(fdt_property_string(fdt, "compatible", "test_tree1"));
177 CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1));
178 CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1));
179 CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1));
180 CHECK(fdt_property_u32(fdt, "#address-cells", 1));
181 CHECK(fdt_property_u32(fdt, "#size-cells", 0));
182
183 CHECK(fdt_begin_node(fdt, "subnode@1"));
184 CHECK(fdt_property_string(fdt, "compatible", "subnode1"));
185 CHECK(fdt_property_u32(fdt, "reg", 1));
186 CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
187 CHECK(fdt_begin_node(fdt, "subsubnode"));
188 CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",
189 23));
190 CHECK(fdt_property_placeholder(fdt, "placeholder", place_len, &place));
191 memcpy(place, place_str, place_len);
192 CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
193 CHECK(fdt_end_node(fdt));
194 CHECK(fdt_begin_node(fdt, "ss1"));
195 CHECK(fdt_end_node(fdt));
196 CHECK(fdt_end_node(fdt));
197
198 CHECK(fdt_begin_node(fdt, "subnode@2"));
199 CHECK(fdt_property_u32(fdt, "reg", 2));
200 CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1));
201 CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
202 CHECK(fdt_property_u32(fdt, "#address-cells", 1));
203 CHECK(fdt_property_u32(fdt, "#size-cells", 0));
204 CHECK(fdt_begin_node(fdt, "subsubnode@0"));
205 CHECK(fdt_property_u32(fdt, "reg", 0));
206 CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2));
207 CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode",
208 23));
209 CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
210 CHECK(fdt_end_node(fdt));
211 CHECK(fdt_begin_node(fdt, "ss2"));
212 CHECK(fdt_end_node(fdt));
213
214 CHECK(fdt_end_node(fdt));
215
216 CHECK(fdt_end_node(fdt));
217
218 save_blob("unfinished_tree1.test.dtb", fdt);
219
220 CHECK(fdt_finish(fdt));
221
222 verbose_printf("Completed tree, totalsize = %d\n",
223 fdt_totalsize(fdt));
224
225 save_blob("sw_tree1.test.dtb", fdt);
226
227 PASS();
228 }
229