2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2013 David Chisnall
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.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
36 #include <sys/types.h>
46 void write(dtc::byte_buffer &buffer, int fd)
48 size_t size = buffer.size();
49 uint8_t *data = buffer.data();
52 ssize_t r = ::write(fd, data, size);
58 else if (errno != EAGAIN)
60 fprintf(stderr, "Writing to file failed\n");
72 void output_writer::write_data(byte_buffer b)
81 binary_writer::write_string(const string &name)
83 push_string(buffer, name);
89 binary_writer::write_data(uint8_t v)
95 binary_writer::write_data(uint32_t v)
97 while (buffer.size() % 4 != 0)
101 push_big_endian(buffer, v);
105 binary_writer::write_data(uint64_t v)
107 while (buffer.size() % 8 != 0)
111 push_big_endian(buffer, v);
115 binary_writer::write_to_file(int fd)
121 binary_writer::size()
123 return buffer.size();
127 asm_writer::write_line(const char *c)
132 buffer.push_back('\n');
138 asm_writer::write_byte(uint8_t b)
141 if (byte_count++ == 0)
143 buffer.push_back('\t');
145 write_string(".byte 0x");
146 snprintf(out, 3, "%.2hhx", b);
147 buffer.push_back(out[0]);
148 buffer.push_back(out[1]);
151 buffer.push_back('\n');
156 buffer.push_back(';');
157 buffer.push_back(' ');
162 asm_writer::write_label(const string &name)
164 write_line("\t.globl ");
165 push_string(buffer, name);
166 buffer.push_back('\n');
167 push_string(buffer, name);
168 buffer.push_back(':');
169 buffer.push_back('\n');
170 buffer.push_back('_');
171 push_string(buffer, name);
172 buffer.push_back(':');
173 buffer.push_back('\n');
178 asm_writer::write_comment(const string &name)
181 push_string(buffer, name);
182 write_string(" */\n");
186 asm_writer::write_string(const char *c)
190 buffer.push_back((uint8_t)*(c++));
196 asm_writer::write_string(const string &name)
198 write_line("\t.string \"");
199 push_string(buffer, name);
201 bytes_written += name.size() + 1;
205 asm_writer::write_data(uint8_t v)
212 asm_writer::write_data(uint32_t v)
214 if (bytes_written % 4 != 0)
216 write_line("\t.balign 4\n");
217 bytes_written += (4 - (bytes_written % 4));
219 write_byte((v >> 24) & 0xff);
220 write_byte((v >> 16) & 0xff);
221 write_byte((v >> 8) & 0xff);
222 write_byte((v >> 0) & 0xff);
227 asm_writer::write_data(uint64_t v)
229 if (bytes_written % 8 != 0)
231 write_line("\t.balign 8\n");
232 bytes_written += (8 - (bytes_written % 8));
234 write_byte((v >> 56) & 0xff);
235 write_byte((v >> 48) & 0xff);
236 write_byte((v >> 40) & 0xff);
237 write_byte((v >> 32) & 0xff);
238 write_byte((v >> 24) & 0xff);
239 write_byte((v >> 16) & 0xff);
240 write_byte((v >> 8) & 0xff);
241 write_byte((v >> 0) & 0xff);
246 asm_writer::write_to_file(int fd)
254 return bytes_written;
258 header::write(output_writer &out)
260 out.write_label("dt_blob_start");
261 out.write_label("dt_header");
262 out.write_comment("magic");
263 out.write_data(magic);
264 out.write_comment("totalsize");
265 out.write_data(totalsize);
266 out.write_comment("off_dt_struct");
267 out.write_data(off_dt_struct);
268 out.write_comment("off_dt_strings");
269 out.write_data(off_dt_strings);
270 out.write_comment("off_mem_rsvmap");
271 out.write_data(off_mem_rsvmap);
272 out.write_comment("version");
273 out.write_data(version);
274 out.write_comment("last_comp_version");
275 out.write_data(last_comp_version);
276 out.write_comment("boot_cpuid_phys");
277 out.write_data(boot_cpuid_phys);
278 out.write_comment("size_dt_strings");
279 out.write_data(size_dt_strings);
280 out.write_comment("size_dt_struct");
281 out.write_data(size_dt_struct);
285 header::read_dtb(input_buffer &input)
287 if (!input.consume_binary(magic))
289 fprintf(stderr, "Missing magic token in header.");
292 if (magic != 0xd00dfeed)
294 fprintf(stderr, "Bad magic token in header. Got %" PRIx32
295 " expected 0xd00dfeed\n", magic);
298 return input.consume_binary(totalsize) &&
299 input.consume_binary(off_dt_struct) &&
300 input.consume_binary(off_dt_strings) &&
301 input.consume_binary(off_mem_rsvmap) &&
302 input.consume_binary(version) &&
303 input.consume_binary(last_comp_version) &&
304 input.consume_binary(boot_cpuid_phys) &&
305 input.consume_binary(size_dt_strings) &&
306 input.consume_binary(size_dt_struct);
309 string_table::add_string(const string &str)
311 auto old = string_offsets.find(str);
312 if (old == string_offsets.end())
314 uint32_t start = size;
315 // Don't forget the trailing nul
316 size += str.size() + 1;
317 string_offsets.insert(std::make_pair(str, start));
318 strings.push_back(str);
328 string_table::write(dtb::output_writer &writer)
330 writer.write_comment("Strings table.");
331 writer.write_label("dt_strings_start");
332 for (auto &i : strings)
334 writer.write_string(i);
336 writer.write_label("dt_strings_end");