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$ 33 */ 34 35 #include "dtb.hh" 36 #include <sys/types.h> 37 #include <inttypes.h> 38 #include <stdio.h> 39 #include <unistd.h> 40 41 using std::string; 42 43 namespace dtc 44 { 45 namespace dtb 46 { 47 48 void output_writer::write_data(byte_buffer b) 49 { 50 for (auto i : b) 51 { 52 write_data(i); 53 } 54 } 55 56 void 57 binary_writer::write_string(const string &name) 58 { 59 push_string(buffer, name); 60 // Trailing nul 61 buffer.push_back(0); 62 } 63 64 void 65 binary_writer::write_data(uint8_t v) 66 { 67 buffer.push_back(v); 68 } 69 70 void 71 binary_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 80 void 81 binary_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 90 void 91 binary_writer::write_to_file(int fd) 92 { 93 // FIXME: Check return 94 write(fd, buffer.data(), buffer.size()); 95 } 96 97 uint32_t 98 binary_writer::size() 99 { 100 return buffer.size(); 101 } 102 103 void 104 asm_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 114 void 115 asm_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 138 void 139 asm_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 154 void 155 asm_writer::write_comment(const string &name) 156 { 157 write_line("\t/* "); 158 push_string(buffer, name); 159 write_string(" */\n"); 160 } 161 162 void 163 asm_writer::write_string(const char *c) 164 { 165 while (*c) 166 { 167 buffer.push_back((uint8_t)*(c++)); 168 } 169 } 170 171 172 void 173 asm_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 181 void 182 asm_writer::write_data(uint8_t v) 183 { 184 write_byte(v); 185 bytes_written++; 186 } 187 188 void 189 asm_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 203 void 204 asm_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 222 void 223 asm_writer::write_to_file(int fd) 224 { 225 // FIXME: Check return 226 write(fd, buffer.data(), buffer.size()); 227 } 228 229 uint32_t 230 asm_writer::size() 231 { 232 return bytes_written; 233 } 234 235 void 236 header::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 262 bool 263 header::read_dtb(input_buffer &input) 264 { 265 if (!input.consume_binary(magic)) 266 { 267 fprintf(stderr, "Missing magic token in header."); 268 return false; 269 } 270 if (magic != 0xd00dfeed) 271 { 272 fprintf(stderr, "Bad magic token in header. Got %" PRIx32 273 " expected 0xd00dfeed\n", magic); 274 return false; 275 } 276 return input.consume_binary(totalsize) && 277 input.consume_binary(off_dt_struct) && 278 input.consume_binary(off_dt_strings) && 279 input.consume_binary(off_mem_rsvmap) && 280 input.consume_binary(version) && 281 input.consume_binary(last_comp_version) && 282 input.consume_binary(boot_cpuid_phys) && 283 input.consume_binary(size_dt_strings) && 284 input.consume_binary(size_dt_struct); 285 } 286 uint32_t 287 string_table::add_string(const string &str) 288 { 289 auto old = string_offsets.find(str); 290 if (old == string_offsets.end()) 291 { 292 uint32_t start = size; 293 // Don't forget the trailing nul 294 size += str.size() + 1; 295 string_offsets.insert(std::make_pair(str, start)); 296 strings.push_back(str); 297 return start; 298 } 299 else 300 { 301 return old->second; 302 } 303 } 304 305 void 306 string_table::write(dtb::output_writer &writer) 307 { 308 writer.write_comment("Strings table."); 309 writer.write_label("dt_strings_start"); 310 for (auto &i : strings) 311 { 312 writer.write_string(i); 313 } 314 writer.write_label("dt_strings_end"); 315 } 316 317 } // namespace dtb 318 319 } // namespace dtc 320 321