Add new USB ID to U3G driver.
[freebsd.git] / usr.bin / dtc / dtb.hh
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2013 David Chisnall
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD$
33  */
34
35 #ifndef _DTB_HH_
36 #define _DTB_HH_
37 #include <map>
38 #include <string>
39
40 #include <assert.h>
41
42 #include "input_buffer.hh"
43 #include "util.hh"
44
45 namespace dtc
46 {
47 /**
48  * The dtb namespace contains code related to the generation of device tree
49  * blobs, the binary representation of flattened device trees.  The abstract
50  * tree representation calls into this code to generate the output.
51  */
52 namespace dtb
53 {
54 /** The token types in the DTB, as defined by ยง7.4.1 of the ePAPR
55  * specification.  All of these values are written in big-endian format in the
56  * output.
57  */
58 enum token_type
59 {
60         /**
61          * Marker indicating the start of a node in the tree.  This is followed
62          * by the nul-terminated name.  If a unit address is specified, then
63          * the name also contains the address, with an @ symbol between the end
64          * of the name and the start of the address.
65          *
66          * The name is then padded such that the next token begins on a 4-byte
67          * boundary.  The node may contain properties, other nodes, both, or be
68          * empty.
69          */
70         FDT_BEGIN_NODE = 0x00000001,
71         /**
72          * Marker indicating the end of a node.  
73          */
74         FDT_END_NODE   = 0x00000002,
75         /**
76          * The start of a property.  This is followed by two 32-bit big-endian
77          * values.  The first indicates the length of the property value, the
78          * second its index in the strings table.  It is then followed by the
79          * property value, if the value is of non-zero length.
80          */
81         FDT_PROP       = 0x00000003,
82         /**
83          * Ignored token.  May be used for padding inside DTB nodes.
84          */
85         FDT_NOP        = 0x00000004,
86         /**
87          * Marker indicating the end of the tree.
88          */
89         FDT_END        = 0x00000009
90 };
91
92 /**
93  * Returns the token as a string.  This is used for debugging and for printing
94  * human-friendly error messages about malformed DTB input.
95  */
96 inline const char *token_type_name(token_type t)
97 {
98         switch(t)
99         {
100                 case FDT_BEGIN_NODE:
101                         return "FDT_BEGIN_NODE";
102                 case FDT_END_NODE:
103                         return "FDT_END_NODE";
104                 case FDT_PROP:
105                         return "FDT_PROP";
106                 case FDT_NOP:
107                         return "FDT_NOP";
108                 case FDT_END:
109                         return "FDT_END";
110         }
111         assert(0);
112 }
113
114 /**
115  * Abstract class for writing a section of the output.  We create one
116  * of these for each section that needs to be written.  It is intended to build
117  * a temporary buffer of the output in memory and then write it to a file
118  * stream.  The size can be returned after all of the data has been written
119  * into the internal buffer, so the sizes of the three tables can be calculated
120  * before storing them in the buffer.
121  */
122 struct output_writer
123 {
124         /**
125          * Writes a label into the output stream.  This is only applicable for
126          * assembly output, where the labels become symbols that can be
127          * resolved at link time.
128          */
129         virtual void write_label(const std::string &name)   = 0;
130         /**
131          * Writes a comment into the output stream.  Useful only when debugging
132          * the output.
133          */
134         virtual void write_comment(const std::string &name) = 0;
135         /**
136          * Writes a string.  A nul terminator is implicitly added.
137          */
138         virtual void write_string(const std::string &name)  = 0;
139         /**
140          * Writes a single 8-bit value.
141          */
142         virtual void write_data(uint8_t)        = 0;
143         /**
144          * Writes a single 32-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(uint32_t)       = 0;
148         /**
149          * Writes a single 64-bit value.  The value is written in big-endian
150          * format, but should be passed in the host's native endian.
151          */
152         virtual void write_data(uint64_t)       = 0;
153         /**
154          * Writes the collected output to the specified file descriptor.
155          */
156         virtual void write_to_file(int fd)      = 0;
157         /**
158          * Returns the number of bytes.
159          */
160         virtual uint32_t size()                 = 0;
161         /**
162          * Helper for writing tokens to the output stream.  This writes a
163          * comment above the token describing its value, for easier debugging
164          * of the output.
165          */
166         inline void write_token(token_type t)
167         {
168                 write_comment(token_type_name(t));
169                 write_data((uint32_t)t);
170         }
171         /**
172          * Helper function that writes a byte buffer to the output, one byte at
173          * a time.
174          */
175         void write_data(byte_buffer b);
176 };
177
178 /**
179  * Binary file writer.  This class is responsible for writing the DTB output
180  * directly in blob format.
181  */
182 class binary_writer : public output_writer
183 {
184         /**
185          * The internal buffer used to store the blob while it is being
186          * constructed.
187          */
188         byte_buffer buffer;
189         public:
190         /**
191          *  The binary format does not support labels, so this method
192          * does nothing.
193          */
194         void write_label(const std::string &) override {}
195         /**
196          * Comments are ignored by the binary writer.
197          */
198         void write_comment(const std::string&)  override {}
199         void write_string(const std::string &name) override;
200         void write_data(uint8_t v) override;
201         void write_data(uint32_t v) override;
202         void write_data(uint64_t v) override;
203         void write_to_file(int fd) override;
204         uint32_t size() override;
205 };
206 /**
207  * Assembly writer.  This class is responsible for writing the output in an
208  * assembly format that is suitable for linking into a kernel, loader, and so
209  * on.
210  */
211 class asm_writer : public output_writer
212 {
213         /**
214          * The internal buffer for temporary values.  Note that this actually
215          * contains ASCII text, but it is a byte buffer so that we can just
216          * copy strings across as-is.
217          */
218         byte_buffer buffer;
219         /**
220          * The number of bytes written to the current line.  This is used to
221          * allow line wrapping, where we aim to write four .byte directives to
222          * make the alignment clearer.
223          */
224         int byte_count;
225         /**
226          * The current number of bytes written.  This is the number in binary
227          * format, not the number of bytes in the buffer.
228          */
229         uint32_t bytes_written;
230
231         /**
232          * Writes a string directly to the output as-is.  This is the function that
233          * performs the real output.
234          */
235         void write_string(const char *c);
236         /**
237          * Write a string to the output.
238          */
239         void write_string(const std::string &c) override;
240         /**
241          * Writes the string, starting on a new line.  
242          */
243         void write_line(const char *c);
244         /**
245          * Writes a byte in binary format.  This will emit a single .byte
246          * directive, with up to four per line.
247          */
248         void write_byte(uint8_t b);
249         public:
250         asm_writer() : byte_count(0), bytes_written(0) {}
251         void write_label(const std::string &name) override;
252         void write_comment(const std::string &name) override;
253         void write_data(uint8_t v) override;
254         void write_data(uint32_t v) override;
255         void write_data(uint64_t v) override;
256         void write_to_file(int fd) override;
257         uint32_t size() override;
258 };
259
260 /**
261  * Class encapsulating the device tree blob header.  This class stores all of
262  * the values found in the header and is responsible for writing them to the
263  * output.
264  */
265 struct header
266 {
267         /**
268          * Magic value, used to validate that this really is a device tree
269          * blob.  Should always be set to 0xd00dfeed.
270          */
271         uint32_t magic;
272         /**
273          * The total size of the blob, including header, reservations, strings
274          * table, and padding.
275          */
276         uint32_t totalsize;
277         /**
278          * The offset from the start of the blob of the struct table (i.e. the
279          * part of the blob containing the entire device tree).
280          */
281         uint32_t off_dt_struct;
282         /**
283          * The offset from the start of the blob of the strings table.  
284          */
285         uint32_t off_dt_strings;
286         /**
287          * The offset of the reservation map from the start of the blob.
288          */
289         uint32_t off_mem_rsvmap;
290         /**
291          * The version of the blob.  This should always be 17.
292          */
293         uint32_t version;
294         /**
295          * The earliest version of the DTB specification with which this blob
296          * is backwards compatible.  This should always be 16.
297          */
298         uint32_t last_comp_version;
299         /**
300          * The ID of the CPU where this boots.
301          */
302         uint32_t boot_cpuid_phys;
303         /**
304          * The size of the strings table.
305          */
306         uint32_t size_dt_strings;
307         /**
308          * The size of the struct table.
309          */
310         uint32_t size_dt_struct;
311         /**
312          * Writes the entire header to the specified output buffer.  
313          */
314         void write(output_writer &out);
315         /**
316          * Reads the header from bits binary representation in a blob.
317          */
318         bool read_dtb(input_buffer &input);
319         /**
320          * Default constructor.  Initialises the values that have sensible
321          * defaults, leaves the others blank.
322          */
323         header() : magic(0xd00dfeed), version(17), last_comp_version(16),
324                 boot_cpuid_phys(0) {}
325 };
326
327 /**
328  * Class encapsulating the string table.  FDT strings are stored in a string
329  * section.  This maintains a map from strings to their offsets in the strings
330  * section.
331  *
332  * Note: We don't currently do suffix matching, which may save a small amount
333  * of space.
334  */
335 class string_table {
336         /**
337          * Map from strings to their offset. 
338          */
339         std::map<std::string, uint32_t> string_offsets;
340         /**
341          * The strings, in the order in which they should be written to the
342          * output.  The order must be stable - adding another string must not
343          * change the offset of any that we have already referenced - and so we
344          * simply write the strings in the order that they are passed.
345          */
346         std::vector<std::string> strings;
347         /**
348          * The current size of the strings section.
349          */
350         uint32_t size;
351         public:
352         /**
353          * Default constructor, creates an empty strings table.
354          */
355         string_table() : size(0) {}
356         /**
357          * Adds a string to the table, returning the offset from the start
358          * where it will be written.  If the string is already present, this
359          * will return its existing offset, otherwise it will return a new
360          * offset.
361          */
362         uint32_t add_string(const std::string &str);
363         /**
364          * Writes the strings table to the specified output.
365          */
366         void write(dtb::output_writer &writer);
367 };
368
369 } // namespace dtb
370
371 } // namespace dtc
372
373 #endif // !_DTB_HH_