1245803Stheraven/*- 2245803Stheraven * Copyright (c) 2013 David Chisnall 3245803Stheraven * All rights reserved. 4245803Stheraven * 5245803Stheraven * This software was developed by SRI International and the University of 6245803Stheraven * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7245803Stheraven * ("CTSRD"), as part of the DARPA CRASH research programme. 8245803Stheraven * 9245803Stheraven * Redistribution and use in source and binary forms, with or without 10245803Stheraven * modification, are permitted provided that the following conditions 11245803Stheraven * are met: 12245803Stheraven * 1. Redistributions of source code must retain the above copyright 13245803Stheraven * notice, this list of conditions and the following disclaimer. 14245803Stheraven * 2. Redistributions in binary form must reproduce the above copyright 15245803Stheraven * notice, this list of conditions and the following disclaimer in the 16245803Stheraven * documentation and/or other materials provided with the distribution. 17245803Stheraven * 18245803Stheraven * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19245803Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20245803Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21245803Stheraven * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22245803Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23245803Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24245803Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25245803Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26245803Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27245803Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28245803Stheraven * SUCH DAMAGE. 29245803Stheraven * 30245803Stheraven * $FreeBSD$ 31245803Stheraven */ 32245803Stheraven 33245803Stheraven#include "dtb.hh" 34245839Stheraven#include <sys/types.h> 35245803Stheraven#include <inttypes.h> 36245839Stheraven#include <stdio.h> 37245839Stheraven#include <unistd.h> 38245803Stheraven 39245839Stheraven 40245803Stheravennamespace dtc 41245803Stheraven{ 42245803Stheravennamespace dtb 43245803Stheraven{ 44245803Stheraven 45245803Stheravenvoid output_writer::write_data(byte_buffer b) 46245803Stheraven{ 47245803Stheraven for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++) 48245803Stheraven { 49245803Stheraven write_data(*i); 50245803Stheraven } 51245803Stheraven} 52245803Stheraven 53245803Stheravenvoid 54245803Stheravenbinary_writer::write_string(string name) 55245803Stheraven{ 56245803Stheraven name.push_to_buffer(buffer); 57245803Stheraven // Trailing nul 58245803Stheraven buffer.push_back(0); 59245803Stheraven} 60245803Stheraven 61245803Stheravenvoid 62245803Stheravenbinary_writer::write_data(uint8_t v) 63245803Stheraven{ 64245803Stheraven buffer.push_back(v); 65245803Stheraven} 66245803Stheraven 67245803Stheravenvoid 68245803Stheravenbinary_writer::write_data(uint32_t v) 69245803Stheraven{ 70245803Stheraven while (buffer.size() % 4 != 0) 71245803Stheraven { 72245803Stheraven buffer.push_back(0); 73245803Stheraven } 74245803Stheraven push_big_endian(buffer, v); 75245803Stheraven} 76245803Stheraven 77245803Stheravenvoid 78245803Stheravenbinary_writer::write_data(uint64_t v) 79245803Stheraven{ 80245803Stheraven while (buffer.size() % 8 != 0) 81245803Stheraven { 82245803Stheraven buffer.push_back(0); 83245803Stheraven } 84245803Stheraven push_big_endian(buffer, v); 85245803Stheraven} 86245803Stheraven 87245803Stheravenvoid 88245803Stheravenbinary_writer::write_to_file(int fd) 89245803Stheraven{ 90245803Stheraven // FIXME: Check return 91245803Stheraven write(fd, buffer.data(), buffer.size()); 92245803Stheraven} 93245803Stheraven 94245803Stheravenuint32_t 95245803Stheravenbinary_writer::size() 96245803Stheraven{ 97245803Stheraven return buffer.size(); 98245803Stheraven} 99245803Stheraven 100245803Stheravenvoid 101245803Stheravenasm_writer::write_string(const char *c) 102245803Stheraven{ 103245803Stheraven while (*c) 104245803Stheraven { 105245803Stheraven buffer.push_back((uint8_t)*(c++)); 106245803Stheraven } 107245803Stheraven} 108245803Stheraven 109245803Stheravenvoid 110245803Stheravenasm_writer::write_line(const char *c) 111245803Stheraven{ 112245803Stheraven if (byte_count != 0) 113245803Stheraven { 114245803Stheraven byte_count = 0; 115245803Stheraven buffer.push_back('\n'); 116245803Stheraven } 117245803Stheraven write_string(c); 118245803Stheraven} 119245803Stheraven 120245803Stheravenvoid 121245803Stheravenasm_writer::write_byte(uint8_t b) 122245803Stheraven{ 123245803Stheraven char out[3] = {0}; 124245803Stheraven if (byte_count++ == 0) 125245803Stheraven { 126245803Stheraven buffer.push_back('\t'); 127245803Stheraven } 128245803Stheraven write_string(".byte 0x"); 129245803Stheraven snprintf(out, 3, "%.2hhx", b); 130245803Stheraven buffer.push_back(out[0]); 131245803Stheraven buffer.push_back(out[1]); 132245803Stheraven if (byte_count == 4) 133245803Stheraven { 134245803Stheraven buffer.push_back('\n'); 135245803Stheraven byte_count = 0; 136245803Stheraven } 137245803Stheraven else 138245803Stheraven { 139245803Stheraven buffer.push_back(';'); 140245803Stheraven buffer.push_back(' '); 141245803Stheraven } 142245803Stheraven} 143245803Stheraven 144245803Stheravenvoid 145245803Stheravenasm_writer::write_label(string name) 146245803Stheraven{ 147245803Stheraven write_line("\t.globl "); 148245803Stheraven name.push_to_buffer(buffer); 149245803Stheraven buffer.push_back('\n'); 150245803Stheraven name.push_to_buffer(buffer); 151245803Stheraven buffer.push_back(':'); 152245803Stheraven buffer.push_back('\n'); 153245803Stheraven buffer.push_back('_'); 154245803Stheraven name.push_to_buffer(buffer); 155245803Stheraven buffer.push_back(':'); 156245803Stheraven buffer.push_back('\n'); 157245803Stheraven 158245803Stheraven} 159245803Stheraven 160245803Stheravenvoid 161245803Stheravenasm_writer::write_comment(string name) 162245803Stheraven{ 163245803Stheraven write_line("\t/* "); 164245803Stheraven name.push_to_buffer(buffer); 165245803Stheraven write_string(" */\n"); 166245803Stheraven} 167245803Stheraven 168245803Stheravenvoid 169245803Stheravenasm_writer::write_string(string name) 170245803Stheraven{ 171245803Stheraven write_line("\t.string \""); 172245803Stheraven name.push_to_buffer(buffer); 173245803Stheraven write_line("\"\n"); 174245803Stheraven bytes_written += name.size() + 1; 175245803Stheraven} 176245803Stheraven 177245803Stheravenvoid 178245803Stheravenasm_writer::write_data(uint8_t v) 179245803Stheraven{ 180245803Stheraven write_byte(v); 181245803Stheraven bytes_written++; 182245803Stheraven} 183245803Stheraven 184245803Stheravenvoid 185245803Stheravenasm_writer::write_data(uint32_t v) 186245803Stheraven{ 187245803Stheraven if (bytes_written % 4 != 0) 188245803Stheraven { 189245803Stheraven write_line("\t.balign 4\n"); 190245803Stheraven bytes_written += (4 - (bytes_written % 4)); 191245803Stheraven } 192245803Stheraven write_byte((v >> 24) & 0xff); 193245803Stheraven write_byte((v >> 16) & 0xff); 194245803Stheraven write_byte((v >> 8) & 0xff); 195245803Stheraven write_byte((v >> 0) & 0xff); 196245803Stheraven bytes_written += 4; 197245803Stheraven} 198245803Stheraven 199245803Stheravenvoid 200245803Stheravenasm_writer::write_data(uint64_t v) 201245803Stheraven{ 202245803Stheraven if (bytes_written % 8 != 0) 203245803Stheraven { 204245803Stheraven write_line("\t.balign 8\n"); 205245803Stheraven bytes_written += (8 - (bytes_written % 8)); 206245803Stheraven } 207245803Stheraven write_byte((v >> 56) & 0xff); 208245803Stheraven write_byte((v >> 48) & 0xff); 209245803Stheraven write_byte((v >> 40) & 0xff); 210245803Stheraven write_byte((v >> 32) & 0xff); 211245803Stheraven write_byte((v >> 24) & 0xff); 212245803Stheraven write_byte((v >> 16) & 0xff); 213245803Stheraven write_byte((v >> 8) & 0xff); 214245803Stheraven write_byte((v >> 0) & 0xff); 215245803Stheraven bytes_written += 8; 216245803Stheraven} 217245803Stheraven 218245803Stheravenvoid 219245803Stheravenasm_writer::write_to_file(int fd) 220245803Stheraven{ 221245803Stheraven // FIXME: Check return 222245803Stheraven write(fd, buffer.data(), buffer.size()); 223245803Stheraven} 224245803Stheraven 225245803Stheravenuint32_t 226245803Stheravenasm_writer::size() 227245803Stheraven{ 228245803Stheraven return bytes_written; 229245803Stheraven} 230245803Stheraven 231245803Stheravenvoid 232245803Stheravenheader::write(output_writer &out) 233245803Stheraven{ 234245803Stheraven out.write_label(string("dt_blob_start")); 235245803Stheraven out.write_label(string("dt_header")); 236245803Stheraven out.write_comment("magic"); 237245803Stheraven out.write_data(magic); 238245803Stheraven out.write_comment("totalsize"); 239245803Stheraven out.write_data(totalsize); 240245803Stheraven out.write_comment("off_dt_struct"); 241245803Stheraven out.write_data(off_dt_struct); 242245803Stheraven out.write_comment("off_dt_strings"); 243245803Stheraven out.write_data(off_dt_strings); 244245803Stheraven out.write_comment("off_mem_rsvmap"); 245245803Stheraven out.write_data(off_mem_rsvmap); 246245803Stheraven out.write_comment("version"); 247245803Stheraven out.write_data(version); 248245803Stheraven out.write_comment("last_comp_version"); 249245803Stheraven out.write_data(last_comp_version); 250245803Stheraven out.write_comment("boot_cpuid_phys"); 251245803Stheraven out.write_data(boot_cpuid_phys); 252245803Stheraven out.write_comment("size_dt_strings"); 253245803Stheraven out.write_data(size_dt_strings); 254245803Stheraven out.write_comment("size_dt_struct"); 255245803Stheraven out.write_data(size_dt_struct); 256245803Stheraven} 257245803Stheraven 258245803Stheravenbool 259245803Stheravenheader::read_dtb(input_buffer &input) 260245803Stheraven{ 261245803Stheraven if (!(input.consume_binary(magic) && magic == 0xd00dfeed)) 262245803Stheraven { 263245803Stheraven fprintf(stderr, "Missing magic token in header. Got %" PRIx32 264245803Stheraven " expected 0xd00dfeed\n", magic); 265245803Stheraven return false; 266245803Stheraven } 267245803Stheraven return input.consume_binary(totalsize) && 268245803Stheraven input.consume_binary(off_dt_struct) && 269245803Stheraven input.consume_binary(off_dt_strings) && 270245803Stheraven input.consume_binary(off_mem_rsvmap) && 271245803Stheraven input.consume_binary(version) && 272245803Stheraven input.consume_binary(last_comp_version) && 273245803Stheraven input.consume_binary(boot_cpuid_phys) && 274245803Stheraven input.consume_binary(size_dt_strings) && 275245803Stheraven input.consume_binary(size_dt_struct); 276245803Stheraven} 277245803Stheravenuint32_t 278245803Stheravenstring_table::add_string(string str) 279245803Stheraven{ 280245803Stheraven std::map<string, uint32_t>::iterator old = string_offsets.find(str); 281245803Stheraven if (old == string_offsets.end()) 282245803Stheraven { 283245803Stheraven uint32_t start = size; 284245803Stheraven // Don't forget the trailing nul 285245803Stheraven size += str.size() + 1; 286245803Stheraven string_offsets.insert(std::make_pair(str, start)); 287245803Stheraven strings.push_back(str); 288245803Stheraven return start; 289245803Stheraven } 290245803Stheraven else 291245803Stheraven { 292245803Stheraven return old->second; 293245803Stheraven } 294245803Stheraven} 295245803Stheraven 296245803Stheravenvoid 297245803Stheravenstring_table::write(dtb::output_writer &writer) 298245803Stheraven{ 299245803Stheraven writer.write_comment(string("Strings table.")); 300245803Stheraven writer.write_label(string("dt_strings_start")); 301245803Stheraven for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ; 302245803Stheraven i!=e ; ++i) 303245803Stheraven { 304245803Stheraven writer.write_string(*i); 305245803Stheraven } 306245803Stheraven writer.write_label(string("dt_strings_end")); 307245803Stheraven} 308245803Stheraven 309245803Stheraven} // namespace dtb 310245803Stheraven 311245803Stheraven} // namespace dtc 312245803Stheraven 313