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