dtb.cc revision 330449
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2013 David Chisnall
5 * All rights reserved.
6 *
7 * This software was developed by SRI International and the University of
8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9 * ("CTSRD"), as part of the DARPA CRASH research programme.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: stable/11/usr.bin/dtc/dtb.cc 330449 2018-03-05 07:26:05Z eadler $
33 */
34
35#include "dtb.hh"
36#include <sys/types.h>
37#include <inttypes.h>
38#include <stdio.h>
39#include <unistd.h>
40
41using std::string;
42
43namespace dtc
44{
45namespace dtb
46{
47
48void output_writer::write_data(byte_buffer b)
49{
50	for (auto i : b)
51	{
52		write_data(i);
53	}
54}
55
56void
57binary_writer::write_string(const string &name)
58{
59	push_string(buffer, name);
60	// Trailing nul
61	buffer.push_back(0);
62}
63
64void
65binary_writer::write_data(uint8_t v)
66{
67	buffer.push_back(v);
68}
69
70void
71binary_writer::write_data(uint32_t v)
72{
73	while (buffer.size() % 4 != 0)
74	{
75		buffer.push_back(0);
76	}
77	push_big_endian(buffer, v);
78}
79
80void
81binary_writer::write_data(uint64_t v)
82{
83	while (buffer.size() % 8 != 0)
84	{
85		buffer.push_back(0);
86	}
87	push_big_endian(buffer, v);
88}
89
90void
91binary_writer::write_to_file(int fd)
92{
93	// FIXME: Check return
94	write(fd, buffer.data(), buffer.size());
95}
96
97uint32_t
98binary_writer::size()
99{
100	return buffer.size();
101}
102
103void
104asm_writer::write_line(const char *c)
105{
106	if (byte_count != 0)
107	{
108		byte_count = 0;
109		buffer.push_back('\n');
110	}
111	write_string(c);
112}
113
114void
115asm_writer::write_byte(uint8_t b)
116{
117	char out[3] = {0};
118	if (byte_count++ == 0)
119	{
120		buffer.push_back('\t');
121	}
122	write_string(".byte 0x");
123	snprintf(out, 3, "%.2hhx", b);
124	buffer.push_back(out[0]);
125	buffer.push_back(out[1]);
126	if (byte_count == 4)
127	{
128		buffer.push_back('\n');
129		byte_count = 0;
130	}
131	else
132	{
133		buffer.push_back(';');
134		buffer.push_back(' ');
135	}
136}
137
138void
139asm_writer::write_label(const string &name)
140{
141	write_line("\t.globl ");
142	push_string(buffer, name);
143	buffer.push_back('\n');
144	push_string(buffer, name);
145	buffer.push_back(':');
146	buffer.push_back('\n');
147	buffer.push_back('_');
148	push_string(buffer, name);
149	buffer.push_back(':');
150	buffer.push_back('\n');
151
152}
153
154void
155asm_writer::write_comment(const string &name)
156{
157	write_line("\t/* ");
158	push_string(buffer, name);
159	write_string(" */\n");
160}
161
162void
163asm_writer::write_string(const char *c)
164{
165	while (*c)
166	{
167		buffer.push_back((uint8_t)*(c++));
168	}
169}
170
171
172void
173asm_writer::write_string(const string &name)
174{
175	write_line("\t.string \"");
176	push_string(buffer, name);
177	write_line("\"\n");
178	bytes_written += name.size() + 1;
179}
180
181void
182asm_writer::write_data(uint8_t v)
183{
184	write_byte(v);
185	bytes_written++;
186}
187
188void
189asm_writer::write_data(uint32_t v)
190{
191	if (bytes_written % 4 != 0)
192	{
193		write_line("\t.balign 4\n");
194		bytes_written += (4 - (bytes_written % 4));
195	}
196	write_byte((v >> 24) & 0xff);
197	write_byte((v >> 16) & 0xff);
198	write_byte((v >> 8) & 0xff);
199	write_byte((v >> 0) & 0xff);
200	bytes_written += 4;
201}
202
203void
204asm_writer::write_data(uint64_t v)
205{
206	if (bytes_written % 8 != 0)
207	{
208		write_line("\t.balign 8\n");
209		bytes_written += (8 - (bytes_written % 8));
210	}
211	write_byte((v >> 56) & 0xff);
212	write_byte((v >> 48) & 0xff);
213	write_byte((v >> 40) & 0xff);
214	write_byte((v >> 32) & 0xff);
215	write_byte((v >> 24) & 0xff);
216	write_byte((v >> 16) & 0xff);
217	write_byte((v >> 8) & 0xff);
218	write_byte((v >> 0) & 0xff);
219	bytes_written += 8;
220}
221
222void
223asm_writer::write_to_file(int fd)
224{
225	// FIXME: Check return
226	write(fd, buffer.data(), buffer.size());
227}
228
229uint32_t
230asm_writer::size()
231{
232	return bytes_written;
233}
234
235void
236header::write(output_writer &out)
237{
238	out.write_label("dt_blob_start");
239	out.write_label("dt_header");
240	out.write_comment("magic");
241	out.write_data(magic);
242	out.write_comment("totalsize");
243	out.write_data(totalsize);
244	out.write_comment("off_dt_struct");
245	out.write_data(off_dt_struct);
246	out.write_comment("off_dt_strings");
247	out.write_data(off_dt_strings);
248	out.write_comment("off_mem_rsvmap");
249	out.write_data(off_mem_rsvmap);
250	out.write_comment("version");
251	out.write_data(version);
252	out.write_comment("last_comp_version");
253	out.write_data(last_comp_version);
254	out.write_comment("boot_cpuid_phys");
255	out.write_data(boot_cpuid_phys);
256	out.write_comment("size_dt_strings");
257	out.write_data(size_dt_strings);
258	out.write_comment("size_dt_struct");
259	out.write_data(size_dt_struct);
260}
261
262bool
263header::read_dtb(input_buffer &input)
264{
265	if (!(input.consume_binary(magic) && magic == 0xd00dfeed))
266	{
267		fprintf(stderr, "Missing magic token in header.  Got %" PRIx32
268		                " expected 0xd00dfeed\n", magic);
269		return false;
270	}
271	return input.consume_binary(totalsize) &&
272	       input.consume_binary(off_dt_struct) &&
273	       input.consume_binary(off_dt_strings) &&
274	       input.consume_binary(off_mem_rsvmap) &&
275	       input.consume_binary(version) &&
276	       input.consume_binary(last_comp_version) &&
277	       input.consume_binary(boot_cpuid_phys) &&
278	       input.consume_binary(size_dt_strings) &&
279	       input.consume_binary(size_dt_struct);
280}
281uint32_t
282string_table::add_string(const string &str)
283{
284	auto old = string_offsets.find(str);
285	if (old == string_offsets.end())
286	{
287		uint32_t start = size;
288		// Don't forget the trailing nul
289		size += str.size() + 1;
290		string_offsets.insert(std::make_pair(str, start));
291		strings.push_back(str);
292		return start;
293	}
294	else
295	{
296		return old->second;
297	}
298}
299
300void
301string_table::write(dtb::output_writer &writer)
302{
303	writer.write_comment("Strings table.");
304	writer.write_label("dt_strings_start");
305	for (auto &i : strings)
306	{
307		writer.write_string(i);
308	}
309	writer.write_label("dt_strings_end");
310}
311
312} // namespace dtb
313
314} // namespace dtc
315
316