checking.hh revision 259065
1207753Smm/*- 2207753Smm * Copyright (c) 2013 David Chisnall 3207753Smm * All rights reserved. 4207753Smm * 5207753Smm * This software was developed by SRI International and the University of 6207753Smm * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7207753Smm * ("CTSRD"), as part of the DARPA CRASH research programme. 8207753Smm * 9263285Sdelphij * Redistribution and use in source and binary forms, with or without 10207753Smm * modification, are permitted provided that the following conditions 11207753Smm * are met: 12207753Smm * 1. Redistributions of source code must retain the above copyright 13207753Smm * notice, this list of conditions and the following disclaimer. 14223935Smm * 2. Redistributions in binary form must reproduce the above copyright 15223935Smm * notice, this list of conditions and the following disclaimer in the 16223935Smm * documentation and/or other materials provided with the distribution. 17207753Smm * 18244601Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19207753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20213700Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21213700Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22207753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23274261Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24292588Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25244601Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26207753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27207753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28207753Smm * SUCH DAMAGE. 29207753Smm * 30207753Smm * $FreeBSD: releng/10.0/usr.bin/dtc/checking.hh 245803 2013-01-22 17:49:51Z theraven $ 31213700Smm */ 32244601Smm 33292588Sdelphij#ifndef _CHECKING_HH_ 34207753Smm#define _CHECKING_HH_ 35292588Sdelphij#include "string.hh" 36292588Sdelphij#include "fdt.hh" 37223935Smm 38219001Smmnamespace dtc 39292588Sdelphij{ 40207753Smmnamespace fdt 41292588Sdelphij{ 42292588Sdelphijnamespace checking 43207753Smm{ 44207753Smm/** 45292588Sdelphij * Base class for all checkers. This will visit the entire tree and perform 46207753Smm * semantic checks defined in subclasses. Note that device trees are generally 47207753Smm * small (a few dozen nodes at most) and so we optimise for flexibility and 48207753Smm * extensibility here, not for performance. Each checker will visit the entire 49207753Smm * tree. 50292588Sdelphij */ 51292588Sdelphijclass checker 52207753Smm{ 53207753Smm /** 54292588Sdelphij * The path to the current node being checked. This is used for 55207753Smm * printing error messages. 56207753Smm */ 57244601Smm device_tree::node_path path; 58223935Smm /** 59213700Smm * The name of the checker. This is used for printing error messages 60244601Smm * and for enabling / disabling specific checkers from the command 61223935Smm * line. 62207753Smm */ 63292588Sdelphij const char *checker_name; 64263285Sdelphij /** 65207753Smm * Visits each node, calling the checker functions on properties and 66207753Smm * nodes. 67312518Sdelphij */ 68207753Smm bool visit_node(device_tree *tree, node *n); 69207753Smm protected: 70213700Smm /** 71213700Smm * Prints the error message, along with the path to the node that 72244601Smm * caused the error and the name of the checker. 73292588Sdelphij */ 74207753Smm void report_error(const char *errmsg); 75223935Smm public: 76207753Smm /** 77207753Smm * Constructor. Takes the name of this checker, which is which is used 78312518Sdelphij * when reporting errors. 79292588Sdelphij */ 80263285Sdelphij checker(const char *name) : checker_name(name) {} 81292588Sdelphij /** 82207753Smm * Virtual destructor in case any subclasses need to do cleanup. 83207753Smm */ 84263285Sdelphij virtual ~checker() {} 85219001Smm /** 86207753Smm * Method for checking that a node is valid. The root class version 87292588Sdelphij * does nothing, subclasses should override this. 88207753Smm */ 89207753Smm virtual bool check_node(device_tree *tree, node *n) 90244601Smm { 91207753Smm return true; 92207753Smm } 93207753Smm /** 94312518Sdelphij * Method for checking that a property is valid. The root class 95292588Sdelphij * version does nothing, subclasses should override this. 96207753Smm */ 97223935Smm virtual bool check_property(device_tree *tree, node *n, property *p) 98292588Sdelphij { 99207753Smm return true; 100207753Smm } 101207753Smm /** 102207753Smm * Runs the checker on the specified device tree. 103223935Smm */ 104292588Sdelphij bool check_tree(fdt::device_tree *tree) 105207753Smm { 106207753Smm return visit_node(tree, tree->get_root()); 107292588Sdelphij } 108312518Sdelphij}; 109207753Smm 110207753Smm/** 111207753Smm * Abstract base class for simple property checks. This class defines a check 112207753Smm * method for subclasses, which is invoked only when it finds a property with 113207753Smm * the matching name. To define simple property checkers, just subclass this 114207753Smm * and override the check() method. 115207753Smm */ 116207753Smmclass property_checker : public checker 117207753Smm{ 118207753Smm /** 119207753Smm * The name of the property that this checker is looking for. 120207753Smm */ 121 string key; 122 public: 123 /** 124 * Implementation of the generic property-checking method that checks 125 * for a property with the name specified in the constructor 126 */ 127 virtual bool check_property(device_tree *tree, node *n, property *p); 128 /** 129 * Constructor. Takes the name of the checker and the name of the 130 * property to check. 131 */ 132 property_checker(const char* name, string property_name) 133 : checker(name), key(property_name) {} 134 /** 135 * The check method, which subclasses should implement. 136 */ 137 virtual bool check(device_tree *tree, node *n, property *p) = 0; 138}; 139 140/** 141 * Property type checker. 142 */ 143template<property_value::value_type T> 144struct property_type_checker : public property_checker 145{ 146 /** 147 * Constructor, takes the name of the checker and the name of the 148 * property to check as arguments. 149 */ 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; 153}; 154 155/** 156 * Empty property checker. This checks that the property has no value. 157 */ 158template<> 159struct property_type_checker <property_value::EMPTY> : public property_checker 160{ 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) 164 { 165 return p->begin() == p->end(); 166 } 167}; 168 169/** 170 * String property checker. This checks that the property has exactly one 171 * value, which is a string. 172 */ 173template<> 174struct property_type_checker <property_value::STRING> : public property_checker 175{ 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) 179 { 180 return (p->begin() + 1 == p->end()) && p->begin()->is_string(); 181 } 182}; 183/** 184 * String list property checker. This checks that the property has at least 185 * one value, all of which are strings. 186 */ 187template<> 188struct property_type_checker <property_value::STRING_LIST> : 189 public property_checker 190{ 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) 194 { 195 for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; 196 ++i) 197 { 198 if (!(i->is_string() || i->is_string_list())) 199 { 200 return false; 201 } 202 } 203 return p->begin() != p->end(); 204 } 205}; 206 207/** 208 * Phandle property checker. This checks that the property has exactly one 209 * value, which is a valid phandle. 210 */ 211template<> 212struct property_type_checker <property_value::PHANDLE> : public property_checker 213{ 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) 217 { 218 return (p->begin() + 1 == p->end()) && 219 (tree->referenced_node(*p->begin()) != 0); 220 } 221}; 222 223/** 224 * Check that a property has the correct size. 225 */ 226struct property_size_checker : public property_checker 227{ 228 /** 229 * The expected size of the property. 230 */ 231 uint32_t size; 232 public: 233 /** 234 * Constructor, takes the name of the checker, the name of the property 235 * to check, and its expected size as arguments. 236 */ 237 property_size_checker(const char* name, string property_name, uint32_t bytes) 238 : property_checker(name, property_name), size(bytes) {} 239 /** 240 * Check, validates that the property has the correct size. 241 */ 242 virtual bool check(device_tree *tree, node *n, property *p); 243}; 244 245 246/** 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. 249 */ 250class check_manager 251{ 252 /** 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. 256 */ 257 std::map<string, checker*> checkers; 258 /** 259 * The disabled checkers. Moving checkers to this list disables them, 260 * but allows them to be easily moved back. 261 */ 262 std::map<string, checker*> disabled_checkers; 263 /** 264 * Helper function for adding a property value checker. 265 */ 266 template<property_value::value_type T> 267 void add_property_type_checker(const char *name, string prop); 268 /** 269 * Helper function for adding a simple type checker. 270 */ 271 void add_property_type_checker(const char *name, string prop); 272 /** 273 * Helper function for adding a property value checker. 274 */ 275 void add_property_size_checker(const char *name, 276 string prop, 277 uint32_t size); 278 public: 279 /** 280 * Delete all of the checkers that are part of this checker manager. 281 */ 282 ~check_manager(); 283 /** 284 * Default constructor, creates check manager containing all of the 285 * default checks. 286 */ 287 check_manager(); 288 /** 289 * Run all of the checks on the specified tree. 290 */ 291 bool run_checks(device_tree *tree, bool keep_going); 292 /** 293 * Disables the named checker. 294 */ 295 bool disable_checker(string name); 296 /** 297 * Enables the named checker. 298 */ 299 bool enable_checker(string name); 300}; 301 302} // namespace checking 303 304} // namespace fdt 305 306} // namespace dtc 307 308#endif // !_CHECKING_HH_ 309