summaryrefslogtreecommitdiffstats
path: root/usr.bin/dtc/checking.hh
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/dtc/checking.hh')
-rw-r--r--usr.bin/dtc/checking.hh308
1 files changed, 308 insertions, 0 deletions
diff --git a/usr.bin/dtc/checking.hh b/usr.bin/dtc/checking.hh
new file mode 100644
index 0000000..0de1d60
--- /dev/null
+++ b/usr.bin/dtc/checking.hh
@@ -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_
OpenPOWER on IntegriCloud