I'm finding it rather annoying that dtc isn't installed on systems that use device trees.
Would there be any negative fallout from installing /usr/bin/dtc as part of the regular world? Tim P.S. In particular, I'm moving away from compiled-in device trees (in favor of having the loader read it from a separate file) in part so that the device tree file can be adjusted without having to recompile the kernel. On Jan 22, 2013, at 9:49 AM, David Chisnall wrote: > Author: theraven > Date: Tue Jan 22 17:49:51 2013 > New Revision: 245803 > URL: http://svnweb.freebsd.org/changeset/base/245803 > > Log: > Import new (BSDL) device tree compiler. Now built by default, so that it > can't > be used on the host system (and not installed on the device, if required). > The > GPL'd one is still available if there are any devices that need it (make > universe passes with it, including kernels that use fdt, but there may be > some > out-of-tree ones). WITH_GPL_DTC can be used to select the old one, for now. > > Probably won't be MFC'd, but we'll remove the GPL'd version in head after the > new one has had a lot more testing and ship it in 10.0. > > Added: > head/usr.bin/dtc/ > head/usr.bin/dtc/HACKING (contents, props changed) > head/usr.bin/dtc/Makefile (contents, props changed) > head/usr.bin/dtc/checking.cc (contents, props changed) > head/usr.bin/dtc/checking.hh (contents, props changed) > head/usr.bin/dtc/dtb.cc (contents, props changed) > head/usr.bin/dtc/dtb.hh (contents, props changed) > head/usr.bin/dtc/dtc.1 (contents, props changed) > head/usr.bin/dtc/dtc.cc (contents, props changed) > head/usr.bin/dtc/fdt.cc (contents, props changed) > head/usr.bin/dtc/fdt.hh (contents, props changed) > head/usr.bin/dtc/input_buffer.cc (contents, props changed) > head/usr.bin/dtc/input_buffer.hh (contents, props changed) > head/usr.bin/dtc/string.cc (contents, props changed) > head/usr.bin/dtc/string.hh (contents, props changed) > head/usr.bin/dtc/util.hh (contents, props changed) > Modified: > head/Makefile.inc1 > head/gnu/usr.bin/Makefile > head/share/man/man5/src.conf.5 > head/share/mk/bsd.own.mk > > Modified: head/Makefile.inc1 > ============================================================================== > --- head/Makefile.inc1 Tue Jan 22 17:21:08 2013 (r245802) > +++ head/Makefile.inc1 Tue Jan 22 17:49:51 2013 (r245803) > @@ -1112,7 +1112,10 @@ _dtrace_tools= cddl/usr.bin/sgsmsg cddl/ > lib/libdwarf cddl/usr.bin/ctfconvert cddl/usr.bin/ctfmerge > .endif > > -.if ${MK_FDT} != "no" > +# Default to building the BSDL DTC, but build the GPL one if users explicitly > +# request it. > +_dtc= /usr.bin/dtc > +.if ${MK_GPL_DTC} != "no" > _dtc= gnu/usr.bin/dtc > .endif > > > Modified: head/gnu/usr.bin/Makefile > ============================================================================== > --- head/gnu/usr.bin/Makefile Tue Jan 22 17:21:08 2013 (r245802) > +++ head/gnu/usr.bin/Makefile Tue Jan 22 17:49:51 2013 (r245803) > @@ -30,7 +30,7 @@ _groff= groff > _cvs= cvs > .endif > > -.if ${MK_FDT} != "no" > +.if ${MK_GPL_DTC} != "no" > _dtc= dtc > .endif > > > Modified: head/share/man/man5/src.conf.5 > ============================================================================== > --- head/share/man/man5/src.conf.5 Tue Jan 22 17:21:08 2013 > (r245802) > +++ head/share/man/man5/src.conf.5 Tue Jan 22 17:49:51 2013 > (r245803) > @@ -476,6 +476,9 @@ Set to not build GPIB bus support. > Set to not build > .Xr gpioctl 8 > as part of the base system. > +.It Va WITH_GPL_DTC > +Set to build the GPL'd version of the device tree compiler from elinux.org, > +instead of the BSD licensed one. > .It Va WITHOUT_GROFF > .\" from FreeBSD: head/tools/build/options/WITHOUT_GROFF 218941 2011-02-22 > 08:13:49Z uqs > Set to not build > > Modified: head/share/mk/bsd.own.mk > ============================================================================== > --- head/share/mk/bsd.own.mk Tue Jan 22 17:21:08 2013 (r245802) > +++ head/share/mk/bsd.own.mk Tue Jan 22 17:49:51 2013 (r245803) > @@ -364,6 +364,7 @@ __DEFAULT_NO_OPTIONS = \ > BSD_GREP \ > CLANG_EXTRAS \ > CTF \ > + GPL_DTC \ > HESIOD \ > ICONV \ > IDEA \ > > Added: head/usr.bin/dtc/HACKING > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/usr.bin/dtc/HACKING Tue Jan 22 17:49:51 2013 (r245803) > @@ -0,0 +1,65 @@ > +$FreeBSD$ > + > +Notes for people hacking on dtc > +=============================== > + > +This file contains some notes for people wishing to hack on dtc. > + > +Upstreaming > +----------- > + > +This code is developed in the FreeBSD svn repository: > + > +https://svn.freebsd.org/base/head/usr.bin/dtc > + > +If you got the source from anywhere else and wish to make changes, please > +ensure that you are working against the latest version, or you may end up > +fixing bugs that are already fixed upstream. Although the license makes no > +requirement that you share any improvements that you make, patches are very > +welcome. > + > +C++11 > +----- > + > +This project currently aims to compile with g++ 4.2.1 and so doesn't make any > +use of C++11 features. It would be a good idea to relax this restriction > once > +clang is the default compiler for ARM, MIPS and PowerPC. > + > +This code makes use of a lot of iterator loops, which would be cleaner using > +the new syntax in C++11. It also explicitly deletes a lot of objects held in > +collections in destructors that have these collections as their members. > This > +could be simplified by using `shared_ptr`. > + > +The code does make use of `static_assert()`, but uses a macro in utility.hh > to > +remove these if they are not supported. The FreeBSD standard headers also > +define a compatibility macro the implements static asserts in terms of an > array > +with 1 element on success and -1 elements on failure. > + > +Adding New Checks > +----------------- > + > +Currently, the biggest weakness of this version of the tool is that it lacks > +most of the semantic checkers that can be implemented by simply reading the > +ePAPR spec. The `checker` class provides a simple superclass for > implementing > +these quite easily. There are also helper methods on `device_tree` for > finding > +specific nodes, for checks that require some understanding of the structure > of > +the tree. > + > +We should probably add a parent pointer to the `node` class for easily > walking > +up the tree. > + > +Adding Direct C Output > +---------------------- > + > +The FreeBSD build system currently uses dtc to generate a blob and then > +converts this to C source code. A new `output_writer` subclass could easily > +generate the C directly. > + > +Parser Improvements > +------------------- > + > +There are a few FIXME lines in the parser for some corner cases that are not > +currently used by FreeBSD. These are mainly related to labels in the middle > of > +values. These can be fixed by creating a new `property_value` with the > +specified label, starting at the location of the label. Don't forget to > remove > +the associated comments from the BUGS section of the man page if you fix > this. > > Added: head/usr.bin/dtc/Makefile > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/usr.bin/dtc/Makefile Tue Jan 22 17:49:51 2013 (r245803) > @@ -0,0 +1,11 @@ > +# $FreeBSD$ > + > +PROG_CXX=dtc > +SRCS= dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc > +MAN= dtc.1 > + > +WARNS?= 3 > + > +NO_SHARED?=NO > + > +.include <bsd.prog.mk> > > Added: head/usr.bin/dtc/checking.cc > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/usr.bin/dtc/checking.cc Tue Jan 22 17:49:51 2013 > (r245803) > @@ -0,0 +1,210 @@ > +/*- > + * Copyright (c) 2013 David Chisnall > + * All rights reserved. > + * > + * This software was developed by SRI International and the University of > + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) > + * ("CTSRD"), as part of the DARPA CRASH research programme. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * $FreeBSD$ > + */ > + > +#include "checking.hh" > + > +namespace dtc > +{ > +namespace fdt > +{ > +namespace checking > +{ > + > +bool > +checker::visit_node(device_tree *tree, node *n) > +{ > + path.push_back(std::make_pair(n->name, n->unit_address)); > + // Check this node > + if (!check_node(tree, n)) > + { > + return false; > + } > + // Now check its properties > + for (node::property_iterator i=n->property_begin(), e=n->property_end() > + ; i!=e ; ++i) > + { > + if (!check_property(tree, n, *i)) > + { > + return false; > + } > + } > + // And then recursively check the children > + for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; > + ++i) > + { > + if (!visit_node(tree, *i)) > + { > + return false; > + } > + } > + path.pop_back(); > + return true; > +} > + > +void > +checker::report_error(const char *errmsg) > +{ > + fprintf(stderr, "Error: %s, while checking node: ", errmsg); > + for (device_tree::node_path::iterator p=path.begin()+1, pe=path.end() ; > + p!=pe ; ++p) > + { > + putc('/', stderr); > + p->first.dump(); > + if (!(p->second.empty())) > + { > + putc('@', stderr); > + p->second.dump(); > + } > + } > + fprintf(stderr, " [-W%s]\n", checker_name); > +} > + > +bool > +property_checker::check_property(device_tree *tree, node *n, property *p) > +{ > + if (p->get_key() == key) > + { > + if (!check(tree, n, p)) > + { > + report_error("property check failed"); > + return false; > + } > + } > + return true; > +} > + > +bool > +property_size_checker::check(device_tree *tree, node *n, property *p) > +{ > + uint32_t psize = 0; > + for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; ++i) > + { > + if (!i->is_binary()) > + { > + return false; > + } > + psize += i->byte_data.size(); > + } > + return psize == size; > +} > + > +template<property_value::value_type T> > +void > +check_manager::add_property_type_checker(const char *name, string prop) > +{ > + checkers.insert(std::make_pair(string(name), > + new property_type_checker<T>(name, prop))); > +} > + > +void > +check_manager::add_property_size_checker(const char *name, > + string prop, > + uint32_t size) > +{ > + checkers.insert(std::make_pair(string(name), > + new property_size_checker(name, prop, size))); > +} > + > +check_manager::~check_manager() > +{ > + while (checkers.begin() != checkers.end()) > + { > + delete checkers.begin()->second; > + checkers.erase(checkers.begin()); > + } > + while (disabled_checkers.begin() != disabled_checkers.end()) > + { > + delete disabled_checkers.begin()->second; > + } > +} > + > +check_manager::check_manager() > +{ > + // NOTE: All checks listed here MUST have a corresponding line > + // in the man page! > + add_property_type_checker<property_value::STRING_LIST>( > + "type-compatible", string("compatible")); > + add_property_type_checker<property_value::STRING>( > + "type-model", string("model")); > + add_property_size_checker("type-phandle", string("phandle"), 4); > +} > + > +bool > +check_manager::run_checks(device_tree *tree, bool keep_going) > +{ > + bool success = true; > + for (std::map<string, checker*>::iterator i=checkers.begin(), > + e=checkers.end() ; i!=e ; ++i) > + { > + success &= i->second->check_tree(tree); > + if (!(success || keep_going)) > + { > + break; > + } > + } > + return success; > +} > + > +bool > +check_manager::disable_checker(string name) > +{ > + std::map<string, checker*>::iterator checker = checkers.find(name); > + if (checker != checkers.end()) > + { > + disabled_checkers.insert(std::make_pair(name, > + checker->second)); > + checkers.erase(checker); > + return true; > + } > + return false; > +} > + > +bool > +check_manager::enable_checker(string name) > +{ > + std::map<string, checker*>::iterator checker = > + disabled_checkers.find(name); > + if (checker != disabled_checkers.end()) > + { > + checkers.insert(std::make_pair(name, checker->second)); > + disabled_checkers.erase(checker); > + return true; > + } > + return false; > +} > + > +} // namespace checking > + > +} // namespace fdt > + > +} // namespace dtc > + > > Added: head/usr.bin/dtc/checking.hh > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/usr.bin/dtc/checking.hh Tue Jan 22 17:49:51 2013 > (r245803) > @@ -0,0 +1,308 @@ > +/*- > + * Copyright (c) 2013 David Chisnall > + * All rights reserved. > + * > + * This software was developed by SRI International and the University of > + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) > + * ("CTSRD"), as part of the DARPA CRASH research programme. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * $FreeBSD$ > + */ > + > +#ifndef _CHECKING_HH_ > +#define _CHECKING_HH_ > +#include "string.hh" > +#include "fdt.hh" > + > +namespace dtc > +{ > +namespace fdt > +{ > +namespace checking > +{ > +/** > + * Base class for all checkers. This will visit the entire tree and perform > + * semantic checks defined in subclasses. Note that device trees are > generally > + * small (a few dozen nodes at most) and so we optimise for flexibility and > + * extensibility here, not for performance. Each checker will visit the > entire > + * tree. > + */ > +class checker > +{ > + /** > + * The path to the current node being checked. This is used for > + * printing error messages. > + */ > + device_tree::node_path path; > + /** > + * The name of the checker. This is used for printing error messages > + * and for enabling / disabling specific checkers from the command > + * line. > + */ > + const char *checker_name; > + /** > + * Visits each node, calling the checker functions on properties and > + * nodes. > + */ > + bool visit_node(device_tree *tree, node *n); > + protected: > + /** > + * Prints the error message, along with the path to the node that > + * caused the error and the name of the checker. > + */ > + void report_error(const char *errmsg); > + public: > + /** > + * Constructor. Takes the name of this checker, which is which is used > + * when reporting errors. > + */ > + checker(const char *name) : checker_name(name) {} > + /** > + * Virtual destructor in case any subclasses need to do cleanup. > + */ > + virtual ~checker() {} > + /** > + * Method for checking that a node is valid. The root class version > + * does nothing, subclasses should override this. > + */ > + virtual bool check_node(device_tree *tree, node *n) > + { > + return true; > + } > + /** > + * Method for checking that a property is valid. The root class > + * version does nothing, subclasses should override this. > + */ > + virtual bool check_property(device_tree *tree, node *n, property *p) > + { > + return true; > + } > + /** > + * Runs the checker on the specified device tree. > + */ > + bool check_tree(fdt::device_tree *tree) > + { > + return visit_node(tree, tree->get_root()); > + } > +}; > + > +/** > + * Abstract base class for simple property checks. This class defines a > check > + * method for subclasses, which is invoked only when it finds a property with > + * the matching name. To define simple property checkers, just subclass this > + * and override the check() method. > + */ > +class property_checker : public checker > +{ > + /** > + * The name of the property that this checker is looking for. > + */ > + string key; > + public: > + /** > + * Implementation of the generic property-checking method that checks > + * for a property with the name specified in the constructor > + */ > + virtual bool check_property(device_tree *tree, node *n, property *p); > + /** > + * Constructor. Takes the name of the checker and the name of the > + * property to check. > + */ > + property_checker(const char* name, string property_name) > + : checker(name), key(property_name) {} > + /** > + * The check method, which subclasses should implement. > + */ > + virtual bool check(device_tree *tree, node *n, property *p) = 0; > +}; > + > +/** > + * Property type checker. > + */ > +template<property_value::value_type T> > +struct property_type_checker : public property_checker > +{ > + /** > + * Constructor, takes the name of the checker and the name of the > + * property to check as arguments. > + */ > + property_type_checker(const char* name, string property_name) : > + property_checker(name, property_name) {} > + virtual bool check(device_tree *tree, node *n, property *p) = 0; > +}; > + > +/** > + * Empty property checker. This checks that the property has no value. > + */ > +template<> > +struct property_type_checker <property_value::EMPTY> : public > property_checker > +{ > + property_type_checker(const char* name, string property_name) : > + property_checker(name, property_name) {} > + virtual bool check(device_tree *tree, node *n, property *p) > + { > + return p->begin() == p->end(); > + } > +}; > + > +/** > + * String property checker. This checks that the property has exactly one > + * value, which is a string. > + */ > +template<> > +struct property_type_checker <property_value::STRING> : public > property_checker > +{ > + property_type_checker(const char* name, string property_name) : > + property_checker(name, property_name) {} > + virtual bool check(device_tree *tree, node *n, property *p) > + { > + return (p->begin() + 1 == p->end()) && p->begin()->is_string(); > + } > +}; > +/** > + * String list property checker. This checks that the property has at least > + * one value, all of which are strings. > + */ > +template<> > +struct property_type_checker <property_value::STRING_LIST> : > + public property_checker > +{ > + property_type_checker(const char* name, string property_name) : > + property_checker(name, property_name) {} > + virtual bool check(device_tree *tree, node *n, property *p) > + { > + for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; > + ++i) > + { > + if (!(i->is_string() || i->is_string_list())) > + { > + return false; > + } > + } > + return p->begin() != p->end(); > + } > +}; > + > +/** > + * Phandle property checker. This checks that the property has exactly one > + * value, which is a valid phandle. > + */ > +template<> > +struct property_type_checker <property_value::PHANDLE> : public > property_checker > +{ > + property_type_checker(const char* name, string property_name) : > + property_checker(name, property_name) {} > + virtual bool check(device_tree *tree, node *n, property *p) > + { > + return (p->begin() + 1 == p->end()) && > + (tree->referenced_node(*p->begin()) != 0); > + } > +}; > + > +/** > + * Check that a property has the correct size. > + */ > +struct property_size_checker : public property_checker > +{ > + /** > + * The expected size of the property. > + */ > + uint32_t size; > + public: > + /** > + * Constructor, takes the name of the checker, the name of the property > + * to check, and its expected size as arguments. > + */ > + property_size_checker(const char* name, string property_name, uint32_t > bytes) > + : property_checker(name, property_name), size(bytes) {} > + /** > + * Check, validates that the property has the correct size. > + */ > + virtual bool check(device_tree *tree, node *n, property *p); > +}; > + > + > +/** > + * The check manager is the interface to running the checks. This allows > + * default checks to be enabled, non-default checks to be enabled, and so on. > + */ > +class check_manager > +{ > + /** > + * The enabled checkers, indexed by their names. The name is used when > + * disabling checkers from the command line. When this manager runs, > + * it will only run the checkers from this map. > + */ > + std::map<string, checker*> checkers; > + /** > + * The disabled checkers. Moving checkers to this list disables them, > + * but allows them to be easily moved back. > + */ > + std::map<string, checker*> disabled_checkers; > + /** > + * Helper function for adding a property value checker. > + */ > + template<property_value::value_type T> > + void add_property_type_checker(const char *name, string prop); > + /** > + * Helper function for adding a simple type checker. > + */ > + void add_property_type_checker(const char *name, string prop); > + /** > + * Helper function for adding a property value checker. > + */ > + void add_property_size_checker(const char *name, > + string prop, > + uint32_t size); > + public: > + /** > + * Delete all of the checkers that are part of this checker manager. > + */ > + ~check_manager(); > + /** > + * Default constructor, creates check manager containing all of the > + * default checks. > + */ > + check_manager(); > + /** > + * Run all of the checks on the specified tree. > + */ > + bool run_checks(device_tree *tree, bool keep_going); > + /** > + * Disables the named checker. > + */ > + bool disable_checker(string name); > + /** > + * Enables the named checker. > + */ > + bool enable_checker(string name); > +}; > + > +} // namespace checking > + > +} // namespace fdt > + > +} // namespace dtc > + > +#endif // !_CHECKING_HH_ > > Added: head/usr.bin/dtc/dtb.cc > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/usr.bin/dtc/dtb.cc Tue Jan 22 17:49:51 2013 (r245803) > @@ -0,0 +1,308 @@ > +/*- > + * Copyright (c) 2013 David Chisnall > + * All rights reserved. > + * > + * This software was developed by SRI International and the University of > + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) > + * ("CTSRD"), as part of the DARPA CRASH research programme. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * $FreeBSD$ > + */ > + > +#include "dtb.hh" > +#include <inttypes.h> > + > +namespace dtc > +{ > +namespace dtb > +{ > + > +void output_writer::write_data(byte_buffer b) > +{ > + for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++) > + { > + write_data(*i); > + } > +} > + > +void > +binary_writer::write_string(string name) > +{ > + name.push_to_buffer(buffer); > + // Trailing nul > + buffer.push_back(0); > +} > + > +void > +binary_writer::write_data(uint8_t v) > +{ > + buffer.push_back(v); > +} > + > +void > +binary_writer::write_data(uint32_t v) > +{ > + while (buffer.size() % 4 != 0) > + { > + buffer.push_back(0); > + } > + push_big_endian(buffer, v); > +} > + > +void > +binary_writer::write_data(uint64_t v) > +{ > + while (buffer.size() % 8 != 0) > + { > + buffer.push_back(0); > + } > + push_big_endian(buffer, v); > +} > + > +void > +binary_writer::write_to_file(int fd) > +{ > + // FIXME: Check return > + write(fd, buffer.data(), buffer.size()); > +} > + > +uint32_t > +binary_writer::size() > +{ > + return buffer.size(); > +} > + > +void > +asm_writer::write_string(const char *c) > +{ > + while (*c) > + { > + buffer.push_back((uint8_t)*(c++)); > + } > +} > + > +void > +asm_writer::write_line(const char *c) > +{ > + if (byte_count != 0) > + { > + byte_count = 0; > + buffer.push_back('\n'); > + } > + write_string(c); > +} > + > +void > +asm_writer::write_byte(uint8_t b) > +{ > + char out[3] = {0}; > + if (byte_count++ == 0) > + { > + buffer.push_back('\t'); > + } > + write_string(".byte 0x"); > + snprintf(out, 3, "%.2hhx", b); > + buffer.push_back(out[0]); > + buffer.push_back(out[1]); > + if (byte_count == 4) > + { > + buffer.push_back('\n'); > + byte_count = 0; > + } > + else > + { > + buffer.push_back(';'); > + buffer.push_back(' '); > + } > +} > + > +void > +asm_writer::write_label(string name) > +{ > + write_line("\t.globl "); > + name.push_to_buffer(buffer); > + buffer.push_back('\n'); > + name.push_to_buffer(buffer); > + buffer.push_back(':'); > + buffer.push_back('\n'); > + buffer.push_back('_'); > + name.push_to_buffer(buffer); > + buffer.push_back(':'); > + buffer.push_back('\n'); > + > +} > + > +void > +asm_writer::write_comment(string name) > +{ > + write_line("\t/* "); > + name.push_to_buffer(buffer); > + write_string(" */\n"); > +} > + > +void > +asm_writer::write_string(string name) > +{ > + write_line("\t.string \""); > + name.push_to_buffer(buffer); > + write_line("\"\n"); > + bytes_written += name.size() + 1; > +} > + > +void > +asm_writer::write_data(uint8_t v) > +{ > + write_byte(v); > + bytes_written++; > +} > + > +void > +asm_writer::write_data(uint32_t v) > +{ > + if (bytes_written % 4 != 0) > + { > + write_line("\t.balign 4\n"); > + bytes_written += (4 - (bytes_written % 4)); > + } > + write_byte((v >> 24) & 0xff); > + write_byte((v >> 16) & 0xff); > + write_byte((v >> 8) & 0xff); > + write_byte((v >> 0) & 0xff); > + bytes_written += 4; > +} > + > +void > +asm_writer::write_data(uint64_t v) > +{ > + if (bytes_written % 8 != 0) > + { > + write_line("\t.balign 8\n"); > + bytes_written += (8 - (bytes_written % 8)); > + } > + write_byte((v >> 56) & 0xff); > + write_byte((v >> 48) & 0xff); > + write_byte((v >> 40) & 0xff); > + write_byte((v >> 32) & 0xff); > + write_byte((v >> 24) & 0xff); > + write_byte((v >> 16) & 0xff); > + write_byte((v >> 8) & 0xff); > + write_byte((v >> 0) & 0xff); > + bytes_written += 8; > +} > + > +void > +asm_writer::write_to_file(int fd) > +{ > + // FIXME: Check return > + write(fd, buffer.data(), buffer.size()); > +} > + > +uint32_t > +asm_writer::size() > +{ > + return bytes_written; > +} > + > +void > +header::write(output_writer &out) > +{ > + out.write_label(string("dt_blob_start")); > + out.write_label(string("dt_header")); > + out.write_comment("magic"); > + out.write_data(magic); > + out.write_comment("totalsize"); > + out.write_data(totalsize); > + out.write_comment("off_dt_struct"); > + out.write_data(off_dt_struct); > + out.write_comment("off_dt_strings"); > + out.write_data(off_dt_strings); > + out.write_comment("off_mem_rsvmap"); > + out.write_data(off_mem_rsvmap); > + out.write_comment("version"); > + out.write_data(version); > + out.write_comment("last_comp_version"); > + out.write_data(last_comp_version); > + out.write_comment("boot_cpuid_phys"); > + out.write_data(boot_cpuid_phys); > + out.write_comment("size_dt_strings"); > + out.write_data(size_dt_strings); > + out.write_comment("size_dt_struct"); > + out.write_data(size_dt_struct); > +} > + > +bool > +header::read_dtb(input_buffer &input) > +{ > + if (!(input.consume_binary(magic) && magic == 0xd00dfeed)) > + { > + fprintf(stderr, "Missing magic token in header. Got %" PRIx32 > + " expected 0xd00dfeed\n", magic); > + return false; > + } > + return input.consume_binary(totalsize) && > + input.consume_binary(off_dt_struct) && > + input.consume_binary(off_dt_strings) && > + input.consume_binary(off_mem_rsvmap) && > + input.consume_binary(version) && > + input.consume_binary(last_comp_version) && > + input.consume_binary(boot_cpuid_phys) && > + input.consume_binary(size_dt_strings) && > + input.consume_binary(size_dt_struct); > +} > +uint32_t > +string_table::add_string(string str) > +{ > + std::map<string, uint32_t>::iterator old = string_offsets.find(str); > + if (old == string_offsets.end()) > + { > + uint32_t start = size; > + // Don't forget the trailing nul > + size += str.size() + 1; > + string_offsets.insert(std::make_pair(str, start)); > + strings.push_back(str); > + return start; > + } > + else > + { > + return old->second; > + } > +} > + > +void > +string_table::write(dtb::output_writer &writer) > +{ > + writer.write_comment(string("Strings table.")); > + writer.write_label(string("dt_strings_start")); > + for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ; > + i!=e ; ++i) > + { > + writer.write_string(*i); > + } > + writer.write_label(string("dt_strings_end")); > +} > + > +} // namespace dtb > + > +} // namespace dtc > + > > Added: head/usr.bin/dtc/dtb.hh > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/usr.bin/dtc/dtb.hh Tue Jan 22 17:49:51 2013 (r245803) > @@ -0,0 +1,365 @@ > +/*- > + * Copyright (c) 2013 David Chisnall > + * All rights reserved. > + * > + * This software was developed by SRI International and the University of > + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) > + * ("CTSRD"), as part of the DARPA CRASH research programme. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * $FreeBSD$ > + */ > + > +#ifndef _DTB_HH_ > > *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"