1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3  * libfdt - Flat Device Tree manipulation
4  *	Testcase/tool constructing an fs tree for further test
5  * Copyright (C) 2018 David Gibson, Red Hat Inc.
6  */
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <stdint.h>
13 #include <sys/stat.h>
14 #include <errno.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 
18 #include <libfdt.h>
19 
20 #include "tests.h"
21 #include "testdata.h"
22 
start_dir(const char * name)23 static void start_dir(const char *name)
24 {
25 	int rc;
26 
27 	rc = mkdir(name, 0777);
28 	if (rc != 0)
29 		FAIL("mkdir(\"%s\"): %s", name, strerror(errno));
30 
31 	rc = chdir(name);
32 	if (rc != 0)
33 		FAIL("chdir(\"%s\"): %s", name, strerror(errno));
34 }
35 
end_dir(void)36 static void end_dir(void)
37 {
38 	int rc;
39 
40 	rc = chdir("..");
41 	if (rc != 0)
42 		FAIL("chdir(..): %s", strerror(errno));
43 }
44 
mkfile(const char * name,void * data,size_t len)45 static void mkfile(const char *name, void *data, size_t len)
46 {
47 	int fd;
48 	int rc;
49 
50 	fd = open(name, O_WRONLY|O_CREAT, 0666);
51 	if (fd < 0)
52 		FAIL("open(\"%s\"): %s", name, strerror(errno));
53 
54 	rc = write(fd, data, len);
55 	if (rc < 0)
56 		FAIL("write(\"%s\"): %s", name, strerror(errno));
57 	if (rc != len)
58 		FAIL("write(\"%s\"): short write", name);
59 
60 	rc = close(fd);
61 	if (rc != 0)
62 		FAIL("close(\"%s\"): %s", name, strerror(errno));
63 }
64 
65 #define mkfile_str(name, s)			  \
66 	do {					  \
67 		char str[] = s;			  \
68 		mkfile((name), str, sizeof(str)); \
69 	} while (0)
70 
mkfile_u32(const char * name,uint32_t val)71 static void mkfile_u32(const char *name, uint32_t val)
72 {
73 	val = cpu_to_fdt32(val);
74 	mkfile(name, &val, sizeof(val));
75 }
76 
mkfile_u64(const char * name,uint64_t val)77 static void mkfile_u64(const char *name, uint64_t val)
78 {
79 	val = cpu_to_fdt64(val);
80 	mkfile(name, &val, sizeof(val));
81 }
82 
main(int argc,char * argv[])83 int main(int argc, char *argv[])
84 {
85 	const char *base;
86 
87 	test_init(argc, argv);
88 	if (argc != 2)
89 		CONFIG("Usage: %s <path>", argv[0]);
90 
91 	base = argv[1];
92 
93 	start_dir(base);
94 	mkfile_str("compatible", "test_tree1");
95 	mkfile_u32("prop-int", TEST_VALUE_1);
96 	mkfile_u64("prop-int64", 0xdeadbeef01abcdefULL);
97 	mkfile_str("prop-str", "hello world");
98 	mkfile_u32("#address-cells", 1);
99 	mkfile_u32("#size-cells", 0);
100 
101 	{
102 		start_dir("subnode@1");
103 
104 		mkfile_str("compatible", "subnode1");
105 		mkfile_u32("reg", 1);
106 		mkfile_u32("prop-int", TEST_VALUE_1);
107 
108 		{
109 			start_dir("subsubnode");
110 
111 			mkfile_str("compatible", "subsubnode1\0subsubnode");
112 			mkfile_str("placeholder", "this is a placeholder string\0string2");
113 			mkfile_u32("prop-int", TEST_VALUE_1);
114 
115 			end_dir();
116 		}
117 
118 		{
119 			start_dir("ss1");
120 			end_dir();
121 		}
122 
123 		end_dir();
124 	}
125 
126 	{
127 		start_dir("subnode@2");
128 
129 		mkfile_u32("reg", 2);
130 		mkfile_u32("linux,phandle", 0x2000);
131 		mkfile_u32("prop-int", TEST_VALUE_2);
132 		mkfile_u32("#address-cells", 1);
133 		mkfile_u32("#size-cells", 0);
134 
135 		{
136 			start_dir("subsubnode@0");
137 
138 			mkfile_u32("reg", 0);
139 			mkfile_u32("phandle", 0x2001);
140 			mkfile_str("compatible", "subsubnode2\0subsubnode");
141 			mkfile_u32("prop-int", TEST_VALUE_2);
142 
143 			end_dir();
144 		}
145 
146 		{
147 			start_dir("ss2");
148 			end_dir();
149 		}
150 
151 		end_dir();
152 	}
153 
154 	PASS();
155 }
156