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