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