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