svn commit: r245803 - in head: . gnu/usr.bin share/man/man5 share/mk usr.bin/dtc

David Chisnall theraven at FreeBSD.org
Tue Jan 22 17:49:53 UTC 2013


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 ***


More information about the svn-src-all mailing list