2 * Copyright (c) 2013 David Chisnall
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.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
40 #include "input_buffer.hh"
46 * The dtb namespace contains code related to the generation of device tree
47 * blobs, the binary representation of flattened device trees. The abstract
48 * tree representation calls into this code to generate the output.
52 /** The token types in the DTB, as defined by ยง7.4.1 of the ePAPR
53 * specification. All of these values are written in big-endian format in the
59 * Marker indicating the start of a node in the tree. This is followed
60 * by the nul-terminated name. If a unit address is specified, then
61 * the name also contains the address, with an @ symbol between the end
62 * of the name and the start of the address.
64 * The name is then padded such that the next token begins on a 4-byte
65 * boundary. The node may contain properties, other nodes, both, or be
68 FDT_BEGIN_NODE = 0x00000001,
70 * Marker indicating the end of a node.
72 FDT_END_NODE = 0x00000002,
74 * The start of a property. This is followed by two 32-bit big-endian
75 * values. The first indicates the length of the property value, the
76 * second its index in the strings table. It is then followed by the
77 * property value, if the value is of non-zero length.
79 FDT_PROP = 0x00000003,
81 * Ignored token. May be used for padding inside DTB nodes.
85 * Marker indicating the end of the tree.
91 * Returns the token as a string. This is used for debugging and for printing
92 * human-friendly error messages about malformed DTB input.
94 inline const char *token_type_name(token_type t)
99 return "FDT_BEGIN_NODE";
101 return "FDT_END_NODE";
113 * Abstract class for writing a section of the output. We create one
114 * of these for each section that needs to be written. It is intended to build
115 * a temporary buffer of the output in memory and then write it to a file
116 * stream. The size can be returned after all of the data has been written
117 * into the internal buffer, so the sizes of the three tables can be calculated
118 * before storing them in the buffer.
123 * Writes a label into the output stream. This is only applicable for
124 * assembly output, where the labels become symbols that can be
125 * resolved at link time.
127 virtual void write_label(const std::string &name) = 0;
129 * Writes a comment into the output stream. Useful only when debugging
132 virtual void write_comment(const std::string &name) = 0;
134 * Writes a string. A nul terminator is implicitly added.
136 virtual void write_string(const std::string &name) = 0;
138 * Writes a single 8-bit value.
140 virtual void write_data(uint8_t) = 0;
142 * Writes a single 32-bit value. The value is written in big-endian
143 * format, but should be passed in the host's native endian.
145 virtual void write_data(uint32_t) = 0;
147 * Writes a single 64-bit value. The value is written in big-endian
148 * format, but should be passed in the host's native endian.
150 virtual void write_data(uint64_t) = 0;
152 * Writes the collected output to the specified file descriptor.
154 virtual void write_to_file(int fd) = 0;
156 * Returns the number of bytes.
158 virtual uint32_t size() = 0;
160 * Helper for writing tokens to the output stream. This writes a
161 * comment above the token describing its value, for easier debugging
164 inline void write_token(token_type t)
166 write_comment(token_type_name(t));
167 write_data((uint32_t)t);
170 * Helper function that writes a byte buffer to the output, one byte at
173 void write_data(byte_buffer b);
177 * Binary file writer. This class is responsible for writing the DTB output
178 * directly in blob format.
180 class binary_writer : public output_writer
183 * The internal buffer used to store the blob while it is being
189 * The binary format does not support labels, so this method
192 virtual void write_label(const std::string &) {}
194 * Comments are ignored by the binary writer.
196 virtual void write_comment(const std::string&) {}
197 virtual void write_string(const std::string &name);
198 virtual void write_data(uint8_t v);
199 virtual void write_data(uint32_t v);
200 virtual void write_data(uint64_t v);
201 virtual void write_to_file(int fd);
202 virtual uint32_t size();
205 * Assembly writer. This class is responsible for writing the output in an
206 * assembly format that is suitable for linking into a kernel, loader, and so
209 class asm_writer : public output_writer
212 * The internal buffer for temporary values. Note that this actually
213 * contains ASCII text, but it is a byte buffer so that we can just
214 * copy strings across as-is.
218 * The number of bytes written to the current line. This is used to
219 * allow line wrapping, where we aim to write four .byte directives to
220 * make the alignment clearer.
224 * The current number of bytes written. This is the number in binary
225 * format, not the number of bytes in the buffer.
227 uint32_t bytes_written;
230 * Writes a string directly to the output as-is. This is the function that
231 * performs the real output.
233 void write_string(const char *c);
235 * Write a string to the output.
237 void write_string(const std::string &c);
239 * Writes the string, starting on a new line.
241 void write_line(const char *c);
243 * Writes a byte in binary format. This will emit a single .byte
244 * directive, with up to four per line.
246 void write_byte(uint8_t b);
248 asm_writer() : byte_count(0), bytes_written(0) {}
249 virtual void write_label(const std::string &name);
250 virtual void write_comment(const std::string &name);
251 virtual void write_data(uint8_t v);
252 virtual void write_data(uint32_t v);
253 virtual void write_data(uint64_t v);
254 virtual void write_to_file(int fd);
255 virtual uint32_t size();
259 * Class encapsulating the device tree blob header. This class stores all of
260 * the values found in the header and is responsible for writing them to the
266 * Magic value, used to validate that this really is a device tree
267 * blob. Should always be set to 0xd00dfeed.
271 * The total size of the blob, including header, reservations, strings
272 * table, and padding.
276 * The offset from the start of the blob of the struct table (i.e. the
277 * part of the blob containing the entire device tree).
279 uint32_t off_dt_struct;
281 * The offset from the start of the blob of the strings table.
283 uint32_t off_dt_strings;
285 * The offset of the reservation map from the start of the blob.
287 uint32_t off_mem_rsvmap;
289 * The version of the blob. This should always be 17.
293 * The earliest version of the DTB specification with which this blob
294 * is backwards compatible. This should always be 16.
296 uint32_t last_comp_version;
298 * The ID of the CPU where this boots.
300 uint32_t boot_cpuid_phys;
302 * The size of the strings table.
304 uint32_t size_dt_strings;
306 * The size of the struct table.
308 uint32_t size_dt_struct;
310 * Writes the entire header to the specified output buffer.
312 void write(output_writer &out);
314 * Reads the header from bits binary representation in a blob.
316 bool read_dtb(input_buffer &input);
318 * Default constructor. Initialises the values that have sensible
319 * defaults, leaves the others blank.
321 header() : magic(0xd00dfeed), version(17), last_comp_version(16),
322 boot_cpuid_phys(0) {}
326 * Class encapsulating the string table. FDT strings are stored in a string
327 * section. This maintains a map from strings to their offsets in the strings
330 * Note: We don't currently do suffix matching, which may save a small amount
335 * Map from strings to their offset.
337 std::map<std::string, uint32_t> string_offsets;
339 * The strings, in the order in which they should be written to the
340 * output. The order must be stable - adding another string must not
341 * change the offset of any that we have already referenced - and so we
342 * simply write the strings in the order that they are passed.
344 std::vector<std::string> strings;
346 * The current size of the strings section.
351 * Default constructor, creates an empty strings table.
353 string_table() : size(0) {}
355 * Adds a string to the table, returning the offset from the start
356 * where it will be written. If the string is already present, this
357 * will return its existing offset, otherwise it will return a new
360 uint32_t add_string(const std::string &str);
362 * Writes the strings table to the specified output.
364 void write(dtb::output_writer &writer);