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 #ifndef _DTB_HH_ 34 #define _DTB_HH_ 35 #include <map> 36 #include "string.hh" 37 38 #include <assert.h> 39 40 namespace dtc 41 { 42 /** 43 * The dtb namespace contains code related to the generation of device tree 44 * blobs, the binary representation of flattened device trees. The abstract 45 * tree representation calls into this code to generate the output. 46 */ 47 namespace dtb 48 { 49 /** The token types in the DTB, as defined by §7.4.1 of the ePAPR 50 * specification. All of these values are written in big-endian format in the 51 * output. 52 */ 53 enum token_type 54 { 55 /** 56 * Marker indicating the start of a node in the tree. This is followed 57 * by the nul-terminated name. If a unit address is specified, then 58 * the name also contains the address, with an @ symbol between the end 59 * of the name and the start of the address. 60 * 61 * The name is then padded such that the next token begins on a 4-byte 62 * boundary. The node may contain properties, other nodes, both, or be 63 * empty. 64 */ 65 FDT_BEGIN_NODE = 0x00000001, 66 /** 67 * Marker indicating the end of a node. 68 */ 69 FDT_END_NODE = 0x00000002, 70 /** 71 * The start of a property. This is followed by two 32-bit big-endian 72 * values. The first indicates the length of the property value, the 73 * second its index in the strings table. It is then followed by the 74 * property value, if the value is of non-zero length. 75 */ 76 FDT_PROP = 0x00000003, 77 /** 78 * Ignored token. May be used for padding inside DTB nodes. 79 */ 80 FDT_NOP = 0x00000004, 81 /** 82 * Marker indicating the end of the tree. 83 */ 84 FDT_END = 0x00000009 85 }; 86 87 /** 88 * Returns the token as a string. This is used for debugging and for printing 89 * human-friendly error messages about malformed DTB input. 90 */ 91 inline const char *token_type_name(token_type t) 92 { 93 switch(t) 94 { 95 case FDT_BEGIN_NODE: 96 return "FDT_BEGIN_NODE"; 97 case FDT_END_NODE: 98 return "FDT_END_NODE"; 99 case FDT_PROP: 100 return "FDT_PROP"; 101 case FDT_NOP: 102 return "FDT_NOP"; 103 case FDT_END: 104 return "FDT_END"; 105 } 106 assert(0); 107 } 108 109 /** 110 * Abstract class for writing a section of the output. We create one 111 * of these for each section that needs to be written. It is intended to build 112 * a temporary buffer of the output in memory and then write it to a file 113 * stream. The size can be returned after all of the data has been written 114 * into the internal buffer, so the sizes of the three tables can be calculated 115 * before storing them in the buffer. 116 */ 117 struct output_writer 118 { 119 /** 120 * Writes a label into the output stream. This is only applicable for 121 * assembly output, where the labels become symbols that can be 122 * resolved at link time. 123 */ 124 virtual void write_label(string name) = 0; 125 /** 126 * Writes a comment into the output stream. Useful only when debugging 127 * the output. 128 */ 129 virtual void write_comment(string name) = 0; 130 /** 131 * Writes a string. A nul terminator is implicitly added. 132 */ 133 virtual void write_string(string name) = 0; 134 /** 135 * Writes a single 8-bit value. 136 */ 137 virtual void write_data(uint8_t) = 0; 138 /** 139 * Writes a single 32-bit value. The value is written in big-endian 140 * format, but should be passed in the host's native endian. 141 */ 142 virtual void write_data(uint32_t) = 0; 143 /** 144 * Writes a single 64-bit value. The value is written in big-endian 145 * format, but should be passed in the host's native endian. 146 */ 147 virtual void write_data(uint64_t) = 0; 148 /** 149 * Writes the collected output to the specified file descriptor. 150 */ 151 virtual void write_to_file(int fd) = 0; 152 /** 153 * Returns the number of bytes. 154 */ 155 virtual uint32_t size() = 0; 156 /** 157 * Helper for writing tokens to the output stream. This writes a 158 * comment above the token describing its value, for easier debugging 159 * of the output. 160 */ 161 inline void write_token(token_type t) 162 { 163 write_comment(token_type_name(t)); 164 write_data((uint32_t)t); 165 } 166 /** 167 * Helper function that writes a byte buffer to the output, one byte at 168 * a time. 169 */ 170 void write_data(byte_buffer b); 171 }; 172 173 /** 174 * Binary file writer. This class is responsible for writing the DTB output 175 * directly in blob format. 176 */ 177 class binary_writer : public output_writer 178 { 179 /** 180 * The internal buffer used to store the blob while it is being 181 * constructed. 182 */ 183 byte_buffer buffer; 184 public: 185 /** 186 * The binary format does not support labels, so this method 187 * does nothing. 188 */ 189 virtual void write_label(string) {} 190 /** 191 * Comments are ignored by the binary writer. 192 */ 193 virtual void write_comment(string) {} 194 virtual void write_string(string name); 195 virtual void write_data(uint8_t v); 196 virtual void write_data(uint32_t v); 197 virtual void write_data(uint64_t v); 198 virtual void write_to_file(int fd); 199 virtual uint32_t size(); 200 }; 201 /** 202 * Assembly writer. This class is responsible for writing the output in an 203 * assembly format that is suitable for linking into a kernel, loader, and so 204 * on. 205 */ 206 class asm_writer : public output_writer 207 { 208 /** 209 * The internal buffer for temporary values. Note that this actually 210 * contains ASCII text, but it is a byte buffer so that we can just 211 * copy strings across as-is. 212 */ 213 byte_buffer buffer; 214 /** 215 * The number of bytes written to the current line. This is used to 216 * allow line wrapping, where we aim to write four .byte directives to 217 * make the alignment clearer. 218 */ 219 int byte_count; 220 /** 221 * The current number of bytes written. This is the number in binary 222 * format, not the number of bytes in the buffer. 223 */ 224 uint32_t bytes_written; 225 226 /** 227 * Writes a C string directly to the output as-is. This is mainly used 228 * for writing directives. 229 */ 230 void write_string(const char *c); 231 /** 232 * Writes the string, starting on a new line. 233 */ 234 void write_line(const char *c); 235 /** 236 * Writes a byte in binary format. This will emit a single .byte 237 * directive, with up to four per line. 238 */ 239 void write_byte(uint8_t b); 240 public: 241 asm_writer() : byte_count(0), bytes_written(0) {} 242 virtual void write_label(string name); 243 virtual void write_comment(string name); 244 virtual void write_string(string name); 245 virtual void write_data(uint8_t v); 246 virtual void write_data(uint32_t v); 247 virtual void write_data(uint64_t v); 248 virtual void write_to_file(int fd); 249 virtual uint32_t size(); 250 }; 251 252 /** 253 * Class encapsulating the device tree blob header. This class stores all of 254 * the values found in the header and is responsible for writing them to the 255 * output. 256 */ 257 struct header 258 { 259 /** 260 * Magic value, used to validate that this really is a device tree 261 * blob. Should always be set to 0xd00dfeed. 262 */ 263 uint32_t magic; 264 /** 265 * The total size of the blob, including header, reservations, strings 266 * table, and padding. 267 */ 268 uint32_t totalsize; 269 /** 270 * The offset from the start of the blob of the struct table (i.e. the 271 * part of the blob containing the entire device tree). 272 */ 273 uint32_t off_dt_struct; 274 /** 275 * The offset from the start of the blob of the strings table. 276 */ 277 uint32_t off_dt_strings; 278 /** 279 * The offset of the reservation map from the start of the blob. 280 */ 281 uint32_t off_mem_rsvmap; 282 /** 283 * The version of the blob. This should always be 17. 284 */ 285 uint32_t version; 286 /** 287 * The earliest version of the DTB specification with which this blob 288 * is backwards compatible. This should always be 16. 289 */ 290 uint32_t last_comp_version; 291 /** 292 * The ID of the CPU where this boots. 293 */ 294 uint32_t boot_cpuid_phys; 295 /** 296 * The size of the strings table. 297 */ 298 uint32_t size_dt_strings; 299 /** 300 * The size of the struct table. 301 */ 302 uint32_t size_dt_struct; 303 /** 304 * Writes the entire header to the specified output buffer. 305 */ 306 void write(output_writer &out); 307 /** 308 * Reads the header from bits binary representation in a blob. 309 */ 310 bool read_dtb(input_buffer &input); 311 /** 312 * Default constructor. Initialises the values that have sensible 313 * defaults, leaves the others blank. 314 */ 315 header() : magic(0xd00dfeed), version(17), last_comp_version(16), 316 boot_cpuid_phys(0) {} 317 }; 318 319 /** 320 * Class encapsulating the string table. FDT strings are stored in a string 321 * section. This maintains a map from strings to their offsets in the strings 322 * section. 323 * 324 * Note: We don't currently do suffix matching, which may save a small amount 325 * of space. 326 */ 327 class string_table { 328 /** 329 * Map from strings to their offset. 330 */ 331 std::map<string, uint32_t> string_offsets; 332 /** 333 * The strings, in the order in which they should be written to the 334 * output. The order must be stable - adding another string must not 335 * change the offset of any that we have already referenced - and so we 336 * simply write the strings in the order that they are passed. 337 */ 338 std::vector<string> strings; 339 /** 340 * The current size of the strings section. 341 */ 342 uint32_t size; 343 public: 344 /** 345 * Default constructor, creates an empty strings table. 346 */ 347 string_table() : size(0) {} 348 /** 349 * Adds a string to the table, returning the offset from the start 350 * where it will be written. If the string is already present, this 351 * will return its existing offset, otherwise it will return a new 352 * offset. 353 */ 354 uint32_t add_string(string str); 355 /** 356 * Writes the strings table to the specified output. 357 */ 358 void write(dtb::output_writer &writer); 359 }; 360 361 } // namespace dtb 362 363 } // namespace dtc 364 365 #endif // !_DTB_HH_ 366