]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/dtb.hh
Import tzdata 2017c
[FreeBSD/FreeBSD.git] / usr.bin / dtc / dtb.hh
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>
37
38 #include <assert.h>
39
40 #include "input_buffer.hh"
41 #include "util.hh"
42
43 namespace dtc
44 {
45 /**
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.
49  */
50 namespace dtb
51 {
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
54  * output.
55  */
56 enum token_type
57 {
58         /**
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.
63          *
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
66          * empty.
67          */
68         FDT_BEGIN_NODE = 0x00000001,
69         /**
70          * Marker indicating the end of a node.  
71          */
72         FDT_END_NODE   = 0x00000002,
73         /**
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.
78          */
79         FDT_PROP       = 0x00000003,
80         /**
81          * Ignored token.  May be used for padding inside DTB nodes.
82          */
83         FDT_NOP        = 0x00000004,
84         /**
85          * Marker indicating the end of the tree.
86          */
87         FDT_END        = 0x00000009
88 };
89
90 /**
91  * Returns the token as a string.  This is used for debugging and for printing
92  * human-friendly error messages about malformed DTB input.
93  */
94 inline const char *token_type_name(token_type t)
95 {
96         switch(t)
97         {
98                 case FDT_BEGIN_NODE:
99                         return "FDT_BEGIN_NODE";
100                 case FDT_END_NODE:
101                         return "FDT_END_NODE";
102                 case FDT_PROP:
103                         return "FDT_PROP";
104                 case FDT_NOP:
105                         return "FDT_NOP";
106                 case FDT_END:
107                         return "FDT_END";
108         }
109         assert(0);
110 }
111
112 /**
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.
119  */
120 struct output_writer
121 {
122         /**
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.
126          */
127         virtual void write_label(const std::string &name)   = 0;
128         /**
129          * Writes a comment into the output stream.  Useful only when debugging
130          * the output.
131          */
132         virtual void write_comment(const std::string &name) = 0;
133         /**
134          * Writes a string.  A nul terminator is implicitly added.
135          */
136         virtual void write_string(const std::string &name)  = 0;
137         /**
138          * Writes a single 8-bit value.
139          */
140         virtual void write_data(uint8_t)        = 0;
141         /**
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.
144          */
145         virtual void write_data(uint32_t)       = 0;
146         /**
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.
149          */
150         virtual void write_data(uint64_t)       = 0;
151         /**
152          * Writes the collected output to the specified file descriptor.
153          */
154         virtual void write_to_file(int fd)      = 0;
155         /**
156          * Returns the number of bytes.
157          */
158         virtual uint32_t size()                 = 0;
159         /**
160          * Helper for writing tokens to the output stream.  This writes a
161          * comment above the token describing its value, for easier debugging
162          * of the output.
163          */
164         inline void write_token(token_type t)
165         {
166                 write_comment(token_type_name(t));
167                 write_data((uint32_t)t);
168         }
169         /**
170          * Helper function that writes a byte buffer to the output, one byte at
171          * a time.
172          */
173         void write_data(byte_buffer b);
174 };
175
176 /**
177  * Binary file writer.  This class is responsible for writing the DTB output
178  * directly in blob format.
179  */
180 class binary_writer : public output_writer
181 {
182         /**
183          * The internal buffer used to store the blob while it is being
184          * constructed.
185          */
186         byte_buffer buffer;
187         public:
188         /**
189          *  The binary format does not support labels, so this method
190          * does nothing.
191          */
192         void write_label(const std::string &) override {}
193         /**
194          * Comments are ignored by the binary writer.
195          */
196         void write_comment(const std::string&)  override {}
197         void write_string(const std::string &name) override;
198         void write_data(uint8_t v) override;
199         void write_data(uint32_t v) override;
200         void write_data(uint64_t v) override;
201         void write_to_file(int fd) override;
202         uint32_t size() override;
203 };
204 /**
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
207  * on.
208  */
209 class asm_writer : public output_writer
210 {
211         /**
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.
215          */
216         byte_buffer buffer;
217         /**
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.
221          */
222         int byte_count;
223         /**
224          * The current number of bytes written.  This is the number in binary
225          * format, not the number of bytes in the buffer.
226          */
227         uint32_t bytes_written;
228
229         /**
230          * Writes a string directly to the output as-is.  This is the function that
231          * performs the real output.
232          */
233         void write_string(const char *c);
234         /**
235          * Write a string to the output.
236          */
237         void write_string(const std::string &c) override;
238         /**
239          * Writes the string, starting on a new line.  
240          */
241         void write_line(const char *c);
242         /**
243          * Writes a byte in binary format.  This will emit a single .byte
244          * directive, with up to four per line.
245          */
246         void write_byte(uint8_t b);
247         public:
248         asm_writer() : byte_count(0), bytes_written(0) {}
249         void write_label(const std::string &name) override;
250         void write_comment(const std::string &name) override;
251         void write_data(uint8_t v) override;
252         void write_data(uint32_t v) override;
253         void write_data(uint64_t v) override;
254         void write_to_file(int fd) override;
255         uint32_t size() override;
256 };
257
258 /**
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
261  * output.
262  */
263 struct header
264 {
265         /**
266          * Magic value, used to validate that this really is a device tree
267          * blob.  Should always be set to 0xd00dfeed.
268          */
269         uint32_t magic;
270         /**
271          * The total size of the blob, including header, reservations, strings
272          * table, and padding.
273          */
274         uint32_t totalsize;
275         /**
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).
278          */
279         uint32_t off_dt_struct;
280         /**
281          * The offset from the start of the blob of the strings table.  
282          */
283         uint32_t off_dt_strings;
284         /**
285          * The offset of the reservation map from the start of the blob.
286          */
287         uint32_t off_mem_rsvmap;
288         /**
289          * The version of the blob.  This should always be 17.
290          */
291         uint32_t version;
292         /**
293          * The earliest version of the DTB specification with which this blob
294          * is backwards compatible.  This should always be 16.
295          */
296         uint32_t last_comp_version;
297         /**
298          * The ID of the CPU where this boots.
299          */
300         uint32_t boot_cpuid_phys;
301         /**
302          * The size of the strings table.
303          */
304         uint32_t size_dt_strings;
305         /**
306          * The size of the struct table.
307          */
308         uint32_t size_dt_struct;
309         /**
310          * Writes the entire header to the specified output buffer.  
311          */
312         void write(output_writer &out);
313         /**
314          * Reads the header from bits binary representation in a blob.
315          */
316         bool read_dtb(input_buffer &input);
317         /**
318          * Default constructor.  Initialises the values that have sensible
319          * defaults, leaves the others blank.
320          */
321         header() : magic(0xd00dfeed), version(17), last_comp_version(16),
322                 boot_cpuid_phys(0) {}
323 };
324
325 /**
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
328  * section.
329  *
330  * Note: We don't currently do suffix matching, which may save a small amount
331  * of space.
332  */
333 class string_table {
334         /**
335          * Map from strings to their offset. 
336          */
337         std::map<std::string, uint32_t> string_offsets;
338         /**
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.
343          */
344         std::vector<std::string> strings;
345         /**
346          * The current size of the strings section.
347          */
348         uint32_t size;
349         public:
350         /**
351          * Default constructor, creates an empty strings table.
352          */
353         string_table() : size(0) {}
354         /**
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
358          * offset.
359          */
360         uint32_t add_string(const std::string &str);
361         /**
362          * Writes the strings table to the specified output.
363          */
364         void write(dtb::output_writer &writer);
365 };
366
367 } // namespace dtb
368
369 } // namespace dtc
370
371 #endif // !_DTB_HH_