xref: /netbsd-src/external/gpl2/dtc/dist/tests/mangle-layout.c (revision 7cdf52c4e116cff01c811ade809106cc07d84795)
1*7cdf52c4Sskrll /*	$NetBSD: mangle-layout.c,v 1.4 2019/12/22 12:38:24 skrll Exp $	*/
2b2f342caSskrll 
3*7cdf52c4Sskrll // SPDX-License-Identifier: LGPL-2.1-or-later
4b8ae3907Smacallan /*
5b8ae3907Smacallan  * libfdt - Flat Device Tree manipulation
6b8ae3907Smacallan  *	Testcase/tool for rearranging blocks of a dtb
7b8ae3907Smacallan  * Copyright (C) 2006 David Gibson, IBM Corporation.
8b8ae3907Smacallan  */
9b8ae3907Smacallan 
10b8ae3907Smacallan #include <stdlib.h>
11b8ae3907Smacallan #include <stdio.h>
12b8ae3907Smacallan #include <string.h>
13b8ae3907Smacallan #include <limits.h>
14b8ae3907Smacallan #include <stdint.h>
15b8ae3907Smacallan 
16b8ae3907Smacallan #include <libfdt.h>
17b8ae3907Smacallan 
18b8ae3907Smacallan #include "tests.h"
19b8ae3907Smacallan #include "testdata.h"
20b8ae3907Smacallan 
21b8ae3907Smacallan struct bufstate {
22b8ae3907Smacallan 	char *buf;
23b8ae3907Smacallan 	int size;
24b8ae3907Smacallan };
25b8ae3907Smacallan 
expand_buf(struct bufstate * buf,int newsize)26b8ae3907Smacallan static void expand_buf(struct bufstate *buf, int newsize)
27b8ae3907Smacallan {
28b8ae3907Smacallan 	buf->buf = realloc(buf->buf, newsize);
29b8ae3907Smacallan 	if (!buf->buf)
30b8ae3907Smacallan 		CONFIG("Allocation failure");
31b8ae3907Smacallan 	buf->size = newsize;
32b8ae3907Smacallan }
33b8ae3907Smacallan 
new_header(struct bufstate * buf,int version,const void * fdt)34b8ae3907Smacallan static void new_header(struct bufstate *buf, int version, const void *fdt)
35b8ae3907Smacallan {
36*7cdf52c4Sskrll 	int hdrsize = fdt_header_size_(version);
37b8ae3907Smacallan 
38*7cdf52c4Sskrll 	if ((version != 16) && (version != 17))
39b8ae3907Smacallan 		CONFIG("Bad version %d", version);
40b8ae3907Smacallan 
41b8ae3907Smacallan 	expand_buf(buf, hdrsize);
42b8ae3907Smacallan 	memset(buf->buf, 0, hdrsize);
43b8ae3907Smacallan 
44b8ae3907Smacallan 	fdt_set_magic(buf->buf, FDT_MAGIC);
45b8ae3907Smacallan 	fdt_set_version(buf->buf, version);
46b8ae3907Smacallan 	fdt_set_last_comp_version(buf->buf, 16);
47b8ae3907Smacallan 	fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
48b8ae3907Smacallan }
49b8ae3907Smacallan 
add_block(struct bufstate * buf,int version,char block,const void * fdt)50b8ae3907Smacallan static void add_block(struct bufstate *buf, int version, char block, const void *fdt)
51b8ae3907Smacallan {
52b8ae3907Smacallan 	int align, size, oldsize;
53b8ae3907Smacallan 	const void *src;
54b8ae3907Smacallan 	int offset;
55b8ae3907Smacallan 
56b8ae3907Smacallan 	switch (block) {
57b8ae3907Smacallan 	case 'm':
58b8ae3907Smacallan 		/* Memory reserve map */
59b8ae3907Smacallan 		align = 8;
60b8ae3907Smacallan 		src = (const char *)fdt + fdt_off_mem_rsvmap(fdt);
61b8ae3907Smacallan 		size = (fdt_num_mem_rsv(fdt) + 1)
62b8ae3907Smacallan 			* sizeof(struct fdt_reserve_entry);
63b8ae3907Smacallan 		break;
64b8ae3907Smacallan 
65b8ae3907Smacallan 	case 't':
66b8ae3907Smacallan 		/* Structure block */
67b8ae3907Smacallan 		align = 4;
68b8ae3907Smacallan 		src = (const char *)fdt + fdt_off_dt_struct(fdt);
69b8ae3907Smacallan 		size = fdt_size_dt_struct(fdt);
70b8ae3907Smacallan 		break;
71b8ae3907Smacallan 
72b8ae3907Smacallan 	case 's':
73b8ae3907Smacallan 		/* Strings block */
74b8ae3907Smacallan 		align = 1;
75b8ae3907Smacallan 		src = (const char *)fdt + fdt_off_dt_strings(fdt);
76b8ae3907Smacallan 		size = fdt_size_dt_strings(fdt);
77b8ae3907Smacallan 		break;
78b8ae3907Smacallan 	default:
79b8ae3907Smacallan 		CONFIG("Bad block '%c'", block);
80b8ae3907Smacallan 	}
81b8ae3907Smacallan 
82b8ae3907Smacallan 	oldsize = buf->size;
8397d12aeaSskrll 	offset = FDTALIGN2(oldsize, align);
84b8ae3907Smacallan 	expand_buf(buf, offset+size);
85b8ae3907Smacallan 	memset(buf->buf + oldsize, 0, offset - oldsize);
86b8ae3907Smacallan 
87b8ae3907Smacallan 	memcpy(buf->buf + offset, src, size);
88b8ae3907Smacallan 
89b8ae3907Smacallan 	switch (block) {
90b8ae3907Smacallan 	case 'm':
91b8ae3907Smacallan 		fdt_set_off_mem_rsvmap(buf->buf, offset);
92b8ae3907Smacallan 		break;
93b8ae3907Smacallan 
94b8ae3907Smacallan 	case 't':
95b8ae3907Smacallan 		fdt_set_off_dt_struct(buf->buf, offset);
96b8ae3907Smacallan 		if (version >= 17)
97b8ae3907Smacallan 			fdt_set_size_dt_struct(buf->buf, size);
98b8ae3907Smacallan 		break;
99b8ae3907Smacallan 
100b8ae3907Smacallan 	case 's':
101b8ae3907Smacallan 		fdt_set_off_dt_strings(buf->buf, offset);
102b8ae3907Smacallan 		fdt_set_size_dt_strings(buf->buf, size);
103b8ae3907Smacallan 		break;
104b8ae3907Smacallan 	}
105b8ae3907Smacallan }
106b8ae3907Smacallan 
main(int argc,char * argv[])107b8ae3907Smacallan int main(int argc, char *argv[])
108b8ae3907Smacallan {
109b8ae3907Smacallan 	void *fdt;
110b8ae3907Smacallan 	int version;
111b8ae3907Smacallan 	const char *blockorder;
112b8ae3907Smacallan 	struct bufstate buf = {NULL, 0};
113b8ae3907Smacallan 	int err;
114b8ae3907Smacallan 	const char *inname;
115b8ae3907Smacallan 	char outname[PATH_MAX];
116b8ae3907Smacallan 
117b8ae3907Smacallan 	test_init(argc, argv);
118b8ae3907Smacallan 	if (argc != 4)
119b8ae3907Smacallan 		CONFIG("Usage: %s <dtb file> <version> <block order>", argv[0]);
120b8ae3907Smacallan 
121b8ae3907Smacallan 	inname = argv[1];
122b8ae3907Smacallan 	fdt = load_blob(argv[1]);
123b8ae3907Smacallan 	version = atoi(argv[2]);
124b8ae3907Smacallan 	blockorder = argv[3];
125b8ae3907Smacallan 	sprintf(outname, "v%d.%s.%s", version, blockorder, inname);
126b8ae3907Smacallan 
127b8ae3907Smacallan 	if ((version != 16) && (version != 17))
128b8ae3907Smacallan 		CONFIG("Version must be 16 or 17");
129b8ae3907Smacallan 
130b8ae3907Smacallan 	if (fdt_version(fdt) < 17)
131b8ae3907Smacallan 		CONFIG("Input tree must be v17");
132b8ae3907Smacallan 
133b8ae3907Smacallan 	new_header(&buf, version, fdt);
134b8ae3907Smacallan 
135b8ae3907Smacallan 	while (*blockorder) {
136b8ae3907Smacallan 		add_block(&buf, version, *blockorder, fdt);
137b8ae3907Smacallan 		blockorder++;
138b8ae3907Smacallan 	}
139b8ae3907Smacallan 
140b8ae3907Smacallan 	fdt_set_totalsize(buf.buf, buf.size);
141b8ae3907Smacallan 
142b8ae3907Smacallan 	err = fdt_check_header(buf.buf);
143b8ae3907Smacallan 	if (err)
144b8ae3907Smacallan 		FAIL("Output tree fails check: %s", fdt_strerror(err));
145b8ae3907Smacallan 
146b8ae3907Smacallan 	save_blob(outname, buf.buf);
147b8ae3907Smacallan 
148b8ae3907Smacallan 	PASS();
149b8ae3907Smacallan }
150