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