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