xref: /freebsd/usr.bin/dtc/dtb.hh (revision 1fdeb1651cdf0032c6cf77ee8bd3fe889ca3d074)
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 name) {}
190 	/**
191 	 * Comments are ignored by the binary writer.
192 	 */
193 	virtual void write_comment(string name) {}
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 ouput 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