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#ifndef _DTB_HH_ 34245803Stheraven#define _DTB_HH_ 35245803Stheraven#include <map> 36245803Stheraven#include "string.hh" 37245803Stheraven 38245803Stheraven#include <assert.h> 39245803Stheraven 40245803Stheravennamespace dtc 41245803Stheraven{ 42245803Stheraven/** 43245803Stheraven * The dtb namespace contains code related to the generation of device tree 44245803Stheraven * blobs, the binary representation of flattened device trees. The abstract 45245803Stheraven * tree representation calls into this code to generate the output. 46245803Stheraven */ 47245803Stheravennamespace dtb 48245803Stheraven{ 49245803Stheraven/** The token types in the DTB, as defined by ��7.4.1 of the ePAPR 50245803Stheraven * specification. All of these values are written in big-endian format in the 51245803Stheraven * output. 52245803Stheraven */ 53245803Stheravenenum token_type 54245803Stheraven{ 55245803Stheraven /** 56245803Stheraven * Marker indicating the start of a node in the tree. This is followed 57245803Stheraven * by the nul-terminated name. If a unit address is specified, then 58245803Stheraven * the name also contains the address, with an @ symbol between the end 59245803Stheraven * of the name and the start of the address. 60245803Stheraven * 61245803Stheraven * The name is then padded such that the next token begins on a 4-byte 62245803Stheraven * boundary. The node may contain properties, other nodes, both, or be 63245803Stheraven * empty. 64245803Stheraven */ 65245803Stheraven FDT_BEGIN_NODE = 0x00000001, 66245803Stheraven /** 67245803Stheraven * Marker indicating the end of a node. 68245803Stheraven */ 69245803Stheraven FDT_END_NODE = 0x00000002, 70245803Stheraven /** 71245803Stheraven * The start of a property. This is followed by two 32-bit big-endian 72245803Stheraven * values. The first indicates the length of the property value, the 73245803Stheraven * second its index in the strings table. It is then followed by the 74245803Stheraven * property value, if the value is of non-zero length. 75245803Stheraven */ 76245803Stheraven FDT_PROP = 0x00000003, 77245803Stheraven /** 78245803Stheraven * Ignored token. May be used for padding inside DTB nodes. 79245803Stheraven */ 80245803Stheraven FDT_NOP = 0x00000004, 81245803Stheraven /** 82245803Stheraven * Marker indicating the end of the tree. 83245803Stheraven */ 84245803Stheraven FDT_END = 0x00000009 85245803Stheraven}; 86245803Stheraven 87245803Stheraven/** 88245803Stheraven * Returns the token as a string. This is used for debugging and for printing 89245803Stheraven * human-friendly error messages about malformed DTB input. 90245803Stheraven */ 91245803Stheraveninline const char *token_type_name(token_type t) 92245803Stheraven{ 93245803Stheraven switch(t) 94245803Stheraven { 95245803Stheraven case FDT_BEGIN_NODE: 96245803Stheraven return "FDT_BEGIN_NODE"; 97245803Stheraven case FDT_END_NODE: 98245803Stheraven return "FDT_END_NODE"; 99245803Stheraven case FDT_PROP: 100245803Stheraven return "FDT_PROP"; 101245803Stheraven case FDT_NOP: 102245803Stheraven return "FDT_NOP"; 103245803Stheraven case FDT_END: 104245803Stheraven return "FDT_END"; 105245803Stheraven } 106245803Stheraven assert(0); 107245803Stheraven} 108245803Stheraven 109245803Stheraven/** 110245803Stheraven * Abstract class for writing a section of the output. We create one 111245803Stheraven * of these for each section that needs to be written. It is intended to build 112245803Stheraven * a temporary buffer of the output in memory and then write it to a file 113245803Stheraven * stream. The size can be returned after all of the data has been written 114245803Stheraven * into the internal buffer, so the sizes of the three tables can be calculated 115245803Stheraven * before storing them in the buffer. 116245803Stheraven */ 117245803Stheravenstruct output_writer 118245803Stheraven{ 119245803Stheraven /** 120245803Stheraven * Writes a label into the output stream. This is only applicable for 121245803Stheraven * assembly output, where the labels become symbols that can be 122245803Stheraven * resolved at link time. 123245803Stheraven */ 124245803Stheraven virtual void write_label(string name) = 0; 125245803Stheraven /** 126245803Stheraven * Writes a comment into the output stream. Useful only when debugging 127245803Stheraven * the output. 128245803Stheraven */ 129245803Stheraven virtual void write_comment(string name) = 0; 130245803Stheraven /** 131245803Stheraven * Writes a string. A nul terminator is implicitly added. 132245803Stheraven */ 133245803Stheraven virtual void write_string(string name) = 0; 134245803Stheraven /** 135245803Stheraven * Writes a single 8-bit value. 136245803Stheraven */ 137245803Stheraven virtual void write_data(uint8_t) = 0; 138245803Stheraven /** 139245803Stheraven * Writes a single 32-bit value. The value is written in big-endian 140245803Stheraven * format, but should be passed in the host's native endian. 141245803Stheraven */ 142245803Stheraven virtual void write_data(uint32_t) = 0; 143245803Stheraven /** 144245803Stheraven * Writes a single 64-bit value. The value is written in big-endian 145245803Stheraven * format, but should be passed in the host's native endian. 146245803Stheraven */ 147245803Stheraven virtual void write_data(uint64_t) = 0; 148245803Stheraven /** 149245803Stheraven * Writes the collected output to the specified file descriptor. 150245803Stheraven */ 151245803Stheraven virtual void write_to_file(int fd) = 0; 152245803Stheraven /** 153245803Stheraven * Returns the number of bytes. 154245803Stheraven */ 155245803Stheraven virtual uint32_t size() = 0; 156245803Stheraven /** 157245803Stheraven * Helper for writing tokens to the output stream. This writes a 158245803Stheraven * comment above the token describing its value, for easier debugging 159245803Stheraven * of the output. 160245803Stheraven */ 161245803Stheraven inline void write_token(token_type t) 162245803Stheraven { 163245803Stheraven write_comment(token_type_name(t)); 164245803Stheraven write_data((uint32_t)t); 165245803Stheraven } 166245803Stheraven /** 167245803Stheraven * Helper function that writes a byte buffer to the output, one byte at 168245803Stheraven * a time. 169245803Stheraven */ 170245803Stheraven void write_data(byte_buffer b); 171245803Stheraven}; 172245803Stheraven 173245803Stheraven/** 174245803Stheraven * Binary file writer. This class is responsible for writing the DTB output 175245803Stheraven * directly in blob format. 176245803Stheraven */ 177245803Stheravenclass binary_writer : public output_writer 178245803Stheraven{ 179245803Stheraven /** 180245803Stheraven * The internal buffer used to store the blob while it is being 181245803Stheraven * constructed. 182245803Stheraven */ 183245803Stheraven byte_buffer buffer; 184245803Stheraven public: 185245803Stheraven /** 186245803Stheraven * The binary format does not support labels, so this method 187245803Stheraven * does nothing. 188245803Stheraven */ 189245803Stheraven virtual void write_label(string name) {} 190245803Stheraven /** 191245803Stheraven * Comments are ignored by the binary writer. 192245803Stheraven */ 193245803Stheraven virtual void write_comment(string name) {} 194245803Stheraven virtual void write_string(string name); 195245803Stheraven virtual void write_data(uint8_t v); 196245803Stheraven virtual void write_data(uint32_t v); 197245803Stheraven virtual void write_data(uint64_t v); 198245803Stheraven virtual void write_to_file(int fd); 199245803Stheraven virtual uint32_t size(); 200245803Stheraven}; 201245803Stheraven/** 202245803Stheraven * Assembly writer. This class is responsible for writing the output in an 203245803Stheraven * assembly format that is suitable for linking into a kernel, loader, and so 204245803Stheraven * on. 205245803Stheraven */ 206245803Stheravenclass asm_writer : public output_writer 207245803Stheraven{ 208245803Stheraven /** 209245803Stheraven * The internal buffer for temporary values. Note that this actually 210245803Stheraven * contains ASCII text, but it is a byte buffer so that we can just 211245803Stheraven * copy strings across as-is. 212245803Stheraven */ 213245803Stheraven byte_buffer buffer; 214245803Stheraven /** 215245803Stheraven * The number of bytes written to the current line. This is used to 216245803Stheraven * allow line wrapping, where we aim to write four .byte directives to 217245803Stheraven * make the alignment clearer. 218245803Stheraven */ 219245803Stheraven int byte_count; 220245803Stheraven /** 221245803Stheraven * The current number of bytes written. This is the number in binary 222245803Stheraven * format, not the number of bytes in the buffer. 223245803Stheraven */ 224245803Stheraven uint32_t bytes_written; 225245803Stheraven 226245803Stheraven /** 227245803Stheraven * Writes a C string directly to the ouput as-is. This is mainly used 228245803Stheraven * for writing directives. 229245803Stheraven */ 230245803Stheraven void write_string(const char *c); 231245803Stheraven /** 232245803Stheraven * Writes the string, starting on a new line. 233245803Stheraven */ 234245803Stheraven void write_line(const char *c); 235245803Stheraven /** 236245803Stheraven * Writes a byte in binary format. This will emit a single .byte 237245803Stheraven * directive, with up to four per line. 238245803Stheraven */ 239245803Stheraven void write_byte(uint8_t b); 240245803Stheraven public: 241245803Stheraven asm_writer() : byte_count(0), bytes_written(0) {} 242245803Stheraven virtual void write_label(string name); 243245803Stheraven virtual void write_comment(string name); 244245803Stheraven virtual void write_string(string name); 245245803Stheraven virtual void write_data(uint8_t v); 246245803Stheraven virtual void write_data(uint32_t v); 247245803Stheraven virtual void write_data(uint64_t v); 248245803Stheraven virtual void write_to_file(int fd); 249245803Stheraven virtual uint32_t size(); 250245803Stheraven}; 251245803Stheraven 252245803Stheraven/** 253245803Stheraven * Class encapsulating the device tree blob header. This class stores all of 254245803Stheraven * the values found in the header and is responsible for writing them to the 255245803Stheraven * output. 256245803Stheraven */ 257245803Stheravenstruct header 258245803Stheraven{ 259245803Stheraven /** 260245803Stheraven * Magic value, used to validate that this really is a device tree 261245803Stheraven * blob. Should always be set to 0xd00dfeed. 262245803Stheraven */ 263245803Stheraven uint32_t magic; 264245803Stheraven /** 265245803Stheraven * The total size of the blob, including header, reservations, strings 266245803Stheraven * table, and padding. 267245803Stheraven */ 268245803Stheraven uint32_t totalsize; 269245803Stheraven /** 270245803Stheraven * The offset from the start of the blob of the struct table (i.e. the 271245803Stheraven * part of the blob containing the entire device tree). 272245803Stheraven */ 273245803Stheraven uint32_t off_dt_struct; 274245803Stheraven /** 275245803Stheraven * The offset from the start of the blob of the strings table. 276245803Stheraven */ 277245803Stheraven uint32_t off_dt_strings; 278245803Stheraven /** 279245803Stheraven * The offset of the reservation map from the start of the blob. 280245803Stheraven */ 281245803Stheraven uint32_t off_mem_rsvmap; 282245803Stheraven /** 283245803Stheraven * The version of the blob. This should always be 17. 284245803Stheraven */ 285245803Stheraven uint32_t version; 286245803Stheraven /** 287245803Stheraven * The earliest version of the DTB specification with which this blob 288245803Stheraven * is backwards compatible. This should always be 16. 289245803Stheraven */ 290245803Stheraven uint32_t last_comp_version; 291245803Stheraven /** 292245803Stheraven * The ID of the CPU where this boots. 293245803Stheraven */ 294245803Stheraven uint32_t boot_cpuid_phys; 295245803Stheraven /** 296245803Stheraven * The size of the strings table. 297245803Stheraven */ 298245803Stheraven uint32_t size_dt_strings; 299245803Stheraven /** 300245803Stheraven * The size of the struct table. 301245803Stheraven */ 302245803Stheraven uint32_t size_dt_struct; 303245803Stheraven /** 304245803Stheraven * Writes the entire header to the specified output buffer. 305245803Stheraven */ 306245803Stheraven void write(output_writer &out); 307245803Stheraven /** 308245803Stheraven * Reads the header from bits binary representation in a blob. 309245803Stheraven */ 310245803Stheraven bool read_dtb(input_buffer &input); 311245803Stheraven /** 312245803Stheraven * Default constructor. Initialises the values that have sensible 313245803Stheraven * defaults, leaves the others blank. 314245803Stheraven */ 315245803Stheraven header() : magic(0xd00dfeed), version(17), last_comp_version(16), 316245803Stheraven boot_cpuid_phys(0) {} 317245803Stheraven}; 318245803Stheraven 319245803Stheraven/** 320245803Stheraven * Class encapsulating the string table. FDT strings are stored in a string 321245803Stheraven * section. This maintains a map from strings to their offsets in the strings 322245803Stheraven * section. 323245803Stheraven * 324245803Stheraven * Note: We don't currently do suffix matching, which may save a small amount 325245803Stheraven * of space. 326245803Stheraven */ 327245803Stheravenclass string_table { 328245803Stheraven /** 329245803Stheraven * Map from strings to their offset. 330245803Stheraven */ 331245803Stheraven std::map<string, uint32_t> string_offsets; 332245803Stheraven /** 333245803Stheraven * The strings, in the order in which they should be written to the 334245803Stheraven * output. The order must be stable - adding another string must not 335245803Stheraven * change the offset of any that we have already referenced - and so we 336245803Stheraven * simply write the strings in the order that they are passed. 337245803Stheraven */ 338245803Stheraven std::vector<string> strings; 339245803Stheraven /** 340245803Stheraven * The current size of the strings section. 341245803Stheraven */ 342245803Stheraven uint32_t size; 343245803Stheraven public: 344245803Stheraven /** 345245803Stheraven * Default constructor, creates an empty strings table. 346245803Stheraven */ 347245803Stheraven string_table() : size(0) {} 348245803Stheraven /** 349245803Stheraven * Adds a string to the table, returning the offset from the start 350245803Stheraven * where it will be written. If the string is already present, this 351245803Stheraven * will return its existing offset, otherwise it will return a new 352245803Stheraven * offset. 353245803Stheraven */ 354245803Stheraven uint32_t add_string(string str); 355245803Stheraven /** 356245803Stheraven * Writes the strings table to the specified output. 357245803Stheraven */ 358245803Stheraven void write(dtb::output_writer &writer); 359245803Stheraven}; 360245803Stheraven 361245803Stheraven} // namespace dtb 362245803Stheraven 363245803Stheraven} // namespace dtc 364245803Stheraven 365245803Stheraven#endif // !_DTB_HH_ 366