1245803Stheraven/*-
2245803Stheraven * Copyright (c) 2013 David Chisnall
3245803Stheraven * All rights reserved.
4245803Stheraven *
5245803Stheraven * This software was developed by SRI International and the University of
6245803Stheraven * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7245803Stheraven * ("CTSRD"), as part of the DARPA CRASH research programme.
8245803Stheraven *
9245803Stheraven * Redistribution and use in source and binary forms, with or without
10245803Stheraven * modification, are permitted provided that the following conditions
11245803Stheraven * are met:
12245803Stheraven * 1. Redistributions of source code must retain the above copyright
13245803Stheraven *    notice, this list of conditions and the following disclaimer.
14245803Stheraven * 2. Redistributions in binary form must reproduce the above copyright
15245803Stheraven *    notice, this list of conditions and the following disclaimer in the
16245803Stheraven *    documentation and/or other materials provided with the distribution.
17245803Stheraven *
18245803Stheraven * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19245803Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20245803Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21245803Stheraven * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22245803Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23245803Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24245803Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25245803Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26245803Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27245803Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28245803Stheraven * SUCH DAMAGE.
29245803Stheraven *
30245803Stheraven * $FreeBSD$
31245803Stheraven */
32245803Stheraven
33245803Stheraven#include "dtb.hh"
34245839Stheraven#include <sys/types.h>
35245803Stheraven#include <inttypes.h>
36245839Stheraven#include <stdio.h>
37245839Stheraven#include <unistd.h>
38245803Stheraven
39245839Stheraven
40245803Stheravennamespace dtc
41245803Stheraven{
42245803Stheravennamespace dtb
43245803Stheraven{
44245803Stheraven
45245803Stheravenvoid output_writer::write_data(byte_buffer b)
46245803Stheraven{
47245803Stheraven	for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++)
48245803Stheraven	{
49245803Stheraven		write_data(*i);
50245803Stheraven	}
51245803Stheraven}
52245803Stheraven
53245803Stheravenvoid
54245803Stheravenbinary_writer::write_string(string name)
55245803Stheraven{
56245803Stheraven	name.push_to_buffer(buffer);
57245803Stheraven	// Trailing nul
58245803Stheraven	buffer.push_back(0);
59245803Stheraven}
60245803Stheraven
61245803Stheravenvoid
62245803Stheravenbinary_writer::write_data(uint8_t v)
63245803Stheraven{
64245803Stheraven	buffer.push_back(v);
65245803Stheraven}
66245803Stheraven
67245803Stheravenvoid
68245803Stheravenbinary_writer::write_data(uint32_t v)
69245803Stheraven{
70245803Stheraven	while (buffer.size() % 4 != 0)
71245803Stheraven	{
72245803Stheraven		buffer.push_back(0);
73245803Stheraven	}
74245803Stheraven	push_big_endian(buffer, v);
75245803Stheraven}
76245803Stheraven
77245803Stheravenvoid
78245803Stheravenbinary_writer::write_data(uint64_t v)
79245803Stheraven{
80245803Stheraven	while (buffer.size() % 8 != 0)
81245803Stheraven	{
82245803Stheraven		buffer.push_back(0);
83245803Stheraven	}
84245803Stheraven	push_big_endian(buffer, v);
85245803Stheraven}
86245803Stheraven
87245803Stheravenvoid
88245803Stheravenbinary_writer::write_to_file(int fd)
89245803Stheraven{
90245803Stheraven	// FIXME: Check return
91245803Stheraven	write(fd, buffer.data(), buffer.size());
92245803Stheraven}
93245803Stheraven
94245803Stheravenuint32_t
95245803Stheravenbinary_writer::size()
96245803Stheraven{
97245803Stheraven	return buffer.size();
98245803Stheraven}
99245803Stheraven
100245803Stheravenvoid
101245803Stheravenasm_writer::write_string(const char *c)
102245803Stheraven{
103245803Stheraven	while (*c)
104245803Stheraven	{
105245803Stheraven		buffer.push_back((uint8_t)*(c++));
106245803Stheraven	}
107245803Stheraven}
108245803Stheraven
109245803Stheravenvoid
110245803Stheravenasm_writer::write_line(const char *c)
111245803Stheraven{
112245803Stheraven	if (byte_count != 0)
113245803Stheraven	{
114245803Stheraven		byte_count = 0;
115245803Stheraven		buffer.push_back('\n');
116245803Stheraven	}
117245803Stheraven	write_string(c);
118245803Stheraven}
119245803Stheraven
120245803Stheravenvoid
121245803Stheravenasm_writer::write_byte(uint8_t b)
122245803Stheraven{
123245803Stheraven	char out[3] = {0};
124245803Stheraven	if (byte_count++ == 0)
125245803Stheraven	{
126245803Stheraven		buffer.push_back('\t');
127245803Stheraven	}
128245803Stheraven	write_string(".byte 0x");
129245803Stheraven	snprintf(out, 3, "%.2hhx", b);
130245803Stheraven	buffer.push_back(out[0]);
131245803Stheraven	buffer.push_back(out[1]);
132245803Stheraven	if (byte_count == 4)
133245803Stheraven	{
134245803Stheraven		buffer.push_back('\n');
135245803Stheraven		byte_count = 0;
136245803Stheraven	}
137245803Stheraven	else
138245803Stheraven	{
139245803Stheraven		buffer.push_back(';');
140245803Stheraven		buffer.push_back(' ');
141245803Stheraven	}
142245803Stheraven}
143245803Stheraven
144245803Stheravenvoid
145245803Stheravenasm_writer::write_label(string name)
146245803Stheraven{
147245803Stheraven	write_line("\t.globl ");
148245803Stheraven	name.push_to_buffer(buffer);
149245803Stheraven	buffer.push_back('\n');
150245803Stheraven	name.push_to_buffer(buffer);
151245803Stheraven	buffer.push_back(':');
152245803Stheraven	buffer.push_back('\n');
153245803Stheraven	buffer.push_back('_');
154245803Stheraven	name.push_to_buffer(buffer);
155245803Stheraven	buffer.push_back(':');
156245803Stheraven	buffer.push_back('\n');
157245803Stheraven
158245803Stheraven}
159245803Stheraven
160245803Stheravenvoid
161245803Stheravenasm_writer::write_comment(string name)
162245803Stheraven{
163245803Stheraven	write_line("\t/* ");
164245803Stheraven	name.push_to_buffer(buffer);
165245803Stheraven	write_string(" */\n");
166245803Stheraven}
167245803Stheraven
168245803Stheravenvoid
169245803Stheravenasm_writer::write_string(string name)
170245803Stheraven{
171245803Stheraven	write_line("\t.string \"");
172245803Stheraven	name.push_to_buffer(buffer);
173245803Stheraven	write_line("\"\n");
174245803Stheraven	bytes_written += name.size() + 1;
175245803Stheraven}
176245803Stheraven
177245803Stheravenvoid
178245803Stheravenasm_writer::write_data(uint8_t v)
179245803Stheraven{
180245803Stheraven	write_byte(v);
181245803Stheraven	bytes_written++;
182245803Stheraven}
183245803Stheraven
184245803Stheravenvoid
185245803Stheravenasm_writer::write_data(uint32_t v)
186245803Stheraven{
187245803Stheraven	if (bytes_written % 4 != 0)
188245803Stheraven	{
189245803Stheraven		write_line("\t.balign 4\n");
190245803Stheraven		bytes_written += (4 - (bytes_written % 4));
191245803Stheraven	}
192245803Stheraven	write_byte((v >> 24) & 0xff);
193245803Stheraven	write_byte((v >> 16) & 0xff);
194245803Stheraven	write_byte((v >> 8) & 0xff);
195245803Stheraven	write_byte((v >> 0) & 0xff);
196245803Stheraven	bytes_written += 4;
197245803Stheraven}
198245803Stheraven
199245803Stheravenvoid
200245803Stheravenasm_writer::write_data(uint64_t v)
201245803Stheraven{
202245803Stheraven	if (bytes_written % 8 != 0)
203245803Stheraven	{
204245803Stheraven		write_line("\t.balign 8\n");
205245803Stheraven		bytes_written += (8 - (bytes_written % 8));
206245803Stheraven	}
207245803Stheraven	write_byte((v >> 56) & 0xff);
208245803Stheraven	write_byte((v >> 48) & 0xff);
209245803Stheraven	write_byte((v >> 40) & 0xff);
210245803Stheraven	write_byte((v >> 32) & 0xff);
211245803Stheraven	write_byte((v >> 24) & 0xff);
212245803Stheraven	write_byte((v >> 16) & 0xff);
213245803Stheraven	write_byte((v >> 8) & 0xff);
214245803Stheraven	write_byte((v >> 0) & 0xff);
215245803Stheraven	bytes_written += 8;
216245803Stheraven}
217245803Stheraven
218245803Stheravenvoid
219245803Stheravenasm_writer::write_to_file(int fd)
220245803Stheraven{
221245803Stheraven	// FIXME: Check return
222245803Stheraven	write(fd, buffer.data(), buffer.size());
223245803Stheraven}
224245803Stheraven
225245803Stheravenuint32_t
226245803Stheravenasm_writer::size()
227245803Stheraven{
228245803Stheraven	return bytes_written;
229245803Stheraven}
230245803Stheraven
231245803Stheravenvoid
232245803Stheravenheader::write(output_writer &out)
233245803Stheraven{
234245803Stheraven	out.write_label(string("dt_blob_start"));
235245803Stheraven	out.write_label(string("dt_header"));
236245803Stheraven	out.write_comment("magic");
237245803Stheraven	out.write_data(magic);
238245803Stheraven	out.write_comment("totalsize");
239245803Stheraven	out.write_data(totalsize);
240245803Stheraven	out.write_comment("off_dt_struct");
241245803Stheraven	out.write_data(off_dt_struct);
242245803Stheraven	out.write_comment("off_dt_strings");
243245803Stheraven	out.write_data(off_dt_strings);
244245803Stheraven	out.write_comment("off_mem_rsvmap");
245245803Stheraven	out.write_data(off_mem_rsvmap);
246245803Stheraven	out.write_comment("version");
247245803Stheraven	out.write_data(version);
248245803Stheraven	out.write_comment("last_comp_version");
249245803Stheraven	out.write_data(last_comp_version);
250245803Stheraven	out.write_comment("boot_cpuid_phys");
251245803Stheraven	out.write_data(boot_cpuid_phys);
252245803Stheraven	out.write_comment("size_dt_strings");
253245803Stheraven	out.write_data(size_dt_strings);
254245803Stheraven	out.write_comment("size_dt_struct");
255245803Stheraven	out.write_data(size_dt_struct);
256245803Stheraven}
257245803Stheraven
258245803Stheravenbool
259245803Stheravenheader::read_dtb(input_buffer &input)
260245803Stheraven{
261245803Stheraven	if (!(input.consume_binary(magic) && magic == 0xd00dfeed))
262245803Stheraven	{
263245803Stheraven		fprintf(stderr, "Missing magic token in header.  Got %" PRIx32
264245803Stheraven		                " expected 0xd00dfeed\n", magic);
265245803Stheraven		return false;
266245803Stheraven	}
267245803Stheraven	return input.consume_binary(totalsize) &&
268245803Stheraven	       input.consume_binary(off_dt_struct) &&
269245803Stheraven	       input.consume_binary(off_dt_strings) &&
270245803Stheraven	       input.consume_binary(off_mem_rsvmap) &&
271245803Stheraven	       input.consume_binary(version) &&
272245803Stheraven	       input.consume_binary(last_comp_version) &&
273245803Stheraven	       input.consume_binary(boot_cpuid_phys) &&
274245803Stheraven	       input.consume_binary(size_dt_strings) &&
275245803Stheraven	       input.consume_binary(size_dt_struct);
276245803Stheraven}
277245803Stheravenuint32_t
278245803Stheravenstring_table::add_string(string str)
279245803Stheraven{
280245803Stheraven	std::map<string, uint32_t>::iterator old = string_offsets.find(str);
281245803Stheraven	if (old == string_offsets.end())
282245803Stheraven	{
283245803Stheraven		uint32_t start = size;
284245803Stheraven		// Don't forget the trailing nul
285245803Stheraven		size += str.size() + 1;
286245803Stheraven		string_offsets.insert(std::make_pair(str, start));
287245803Stheraven		strings.push_back(str);
288245803Stheraven		return start;
289245803Stheraven	}
290245803Stheraven	else
291245803Stheraven	{
292245803Stheraven		return old->second;
293245803Stheraven	}
294245803Stheraven}
295245803Stheraven
296245803Stheravenvoid
297245803Stheravenstring_table::write(dtb::output_writer &writer)
298245803Stheraven{
299245803Stheraven	writer.write_comment(string("Strings table."));
300245803Stheraven	writer.write_label(string("dt_strings_start"));
301245803Stheraven	for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ;
302245803Stheraven	     i!=e ; ++i)
303245803Stheraven	{
304245803Stheraven		writer.write_string(*i);
305245803Stheraven	}
306245803Stheraven	writer.write_label(string("dt_strings_end"));
307245803Stheraven}
308245803Stheraven
309245803Stheraven} // namespace dtb
310245803Stheraven
311245803Stheraven} // namespace dtc
312245803Stheraven
313