dtb.hh revision 293290
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: stable/10/usr.bin/dtc/dtb.hh 293290 2016-01-07 00:40:51Z bdrewery $
31 */
32
33#ifndef _DTB_HH_
34#define _DTB_HH_
35#include <map>
36#include "string.hh"
37
38#include <assert.h>
39
40namespace 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 */
47namespace 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 */
53enum 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 */
91inline 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 */
117struct 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 */
177class 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 */
206class 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 */
257struct 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 */
327class 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