xref: /freebsd/usr.bin/dtc/dtb.cc (revision a35f04fba2ebb8f86d4cbdc710c89a094572b08e)
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$
31  */
32 
33 #include "dtb.hh"
34 #include <sys/types.h>
35 #include <inttypes.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 
39 using std::string;
40 
41 namespace dtc
42 {
43 namespace dtb
44 {
45 
46 void output_writer::write_data(byte_buffer b)
47 {
48 	for (auto i : b)
49 	{
50 		write_data(i);
51 	}
52 }
53 
54 void
55 binary_writer::write_string(const string &name)
56 {
57 	push_string(buffer, name);
58 	// Trailing nul
59 	buffer.push_back(0);
60 }
61 
62 void
63 binary_writer::write_data(uint8_t v)
64 {
65 	buffer.push_back(v);
66 }
67 
68 void
69 binary_writer::write_data(uint32_t v)
70 {
71 	while (buffer.size() % 4 != 0)
72 	{
73 		buffer.push_back(0);
74 	}
75 	push_big_endian(buffer, v);
76 }
77 
78 void
79 binary_writer::write_data(uint64_t v)
80 {
81 	while (buffer.size() % 8 != 0)
82 	{
83 		buffer.push_back(0);
84 	}
85 	push_big_endian(buffer, v);
86 }
87 
88 void
89 binary_writer::write_to_file(int fd)
90 {
91 	// FIXME: Check return
92 	write(fd, buffer.data(), buffer.size());
93 }
94 
95 uint32_t
96 binary_writer::size()
97 {
98 	return buffer.size();
99 }
100 
101 void
102 asm_writer::write_line(const char *c)
103 {
104 	if (byte_count != 0)
105 	{
106 		byte_count = 0;
107 		buffer.push_back('\n');
108 	}
109 	write_string(c);
110 }
111 
112 void
113 asm_writer::write_byte(uint8_t b)
114 {
115 	char out[3] = {0};
116 	if (byte_count++ == 0)
117 	{
118 		buffer.push_back('\t');
119 	}
120 	write_string(".byte 0x");
121 	snprintf(out, 3, "%.2hhx", b);
122 	buffer.push_back(out[0]);
123 	buffer.push_back(out[1]);
124 	if (byte_count == 4)
125 	{
126 		buffer.push_back('\n');
127 		byte_count = 0;
128 	}
129 	else
130 	{
131 		buffer.push_back(';');
132 		buffer.push_back(' ');
133 	}
134 }
135 
136 void
137 asm_writer::write_label(const string &name)
138 {
139 	write_line("\t.globl ");
140 	push_string(buffer, name);
141 	buffer.push_back('\n');
142 	push_string(buffer, name);
143 	buffer.push_back(':');
144 	buffer.push_back('\n');
145 	buffer.push_back('_');
146 	push_string(buffer, name);
147 	buffer.push_back(':');
148 	buffer.push_back('\n');
149 
150 }
151 
152 void
153 asm_writer::write_comment(const string &name)
154 {
155 	write_line("\t/* ");
156 	push_string(buffer, name);
157 	write_string(" */\n");
158 }
159 
160 void
161 asm_writer::write_string(const char *c)
162 {
163 	while (*c)
164 	{
165 		buffer.push_back((uint8_t)*(c++));
166 	}
167 }
168 
169 
170 void
171 asm_writer::write_string(const string &name)
172 {
173 	write_line("\t.string \"");
174 	push_string(buffer, name);
175 	write_line("\"\n");
176 	bytes_written += name.size() + 1;
177 }
178 
179 void
180 asm_writer::write_data(uint8_t v)
181 {
182 	write_byte(v);
183 	bytes_written++;
184 }
185 
186 void
187 asm_writer::write_data(uint32_t v)
188 {
189 	if (bytes_written % 4 != 0)
190 	{
191 		write_line("\t.balign 4\n");
192 		bytes_written += (4 - (bytes_written % 4));
193 	}
194 	write_byte((v >> 24) & 0xff);
195 	write_byte((v >> 16) & 0xff);
196 	write_byte((v >> 8) & 0xff);
197 	write_byte((v >> 0) & 0xff);
198 	bytes_written += 4;
199 }
200 
201 void
202 asm_writer::write_data(uint64_t v)
203 {
204 	if (bytes_written % 8 != 0)
205 	{
206 		write_line("\t.balign 8\n");
207 		bytes_written += (8 - (bytes_written % 8));
208 	}
209 	write_byte((v >> 56) & 0xff);
210 	write_byte((v >> 48) & 0xff);
211 	write_byte((v >> 40) & 0xff);
212 	write_byte((v >> 32) & 0xff);
213 	write_byte((v >> 24) & 0xff);
214 	write_byte((v >> 16) & 0xff);
215 	write_byte((v >> 8) & 0xff);
216 	write_byte((v >> 0) & 0xff);
217 	bytes_written += 8;
218 }
219 
220 void
221 asm_writer::write_to_file(int fd)
222 {
223 	// FIXME: Check return
224 	write(fd, buffer.data(), buffer.size());
225 }
226 
227 uint32_t
228 asm_writer::size()
229 {
230 	return bytes_written;
231 }
232 
233 void
234 header::write(output_writer &out)
235 {
236 	out.write_label("dt_blob_start");
237 	out.write_label("dt_header");
238 	out.write_comment("magic");
239 	out.write_data(magic);
240 	out.write_comment("totalsize");
241 	out.write_data(totalsize);
242 	out.write_comment("off_dt_struct");
243 	out.write_data(off_dt_struct);
244 	out.write_comment("off_dt_strings");
245 	out.write_data(off_dt_strings);
246 	out.write_comment("off_mem_rsvmap");
247 	out.write_data(off_mem_rsvmap);
248 	out.write_comment("version");
249 	out.write_data(version);
250 	out.write_comment("last_comp_version");
251 	out.write_data(last_comp_version);
252 	out.write_comment("boot_cpuid_phys");
253 	out.write_data(boot_cpuid_phys);
254 	out.write_comment("size_dt_strings");
255 	out.write_data(size_dt_strings);
256 	out.write_comment("size_dt_struct");
257 	out.write_data(size_dt_struct);
258 }
259 
260 bool
261 header::read_dtb(input_buffer &input)
262 {
263 	if (!(input.consume_binary(magic) && magic == 0xd00dfeed))
264 	{
265 		fprintf(stderr, "Missing magic token in header.  Got %" PRIx32
266 		                " expected 0xd00dfeed\n", magic);
267 		return false;
268 	}
269 	return input.consume_binary(totalsize) &&
270 	       input.consume_binary(off_dt_struct) &&
271 	       input.consume_binary(off_dt_strings) &&
272 	       input.consume_binary(off_mem_rsvmap) &&
273 	       input.consume_binary(version) &&
274 	       input.consume_binary(last_comp_version) &&
275 	       input.consume_binary(boot_cpuid_phys) &&
276 	       input.consume_binary(size_dt_strings) &&
277 	       input.consume_binary(size_dt_struct);
278 }
279 uint32_t
280 string_table::add_string(const string &str)
281 {
282 	auto old = string_offsets.find(str);
283 	if (old == string_offsets.end())
284 	{
285 		uint32_t start = size;
286 		// Don't forget the trailing nul
287 		size += str.size() + 1;
288 		string_offsets.insert(std::make_pair(str, start));
289 		strings.push_back(str);
290 		return start;
291 	}
292 	else
293 	{
294 		return old->second;
295 	}
296 }
297 
298 void
299 string_table::write(dtb::output_writer &writer)
300 {
301 	writer.write_comment("Strings table.");
302 	writer.write_label("dt_strings_start");
303 	for (auto &i : strings)
304 	{
305 		writer.write_string(i);
306 	}
307 	writer.write_label("dt_strings_end");
308 }
309 
310 } // namespace dtb
311 
312 } // namespace dtc
313 
314