xref: /netbsd-src/external/gpl2/dtc/dist/tests/sw_tree1.c (revision cc7d2833ecf67da5a5ddc470841931eb9f6723e4)
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