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