2 * Copyright (c) 2013 David Chisnall
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.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
45 * Base class for all checkers. This will visit the entire tree and perform
46 * semantic checks defined in subclasses. Note that device trees are generally
47 * small (a few dozen nodes at most) and so we optimise for flexibility and
48 * extensibility here, not for performance. Each checker will visit the entire
54 * The path to the current node being checked. This is used for
55 * printing error messages.
57 device_tree::node_path path;
59 * The name of the checker. This is used for printing error messages
60 * and for enabling / disabling specific checkers from the command
63 const char *checker_name;
65 * Visits each node, calling the checker functions on properties and
68 bool visit_node(device_tree *tree, node *n);
71 * Prints the error message, along with the path to the node that
72 * caused the error and the name of the checker.
74 void report_error(const char *errmsg);
77 * Constructor. Takes the name of this checker, which is which is used
78 * when reporting errors.
80 checker(const char *name) : checker_name(name) {}
82 * Virtual destructor in case any subclasses need to do cleanup.
86 * Method for checking that a node is valid. The root class version
87 * does nothing, subclasses should override this.
89 virtual bool check_node(device_tree *tree, node *n)
94 * Method for checking that a property is valid. The root class
95 * version does nothing, subclasses should override this.
97 virtual bool check_property(device_tree *tree, node *n, property *p)
102 * Runs the checker on the specified device tree.
104 bool check_tree(fdt::device_tree *tree)
106 return visit_node(tree, tree->get_root());
111 * Abstract base class for simple property checks. This class defines a check
112 * method for subclasses, which is invoked only when it finds a property with
113 * the matching name. To define simple property checkers, just subclass this
114 * and override the check() method.
116 class property_checker : public checker
119 * The name of the property that this checker is looking for.
124 * Implementation of the generic property-checking method that checks
125 * for a property with the name specified in the constructor
127 virtual bool check_property(device_tree *tree, node *n, property *p);
129 * Constructor. Takes the name of the checker and the name of the
132 property_checker(const char* name, string property_name)
133 : checker(name), key(property_name) {}
135 * The check method, which subclasses should implement.
137 virtual bool check(device_tree *tree, node *n, property *p) = 0;
141 * Property type checker.
143 template<property_value::value_type T>
144 struct property_type_checker : public property_checker
147 * Constructor, takes the name of the checker and the name of the
148 * property to check as arguments.
150 property_type_checker(const char* name, string property_name) :
151 property_checker(name, property_name) {}
152 virtual bool check(device_tree *tree, node *n, property *p) = 0;
156 * Empty property checker. This checks that the property has no value.
159 struct property_type_checker <property_value::EMPTY> : public property_checker
161 property_type_checker(const char* name, string property_name) :
162 property_checker(name, property_name) {}
163 virtual bool check(device_tree *tree, node *n, property *p)
165 return p->begin() == p->end();
170 * String property checker. This checks that the property has exactly one
171 * value, which is a string.
174 struct property_type_checker <property_value::STRING> : public property_checker
176 property_type_checker(const char* name, string property_name) :
177 property_checker(name, property_name) {}
178 virtual bool check(device_tree *tree, node *n, property *p)
180 return (p->begin() + 1 == p->end()) && p->begin()->is_string();
184 * String list property checker. This checks that the property has at least
185 * one value, all of which are strings.
188 struct property_type_checker <property_value::STRING_LIST> :
189 public property_checker
191 property_type_checker(const char* name, string property_name) :
192 property_checker(name, property_name) {}
193 virtual bool check(device_tree *tree, node *n, property *p)
195 for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ;
198 if (!(i->is_string() || i->is_string_list()))
203 return p->begin() != p->end();
208 * Phandle property checker. This checks that the property has exactly one
209 * value, which is a valid phandle.
212 struct property_type_checker <property_value::PHANDLE> : public property_checker
214 property_type_checker(const char* name, string property_name) :
215 property_checker(name, property_name) {}
216 virtual bool check(device_tree *tree, node *n, property *p)
218 return (p->begin() + 1 == p->end()) &&
219 (tree->referenced_node(*p->begin()) != 0);
224 * Check that a property has the correct size.
226 struct property_size_checker : public property_checker
229 * The expected size of the property.
234 * Constructor, takes the name of the checker, the name of the property
235 * to check, and its expected size as arguments.
237 property_size_checker(const char* name, string property_name, uint32_t bytes)
238 : property_checker(name, property_name), size(bytes) {}
240 * Check, validates that the property has the correct size.
242 virtual bool check(device_tree *tree, node *n, property *p);
247 * The check manager is the interface to running the checks. This allows
248 * default checks to be enabled, non-default checks to be enabled, and so on.
253 * The enabled checkers, indexed by their names. The name is used when
254 * disabling checkers from the command line. When this manager runs,
255 * it will only run the checkers from this map.
257 std::map<string, checker*> checkers;
259 * The disabled checkers. Moving checkers to this list disables them,
260 * but allows them to be easily moved back.
262 std::map<string, checker*> disabled_checkers;
264 * Helper function for adding a property value checker.
266 template<property_value::value_type T>
267 void add_property_type_checker(const char *name, string prop);
269 * Helper function for adding a simple type checker.
271 void add_property_type_checker(const char *name, string prop);
273 * Helper function for adding a property value checker.
275 void add_property_size_checker(const char *name,
280 * Delete all of the checkers that are part of this checker manager.
284 * Default constructor, creates check manager containing all of the
289 * Run all of the checks on the specified tree.
291 bool run_checks(device_tree *tree, bool keep_going);
293 * Disables the named checker.
295 bool disable_checker(string name);
297 * Enables the named checker.
299 bool enable_checker(string name);
302 } // namespace checking
308 #endif // !_CHECKING_HH_