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