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