2 * Copyright (c) 2013 David Chisnall
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.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/types.h>
45 void output_writer::write_data(byte_buffer b)
47 for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++)
54 binary_writer::write_string(string name)
56 name.push_to_buffer(buffer);
62 binary_writer::write_data(uint8_t v)
68 binary_writer::write_data(uint32_t v)
70 while (buffer.size() % 4 != 0)
74 push_big_endian(buffer, v);
78 binary_writer::write_data(uint64_t v)
80 while (buffer.size() % 8 != 0)
84 push_big_endian(buffer, v);
88 binary_writer::write_to_file(int fd)
90 // FIXME: Check return
91 write(fd, buffer.data(), buffer.size());
101 asm_writer::write_string(const char *c)
105 buffer.push_back((uint8_t)*(c++));
110 asm_writer::write_line(const char *c)
115 buffer.push_back('\n');
121 asm_writer::write_byte(uint8_t b)
124 if (byte_count++ == 0)
126 buffer.push_back('\t');
128 write_string(".byte 0x");
129 snprintf(out, 3, "%.2hhx", b);
130 buffer.push_back(out[0]);
131 buffer.push_back(out[1]);
134 buffer.push_back('\n');
139 buffer.push_back(';');
140 buffer.push_back(' ');
145 asm_writer::write_label(string name)
147 write_line("\t.globl ");
148 name.push_to_buffer(buffer);
149 buffer.push_back('\n');
150 name.push_to_buffer(buffer);
151 buffer.push_back(':');
152 buffer.push_back('\n');
153 buffer.push_back('_');
154 name.push_to_buffer(buffer);
155 buffer.push_back(':');
156 buffer.push_back('\n');
161 asm_writer::write_comment(string name)
164 name.push_to_buffer(buffer);
165 write_string(" */\n");
169 asm_writer::write_string(string name)
171 write_line("\t.string \"");
172 name.push_to_buffer(buffer);
174 bytes_written += name.size() + 1;
178 asm_writer::write_data(uint8_t v)
185 asm_writer::write_data(uint32_t v)
187 if (bytes_written % 4 != 0)
189 write_line("\t.balign 4\n");
190 bytes_written += (4 - (bytes_written % 4));
192 write_byte((v >> 24) & 0xff);
193 write_byte((v >> 16) & 0xff);
194 write_byte((v >> 8) & 0xff);
195 write_byte((v >> 0) & 0xff);
200 asm_writer::write_data(uint64_t v)
202 if (bytes_written % 8 != 0)
204 write_line("\t.balign 8\n");
205 bytes_written += (8 - (bytes_written % 8));
207 write_byte((v >> 56) & 0xff);
208 write_byte((v >> 48) & 0xff);
209 write_byte((v >> 40) & 0xff);
210 write_byte((v >> 32) & 0xff);
211 write_byte((v >> 24) & 0xff);
212 write_byte((v >> 16) & 0xff);
213 write_byte((v >> 8) & 0xff);
214 write_byte((v >> 0) & 0xff);
219 asm_writer::write_to_file(int fd)
221 // FIXME: Check return
222 write(fd, buffer.data(), buffer.size());
228 return bytes_written;
232 header::write(output_writer &out)
234 out.write_label(string("dt_blob_start"));
235 out.write_label(string("dt_header"));
236 out.write_comment("magic");
237 out.write_data(magic);
238 out.write_comment("totalsize");
239 out.write_data(totalsize);
240 out.write_comment("off_dt_struct");
241 out.write_data(off_dt_struct);
242 out.write_comment("off_dt_strings");
243 out.write_data(off_dt_strings);
244 out.write_comment("off_mem_rsvmap");
245 out.write_data(off_mem_rsvmap);
246 out.write_comment("version");
247 out.write_data(version);
248 out.write_comment("last_comp_version");
249 out.write_data(last_comp_version);
250 out.write_comment("boot_cpuid_phys");
251 out.write_data(boot_cpuid_phys);
252 out.write_comment("size_dt_strings");
253 out.write_data(size_dt_strings);
254 out.write_comment("size_dt_struct");
255 out.write_data(size_dt_struct);
259 header::read_dtb(input_buffer &input)
261 if (!(input.consume_binary(magic) && magic == 0xd00dfeed))
263 fprintf(stderr, "Missing magic token in header. Got %" PRIx32
264 " expected 0xd00dfeed\n", magic);
267 return input.consume_binary(totalsize) &&
268 input.consume_binary(off_dt_struct) &&
269 input.consume_binary(off_dt_strings) &&
270 input.consume_binary(off_mem_rsvmap) &&
271 input.consume_binary(version) &&
272 input.consume_binary(last_comp_version) &&
273 input.consume_binary(boot_cpuid_phys) &&
274 input.consume_binary(size_dt_strings) &&
275 input.consume_binary(size_dt_struct);
278 string_table::add_string(string str)
280 std::map<string, uint32_t>::iterator old = string_offsets.find(str);
281 if (old == string_offsets.end())
283 uint32_t start = size;
284 // Don't forget the trailing nul
285 size += str.size() + 1;
286 string_offsets.insert(std::make_pair(str, start));
287 strings.push_back(str);
297 string_table::write(dtb::output_writer &writer)
299 writer.write_comment(string("Strings table."));
300 writer.write_label(string("dt_strings_start"));
301 for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ;
304 writer.write_string(*i);
306 writer.write_label(string("dt_strings_end"));