1245803Stheraven/*- 2245803Stheraven * Copyright (c) 2013 David Chisnall 3245803Stheraven * All rights reserved. 4245803Stheraven * 5245803Stheraven * This software was developed by SRI International and the University of 6245803Stheraven * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7245803Stheraven * ("CTSRD"), as part of the DARPA CRASH research programme. 8245803Stheraven * 9245803Stheraven * Redistribution and use in source and binary forms, with or without 10245803Stheraven * modification, are permitted provided that the following conditions 11245803Stheraven * are met: 12245803Stheraven * 1. Redistributions of source code must retain the above copyright 13245803Stheraven * notice, this list of conditions and the following disclaimer. 14245803Stheraven * 2. Redistributions in binary form must reproduce the above copyright 15245803Stheraven * notice, this list of conditions and the following disclaimer in the 16245803Stheraven * documentation and/or other materials provided with the distribution. 17245803Stheraven * 18245803Stheraven * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19245803Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20245803Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21245803Stheraven * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22245803Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23245803Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24245803Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25245803Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26245803Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27245803Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28245803Stheraven * SUCH DAMAGE. 29245803Stheraven * 30245803Stheraven * $FreeBSD$ 31245803Stheraven */ 32245803Stheraven 33245803Stheraven#ifndef _CHECKING_HH_ 34245803Stheraven#define _CHECKING_HH_ 35245803Stheraven#include "string.hh" 36245803Stheraven#include "fdt.hh" 37245803Stheraven 38245803Stheravennamespace dtc 39245803Stheraven{ 40245803Stheravennamespace fdt 41245803Stheraven{ 42245803Stheravennamespace checking 43245803Stheraven{ 44245803Stheraven/** 45245803Stheraven * Base class for all checkers. This will visit the entire tree and perform 46245803Stheraven * semantic checks defined in subclasses. Note that device trees are generally 47245803Stheraven * small (a few dozen nodes at most) and so we optimise for flexibility and 48245803Stheraven * extensibility here, not for performance. Each checker will visit the entire 49245803Stheraven * tree. 50245803Stheraven */ 51245803Stheravenclass checker 52245803Stheraven{ 53245803Stheraven /** 54245803Stheraven * The path to the current node being checked. This is used for 55245803Stheraven * printing error messages. 56245803Stheraven */ 57245803Stheraven device_tree::node_path path; 58245803Stheraven /** 59245803Stheraven * The name of the checker. This is used for printing error messages 60245803Stheraven * and for enabling / disabling specific checkers from the command 61245803Stheraven * line. 62245803Stheraven */ 63245803Stheraven const char *checker_name; 64245803Stheraven /** 65245803Stheraven * Visits each node, calling the checker functions on properties and 66245803Stheraven * nodes. 67245803Stheraven */ 68245803Stheraven bool visit_node(device_tree *tree, node *n); 69245803Stheraven protected: 70245803Stheraven /** 71245803Stheraven * Prints the error message, along with the path to the node that 72245803Stheraven * caused the error and the name of the checker. 73245803Stheraven */ 74245803Stheraven void report_error(const char *errmsg); 75245803Stheraven public: 76245803Stheraven /** 77245803Stheraven * Constructor. Takes the name of this checker, which is which is used 78245803Stheraven * when reporting errors. 79245803Stheraven */ 80245803Stheraven checker(const char *name) : checker_name(name) {} 81245803Stheraven /** 82245803Stheraven * Virtual destructor in case any subclasses need to do cleanup. 83245803Stheraven */ 84245803Stheraven virtual ~checker() {} 85245803Stheraven /** 86245803Stheraven * Method for checking that a node is valid. The root class version 87245803Stheraven * does nothing, subclasses should override this. 88245803Stheraven */ 89245803Stheraven virtual bool check_node(device_tree *tree, node *n) 90245803Stheraven { 91245803Stheraven return true; 92245803Stheraven } 93245803Stheraven /** 94245803Stheraven * Method for checking that a property is valid. The root class 95245803Stheraven * version does nothing, subclasses should override this. 96245803Stheraven */ 97245803Stheraven virtual bool check_property(device_tree *tree, node *n, property *p) 98245803Stheraven { 99245803Stheraven return true; 100245803Stheraven } 101245803Stheraven /** 102245803Stheraven * Runs the checker on the specified device tree. 103245803Stheraven */ 104245803Stheraven bool check_tree(fdt::device_tree *tree) 105245803Stheraven { 106245803Stheraven return visit_node(tree, tree->get_root()); 107245803Stheraven } 108245803Stheraven}; 109245803Stheraven 110245803Stheraven/** 111245803Stheraven * Abstract base class for simple property checks. This class defines a check 112245803Stheraven * method for subclasses, which is invoked only when it finds a property with 113245803Stheraven * the matching name. To define simple property checkers, just subclass this 114245803Stheraven * and override the check() method. 115245803Stheraven */ 116245803Stheravenclass property_checker : public checker 117245803Stheraven{ 118245803Stheraven /** 119245803Stheraven * The name of the property that this checker is looking for. 120245803Stheraven */ 121245803Stheraven string key; 122245803Stheraven public: 123245803Stheraven /** 124245803Stheraven * Implementation of the generic property-checking method that checks 125245803Stheraven * for a property with the name specified in the constructor 126245803Stheraven */ 127245803Stheraven virtual bool check_property(device_tree *tree, node *n, property *p); 128245803Stheraven /** 129245803Stheraven * Constructor. Takes the name of the checker and the name of the 130245803Stheraven * property to check. 131245803Stheraven */ 132245803Stheraven property_checker(const char* name, string property_name) 133245803Stheraven : checker(name), key(property_name) {} 134245803Stheraven /** 135245803Stheraven * The check method, which subclasses should implement. 136245803Stheraven */ 137245803Stheraven virtual bool check(device_tree *tree, node *n, property *p) = 0; 138245803Stheraven}; 139245803Stheraven 140245803Stheraven/** 141245803Stheraven * Property type checker. 142245803Stheraven */ 143245803Stheraventemplate<property_value::value_type T> 144245803Stheravenstruct property_type_checker : public property_checker 145245803Stheraven{ 146245803Stheraven /** 147245803Stheraven * Constructor, takes the name of the checker and the name of the 148245803Stheraven * property to check as arguments. 149245803Stheraven */ 150245803Stheraven property_type_checker(const char* name, string property_name) : 151245803Stheraven property_checker(name, property_name) {} 152245803Stheraven virtual bool check(device_tree *tree, node *n, property *p) = 0; 153245803Stheraven}; 154245803Stheraven 155245803Stheraven/** 156245803Stheraven * Empty property checker. This checks that the property has no value. 157245803Stheraven */ 158245803Stheraventemplate<> 159245803Stheravenstruct property_type_checker <property_value::EMPTY> : public property_checker 160245803Stheraven{ 161245803Stheraven property_type_checker(const char* name, string property_name) : 162245803Stheraven property_checker(name, property_name) {} 163245803Stheraven virtual bool check(device_tree *tree, node *n, property *p) 164245803Stheraven { 165245803Stheraven return p->begin() == p->end(); 166245803Stheraven } 167245803Stheraven}; 168245803Stheraven 169245803Stheraven/** 170245803Stheraven * String property checker. This checks that the property has exactly one 171245803Stheraven * value, which is a string. 172245803Stheraven */ 173245803Stheraventemplate<> 174245803Stheravenstruct property_type_checker <property_value::STRING> : public property_checker 175245803Stheraven{ 176245803Stheraven property_type_checker(const char* name, string property_name) : 177245803Stheraven property_checker(name, property_name) {} 178245803Stheraven virtual bool check(device_tree *tree, node *n, property *p) 179245803Stheraven { 180245803Stheraven return (p->begin() + 1 == p->end()) && p->begin()->is_string(); 181245803Stheraven } 182245803Stheraven}; 183245803Stheraven/** 184245803Stheraven * String list property checker. This checks that the property has at least 185245803Stheraven * one value, all of which are strings. 186245803Stheraven */ 187245803Stheraventemplate<> 188245803Stheravenstruct property_type_checker <property_value::STRING_LIST> : 189245803Stheraven public property_checker 190245803Stheraven{ 191245803Stheraven property_type_checker(const char* name, string property_name) : 192245803Stheraven property_checker(name, property_name) {} 193245803Stheraven virtual bool check(device_tree *tree, node *n, property *p) 194245803Stheraven { 195245803Stheraven for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; 196245803Stheraven ++i) 197245803Stheraven { 198245803Stheraven if (!(i->is_string() || i->is_string_list())) 199245803Stheraven { 200245803Stheraven return false; 201245803Stheraven } 202245803Stheraven } 203245803Stheraven return p->begin() != p->end(); 204245803Stheraven } 205245803Stheraven}; 206245803Stheraven 207245803Stheraven/** 208245803Stheraven * Phandle property checker. This checks that the property has exactly one 209245803Stheraven * value, which is a valid phandle. 210245803Stheraven */ 211245803Stheraventemplate<> 212245803Stheravenstruct property_type_checker <property_value::PHANDLE> : public property_checker 213245803Stheraven{ 214245803Stheraven property_type_checker(const char* name, string property_name) : 215245803Stheraven property_checker(name, property_name) {} 216245803Stheraven virtual bool check(device_tree *tree, node *n, property *p) 217245803Stheraven { 218245803Stheraven return (p->begin() + 1 == p->end()) && 219245803Stheraven (tree->referenced_node(*p->begin()) != 0); 220245803Stheraven } 221245803Stheraven}; 222245803Stheraven 223245803Stheraven/** 224245803Stheraven * Check that a property has the correct size. 225245803Stheraven */ 226245803Stheravenstruct property_size_checker : public property_checker 227245803Stheraven{ 228245803Stheraven /** 229245803Stheraven * The expected size of the property. 230245803Stheraven */ 231245803Stheraven uint32_t size; 232245803Stheraven public: 233245803Stheraven /** 234245803Stheraven * Constructor, takes the name of the checker, the name of the property 235245803Stheraven * to check, and its expected size as arguments. 236245803Stheraven */ 237245803Stheraven property_size_checker(const char* name, string property_name, uint32_t bytes) 238245803Stheraven : property_checker(name, property_name), size(bytes) {} 239245803Stheraven /** 240245803Stheraven * Check, validates that the property has the correct size. 241245803Stheraven */ 242245803Stheraven virtual bool check(device_tree *tree, node *n, property *p); 243245803Stheraven}; 244245803Stheraven 245245803Stheraven 246245803Stheraven/** 247245803Stheraven * The check manager is the interface to running the checks. This allows 248245803Stheraven * default checks to be enabled, non-default checks to be enabled, and so on. 249245803Stheraven */ 250245803Stheravenclass check_manager 251245803Stheraven{ 252245803Stheraven /** 253245803Stheraven * The enabled checkers, indexed by their names. The name is used when 254245803Stheraven * disabling checkers from the command line. When this manager runs, 255245803Stheraven * it will only run the checkers from this map. 256245803Stheraven */ 257245803Stheraven std::map<string, checker*> checkers; 258245803Stheraven /** 259245803Stheraven * The disabled checkers. Moving checkers to this list disables them, 260245803Stheraven * but allows them to be easily moved back. 261245803Stheraven */ 262245803Stheraven std::map<string, checker*> disabled_checkers; 263245803Stheraven /** 264245803Stheraven * Helper function for adding a property value checker. 265245803Stheraven */ 266245803Stheraven template<property_value::value_type T> 267245803Stheraven void add_property_type_checker(const char *name, string prop); 268245803Stheraven /** 269245803Stheraven * Helper function for adding a simple type checker. 270245803Stheraven */ 271245803Stheraven void add_property_type_checker(const char *name, string prop); 272245803Stheraven /** 273245803Stheraven * Helper function for adding a property value checker. 274245803Stheraven */ 275245803Stheraven void add_property_size_checker(const char *name, 276245803Stheraven string prop, 277245803Stheraven uint32_t size); 278245803Stheraven public: 279245803Stheraven /** 280245803Stheraven * Delete all of the checkers that are part of this checker manager. 281245803Stheraven */ 282245803Stheraven ~check_manager(); 283245803Stheraven /** 284245803Stheraven * Default constructor, creates check manager containing all of the 285245803Stheraven * default checks. 286245803Stheraven */ 287245803Stheraven check_manager(); 288245803Stheraven /** 289245803Stheraven * Run all of the checks on the specified tree. 290245803Stheraven */ 291245803Stheraven bool run_checks(device_tree *tree, bool keep_going); 292245803Stheraven /** 293245803Stheraven * Disables the named checker. 294245803Stheraven */ 295245803Stheraven bool disable_checker(string name); 296245803Stheraven /** 297245803Stheraven * Enables the named checker. 298245803Stheraven */ 299245803Stheraven bool enable_checker(string name); 300245803Stheraven}; 301245803Stheraven 302245803Stheraven} // namespace checking 303245803Stheraven 304245803Stheraven} // namespace fdt 305245803Stheraven 306245803Stheraven} // namespace dtc 307245803Stheraven 308245803Stheraven#endif // !_CHECKING_HH_ 309