1af0dd31fSDavid Chisnall /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 4af0dd31fSDavid Chisnall * Copyright (c) 2013 David Chisnall 5af0dd31fSDavid Chisnall * All rights reserved. 6af0dd31fSDavid Chisnall * 7af0dd31fSDavid Chisnall * This software was developed by SRI International and the University of 8af0dd31fSDavid Chisnall * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 9af0dd31fSDavid Chisnall * ("CTSRD"), as part of the DARPA CRASH research programme. 10af0dd31fSDavid Chisnall * 11af0dd31fSDavid Chisnall * Redistribution and use in source and binary forms, with or without 12af0dd31fSDavid Chisnall * modification, are permitted provided that the following conditions 13af0dd31fSDavid Chisnall * are met: 14af0dd31fSDavid Chisnall * 1. Redistributions of source code must retain the above copyright 15af0dd31fSDavid Chisnall * notice, this list of conditions and the following disclaimer. 16af0dd31fSDavid Chisnall * 2. Redistributions in binary form must reproduce the above copyright 17af0dd31fSDavid Chisnall * notice, this list of conditions and the following disclaimer in the 18af0dd31fSDavid Chisnall * documentation and/or other materials provided with the distribution. 19af0dd31fSDavid Chisnall * 20af0dd31fSDavid Chisnall * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21af0dd31fSDavid Chisnall * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22af0dd31fSDavid Chisnall * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23af0dd31fSDavid Chisnall * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24af0dd31fSDavid Chisnall * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25af0dd31fSDavid Chisnall * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26af0dd31fSDavid Chisnall * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27af0dd31fSDavid Chisnall * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28af0dd31fSDavid Chisnall * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29af0dd31fSDavid Chisnall * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30af0dd31fSDavid Chisnall * SUCH DAMAGE. 31af0dd31fSDavid Chisnall */ 32af0dd31fSDavid Chisnall 33af0dd31fSDavid Chisnall #ifndef _CHECKING_HH_ 34af0dd31fSDavid Chisnall #define _CHECKING_HH_ 35bbe31b70SEd Maste #include <string> 36af0dd31fSDavid Chisnall #include "fdt.hh" 37af0dd31fSDavid Chisnall 38af0dd31fSDavid Chisnall namespace dtc 39af0dd31fSDavid Chisnall { 40af0dd31fSDavid Chisnall namespace fdt 41af0dd31fSDavid Chisnall { 42af0dd31fSDavid Chisnall namespace checking 43af0dd31fSDavid Chisnall { 44af0dd31fSDavid Chisnall /** 45af0dd31fSDavid Chisnall * Base class for all checkers. This will visit the entire tree and perform 46af0dd31fSDavid Chisnall * semantic checks defined in subclasses. Note that device trees are generally 47af0dd31fSDavid Chisnall * small (a few dozen nodes at most) and so we optimise for flexibility and 48af0dd31fSDavid Chisnall * extensibility here, not for performance. Each checker will visit the entire 49af0dd31fSDavid Chisnall * tree. 50af0dd31fSDavid Chisnall */ 51af0dd31fSDavid Chisnall class checker 52af0dd31fSDavid Chisnall { 53af0dd31fSDavid Chisnall /** 54af0dd31fSDavid Chisnall * The path to the current node being checked. This is used for 55af0dd31fSDavid Chisnall * printing error messages. 56af0dd31fSDavid Chisnall */ 57af0dd31fSDavid Chisnall device_tree::node_path path; 58af0dd31fSDavid Chisnall /** 59af0dd31fSDavid Chisnall * The name of the checker. This is used for printing error messages 60af0dd31fSDavid Chisnall * and for enabling / disabling specific checkers from the command 61af0dd31fSDavid Chisnall * line. 62af0dd31fSDavid Chisnall */ 63af0dd31fSDavid Chisnall const char *checker_name; 64af0dd31fSDavid Chisnall /** 65af0dd31fSDavid Chisnall * Visits each node, calling the checker functions on properties and 66af0dd31fSDavid Chisnall * nodes. 67af0dd31fSDavid Chisnall */ 68a0706eb4SDavid Chisnall bool visit_node(device_tree *tree, const node_ptr &n); 69af0dd31fSDavid Chisnall protected: 70af0dd31fSDavid Chisnall /** 71af0dd31fSDavid Chisnall * Prints the error message, along with the path to the node that 72af0dd31fSDavid Chisnall * caused the error and the name of the checker. 73af0dd31fSDavid Chisnall */ 74af0dd31fSDavid Chisnall void report_error(const char *errmsg); 75af0dd31fSDavid Chisnall public: 76af0dd31fSDavid Chisnall /** 77af0dd31fSDavid Chisnall * Constructor. Takes the name of this checker, which is which is used 78af0dd31fSDavid Chisnall * when reporting errors. 79af0dd31fSDavid Chisnall */ checker(const char * name)80af0dd31fSDavid Chisnall checker(const char *name) : checker_name(name) {} 81af0dd31fSDavid Chisnall /** 82af0dd31fSDavid Chisnall * Virtual destructor in case any subclasses need to do cleanup. 83af0dd31fSDavid Chisnall */ ~checker()84af0dd31fSDavid Chisnall virtual ~checker() {} 85af0dd31fSDavid Chisnall /** 86af0dd31fSDavid Chisnall * Method for checking that a node is valid. The root class version 87af0dd31fSDavid Chisnall * does nothing, subclasses should override this. 88af0dd31fSDavid Chisnall */ check_node(device_tree *,const node_ptr &)89c64a3eafSDavid Chisnall virtual bool check_node(device_tree *, const node_ptr &) 90af0dd31fSDavid Chisnall { 91af0dd31fSDavid Chisnall return true; 92af0dd31fSDavid Chisnall } 93af0dd31fSDavid Chisnall /** 94af0dd31fSDavid Chisnall * Method for checking that a property is valid. The root class 95af0dd31fSDavid Chisnall * version does nothing, subclasses should override this. 96af0dd31fSDavid Chisnall */ check_property(device_tree *,const node_ptr &,property_ptr)97c64a3eafSDavid Chisnall virtual bool check_property(device_tree *, const node_ptr &, property_ptr ) 98af0dd31fSDavid Chisnall { 99af0dd31fSDavid Chisnall return true; 100af0dd31fSDavid Chisnall } 101af0dd31fSDavid Chisnall /** 102af0dd31fSDavid Chisnall * Runs the checker on the specified device tree. 103af0dd31fSDavid Chisnall */ check_tree(fdt::device_tree * tree)104af0dd31fSDavid Chisnall bool check_tree(fdt::device_tree *tree) 105af0dd31fSDavid Chisnall { 106af0dd31fSDavid Chisnall return visit_node(tree, tree->get_root()); 107af0dd31fSDavid Chisnall } 108af0dd31fSDavid Chisnall }; 109af0dd31fSDavid Chisnall 110af0dd31fSDavid Chisnall /** 111af0dd31fSDavid Chisnall * Abstract base class for simple property checks. This class defines a check 112af0dd31fSDavid Chisnall * method for subclasses, which is invoked only when it finds a property with 113af0dd31fSDavid Chisnall * the matching name. To define simple property checkers, just subclass this 114af0dd31fSDavid Chisnall * and override the check() method. 115af0dd31fSDavid Chisnall */ 116af0dd31fSDavid Chisnall class property_checker : public checker 117af0dd31fSDavid Chisnall { 118af0dd31fSDavid Chisnall /** 119af0dd31fSDavid Chisnall * The name of the property that this checker is looking for. 120af0dd31fSDavid Chisnall */ 121bbe31b70SEd Maste std::string key; 122af0dd31fSDavid Chisnall public: 123af0dd31fSDavid Chisnall /** 124af0dd31fSDavid Chisnall * Implementation of the generic property-checking method that checks 125bbe31b70SEd Maste * for a property with the name specified in the constructor. 126af0dd31fSDavid Chisnall */ 127a0706eb4SDavid Chisnall virtual bool check_property(device_tree *tree, const node_ptr &n, property_ptr p); 128af0dd31fSDavid Chisnall /** 129af0dd31fSDavid Chisnall * Constructor. Takes the name of the checker and the name of the 130af0dd31fSDavid Chisnall * property to check. 131af0dd31fSDavid Chisnall */ property_checker(const char * name,const std::string & property_name)132bbe31b70SEd Maste property_checker(const char* name, const std::string &property_name) 133af0dd31fSDavid Chisnall : checker(name), key(property_name) {} 134af0dd31fSDavid Chisnall /** 135af0dd31fSDavid Chisnall * The check method, which subclasses should implement. 136af0dd31fSDavid Chisnall */ 137a0706eb4SDavid Chisnall virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0; 138af0dd31fSDavid Chisnall }; 139af0dd31fSDavid Chisnall 140af0dd31fSDavid Chisnall /** 141af0dd31fSDavid Chisnall * Property type checker. 142af0dd31fSDavid Chisnall */ 143af0dd31fSDavid Chisnall template<property_value::value_type T> 144af0dd31fSDavid Chisnall struct property_type_checker : public property_checker 145af0dd31fSDavid Chisnall { 146af0dd31fSDavid Chisnall /** 147af0dd31fSDavid Chisnall * Constructor, takes the name of the checker and the name of the 148af0dd31fSDavid Chisnall * property to check as arguments. 149af0dd31fSDavid Chisnall */ property_type_checkerdtc::fdt::checking::property_type_checker150bbe31b70SEd Maste property_type_checker(const char* name, const std::string &property_name) : 151af0dd31fSDavid Chisnall property_checker(name, property_name) {} 152a0706eb4SDavid Chisnall virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0; 153af0dd31fSDavid Chisnall }; 154af0dd31fSDavid Chisnall 155af0dd31fSDavid Chisnall /** 156af0dd31fSDavid Chisnall * Empty property checker. This checks that the property has no value. 157af0dd31fSDavid Chisnall */ 158af0dd31fSDavid Chisnall template<> 159af0dd31fSDavid Chisnall struct property_type_checker <property_value::EMPTY> : public property_checker 160af0dd31fSDavid Chisnall { property_type_checkerdtc::fdt::checking::property_type_checker161bbe31b70SEd Maste property_type_checker(const char* name, const std::string &property_name) : 162af0dd31fSDavid Chisnall property_checker(name, property_name) {} checkdtc::fdt::checking::property_type_checker163c64a3eafSDavid Chisnall virtual bool check(device_tree *, const node_ptr &, property_ptr p) 164af0dd31fSDavid Chisnall { 165af0dd31fSDavid Chisnall return p->begin() == p->end(); 166af0dd31fSDavid Chisnall } 167af0dd31fSDavid Chisnall }; 168af0dd31fSDavid Chisnall 169af0dd31fSDavid Chisnall /** 170af0dd31fSDavid Chisnall * String property checker. This checks that the property has exactly one 171af0dd31fSDavid Chisnall * value, which is a string. 172af0dd31fSDavid Chisnall */ 173af0dd31fSDavid Chisnall template<> 174af0dd31fSDavid Chisnall struct property_type_checker <property_value::STRING> : public property_checker 175af0dd31fSDavid Chisnall { property_type_checkerdtc::fdt::checking::property_type_checker176bbe31b70SEd Maste property_type_checker(const char* name, const std::string &property_name) : 177af0dd31fSDavid Chisnall property_checker(name, property_name) {} checkdtc::fdt::checking::property_type_checker178c64a3eafSDavid Chisnall virtual bool check(device_tree *, const node_ptr &, property_ptr p) 179af0dd31fSDavid Chisnall { 180af0dd31fSDavid Chisnall return (p->begin() + 1 == p->end()) && p->begin()->is_string(); 181af0dd31fSDavid Chisnall } 182af0dd31fSDavid Chisnall }; 183af0dd31fSDavid Chisnall /** 184af0dd31fSDavid Chisnall * String list property checker. This checks that the property has at least 185af0dd31fSDavid Chisnall * one value, all of which are strings. 186af0dd31fSDavid Chisnall */ 187af0dd31fSDavid Chisnall template<> 188af0dd31fSDavid Chisnall struct property_type_checker <property_value::STRING_LIST> : 189af0dd31fSDavid Chisnall public property_checker 190af0dd31fSDavid Chisnall { property_type_checkerdtc::fdt::checking::property_type_checker191bbe31b70SEd Maste property_type_checker(const char* name, const std::string &property_name) : 192af0dd31fSDavid Chisnall property_checker(name, property_name) {} checkdtc::fdt::checking::property_type_checker193c64a3eafSDavid Chisnall virtual bool check(device_tree *, const node_ptr &, property_ptr p) 194af0dd31fSDavid Chisnall { 195af0dd31fSDavid Chisnall for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; 196af0dd31fSDavid Chisnall ++i) 197af0dd31fSDavid Chisnall { 198af0dd31fSDavid Chisnall if (!(i->is_string() || i->is_string_list())) 199af0dd31fSDavid Chisnall { 200af0dd31fSDavid Chisnall return false; 201af0dd31fSDavid Chisnall } 202af0dd31fSDavid Chisnall } 203af0dd31fSDavid Chisnall return p->begin() != p->end(); 204af0dd31fSDavid Chisnall } 205af0dd31fSDavid Chisnall }; 206af0dd31fSDavid Chisnall 207af0dd31fSDavid Chisnall /** 208af0dd31fSDavid Chisnall * Phandle property checker. This checks that the property has exactly one 209af0dd31fSDavid Chisnall * value, which is a valid phandle. 210af0dd31fSDavid Chisnall */ 211af0dd31fSDavid Chisnall template<> 212af0dd31fSDavid Chisnall struct property_type_checker <property_value::PHANDLE> : public property_checker 213af0dd31fSDavid Chisnall { property_type_checkerdtc::fdt::checking::property_type_checker214bbe31b70SEd Maste property_type_checker(const char* name, const std::string &property_name) : 215af0dd31fSDavid Chisnall property_checker(name, property_name) {} checkdtc::fdt::checking::property_type_checker216c64a3eafSDavid Chisnall virtual bool check(device_tree *tree, const node_ptr &, property_ptr p) 217af0dd31fSDavid Chisnall { 218af0dd31fSDavid Chisnall return (p->begin() + 1 == p->end()) && 219af0dd31fSDavid Chisnall (tree->referenced_node(*p->begin()) != 0); 220af0dd31fSDavid Chisnall } 221af0dd31fSDavid Chisnall }; 222af0dd31fSDavid Chisnall 223af0dd31fSDavid Chisnall /** 224af0dd31fSDavid Chisnall * Check that a property has the correct size. 225af0dd31fSDavid Chisnall */ 226af0dd31fSDavid Chisnall struct property_size_checker : public property_checker 227af0dd31fSDavid Chisnall { 228af0dd31fSDavid Chisnall /** 229af0dd31fSDavid Chisnall * The expected size of the property. 230af0dd31fSDavid Chisnall */ 231af0dd31fSDavid Chisnall uint32_t size; 232af0dd31fSDavid Chisnall public: 233af0dd31fSDavid Chisnall /** 234af0dd31fSDavid Chisnall * Constructor, takes the name of the checker, the name of the property 235af0dd31fSDavid Chisnall * to check, and its expected size as arguments. 236af0dd31fSDavid Chisnall */ property_size_checkerdtc::fdt::checking::property_size_checker237bbe31b70SEd Maste property_size_checker(const char* name, 238bbe31b70SEd Maste const std::string &property_name, 239bbe31b70SEd Maste uint32_t bytes) 240af0dd31fSDavid Chisnall : property_checker(name, property_name), size(bytes) {} 241af0dd31fSDavid Chisnall /** 242af0dd31fSDavid Chisnall * Check, validates that the property has the correct size. 243af0dd31fSDavid Chisnall */ 244a0706eb4SDavid Chisnall virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p); 245af0dd31fSDavid Chisnall }; 246af0dd31fSDavid Chisnall 247af0dd31fSDavid Chisnall 248af0dd31fSDavid Chisnall /** 249af0dd31fSDavid Chisnall * The check manager is the interface to running the checks. This allows 250af0dd31fSDavid Chisnall * default checks to be enabled, non-default checks to be enabled, and so on. 251af0dd31fSDavid Chisnall */ 252af0dd31fSDavid Chisnall class check_manager 253af0dd31fSDavid Chisnall { 254af0dd31fSDavid Chisnall /** 255af0dd31fSDavid Chisnall * The enabled checkers, indexed by their names. The name is used when 256af0dd31fSDavid Chisnall * disabling checkers from the command line. When this manager runs, 257af0dd31fSDavid Chisnall * it will only run the checkers from this map. 258af0dd31fSDavid Chisnall */ 259bbe31b70SEd Maste std::unordered_map<std::string, checker*> checkers; 260af0dd31fSDavid Chisnall /** 261af0dd31fSDavid Chisnall * The disabled checkers. Moving checkers to this list disables them, 262af0dd31fSDavid Chisnall * but allows them to be easily moved back. 263af0dd31fSDavid Chisnall */ 264bbe31b70SEd Maste std::unordered_map<std::string, checker*> disabled_checkers; 265af0dd31fSDavid Chisnall /** 266af0dd31fSDavid Chisnall * Helper function for adding a property value checker. 267af0dd31fSDavid Chisnall */ 268af0dd31fSDavid Chisnall template<property_value::value_type T> 269bbe31b70SEd Maste void add_property_type_checker(const char *name, const std::string &prop); 270af0dd31fSDavid Chisnall /** 271af0dd31fSDavid Chisnall * Helper function for adding a simple type checker. 272af0dd31fSDavid Chisnall */ 273bbe31b70SEd Maste void add_property_type_checker(const char *name, const std::string &prop); 274af0dd31fSDavid Chisnall /** 275af0dd31fSDavid Chisnall * Helper function for adding a property value checker. 276af0dd31fSDavid Chisnall */ 277af0dd31fSDavid Chisnall void add_property_size_checker(const char *name, 278bbe31b70SEd Maste const std::string &prop, 279af0dd31fSDavid Chisnall uint32_t size); 280af0dd31fSDavid Chisnall public: 281af0dd31fSDavid Chisnall /** 282af0dd31fSDavid Chisnall * Delete all of the checkers that are part of this checker manager. 283af0dd31fSDavid Chisnall */ 284af0dd31fSDavid Chisnall ~check_manager(); 285af0dd31fSDavid Chisnall /** 286af0dd31fSDavid Chisnall * Default constructor, creates check manager containing all of the 287af0dd31fSDavid Chisnall * default checks. 288af0dd31fSDavid Chisnall */ 289af0dd31fSDavid Chisnall check_manager(); 290af0dd31fSDavid Chisnall /** 291af0dd31fSDavid Chisnall * Run all of the checks on the specified tree. 292af0dd31fSDavid Chisnall */ 293af0dd31fSDavid Chisnall bool run_checks(device_tree *tree, bool keep_going); 294af0dd31fSDavid Chisnall /** 295af0dd31fSDavid Chisnall * Disables the named checker. 296af0dd31fSDavid Chisnall */ 297bbe31b70SEd Maste bool disable_checker(const std::string &name); 298af0dd31fSDavid Chisnall /** 299af0dd31fSDavid Chisnall * Enables the named checker. 300af0dd31fSDavid Chisnall */ 301bbe31b70SEd Maste bool enable_checker(const std::string &name); 302af0dd31fSDavid Chisnall }; 303af0dd31fSDavid Chisnall 304af0dd31fSDavid Chisnall } // namespace checking 305af0dd31fSDavid Chisnall 306af0dd31fSDavid Chisnall } // namespace fdt 307af0dd31fSDavid Chisnall 308af0dd31fSDavid Chisnall } // namespace dtc 309af0dd31fSDavid Chisnall 310af0dd31fSDavid Chisnall #endif // !_CHECKING_HH_ 311