dtb.cc revision 318093
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: stable/11/usr.bin/dtc/dtb.cc 318093 2017-05-09 18:46:49Z gonzo $ 31 */ 32 33#include "dtb.hh" 34#include <sys/types.h> 35#include <inttypes.h> 36#include <stdio.h> 37#include <unistd.h> 38 39using std::string; 40 41namespace dtc 42{ 43namespace dtb 44{ 45 46void output_writer::write_data(byte_buffer b) 47{ 48 for (auto i : b) 49 { 50 write_data(i); 51 } 52} 53 54void 55binary_writer::write_string(const string &name) 56{ 57 push_string(buffer, name); 58 // Trailing nul 59 buffer.push_back(0); 60} 61 62void 63binary_writer::write_data(uint8_t v) 64{ 65 buffer.push_back(v); 66} 67 68void 69binary_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 78void 79binary_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 88void 89binary_writer::write_to_file(int fd) 90{ 91 // FIXME: Check return 92 write(fd, buffer.data(), buffer.size()); 93} 94 95uint32_t 96binary_writer::size() 97{ 98 return buffer.size(); 99} 100 101void 102asm_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 112void 113asm_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 136void 137asm_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 152void 153asm_writer::write_comment(const string &name) 154{ 155 write_line("\t/* "); 156 push_string(buffer, name); 157 write_string(" */\n"); 158} 159 160void 161asm_writer::write_string(const char *c) 162{ 163 while (*c) 164 { 165 buffer.push_back((uint8_t)*(c++)); 166 } 167} 168 169 170void 171asm_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 179void 180asm_writer::write_data(uint8_t v) 181{ 182 write_byte(v); 183 bytes_written++; 184} 185 186void 187asm_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 201void 202asm_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 220void 221asm_writer::write_to_file(int fd) 222{ 223 // FIXME: Check return 224 write(fd, buffer.data(), buffer.size()); 225} 226 227uint32_t 228asm_writer::size() 229{ 230 return bytes_written; 231} 232 233void 234header::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 260bool 261header::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} 279uint32_t 280string_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 298void 299string_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