]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/checking.hh
fdt: Expect strchr() to return a const char*
[FreeBSD/FreeBSD.git] / usr.bin / dtc / checking.hh
1 /*-
2  * Copyright (c) 2013 David Chisnall
3  * All rights reserved.
4  *
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.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
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.
17  *
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
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #ifndef _CHECKING_HH_
34 #define _CHECKING_HH_
35 #include <string>
36 #include "fdt.hh"
37
38 namespace dtc
39 {
40 namespace fdt
41 {
42 namespace checking
43 {
44 /**
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
49  * tree.
50  */
51 class checker
52 {
53         /**
54          * The path to the current node being checked.  This is used for
55          * printing error messages.
56          */
57         device_tree::node_path path;
58         /**
59          * The name of the checker.  This is used for printing error messages
60          * and for enabling / disabling specific checkers from the command
61          * line.
62          */
63         const char *checker_name;
64         /**
65          * Visits each node, calling the checker functions on properties and
66          * nodes.
67          */
68         bool visit_node(device_tree *tree, const node_ptr &n);
69         protected:
70         /**
71          * Prints the error message, along with the path to the node that
72          * caused the error and the name of the checker.
73          */
74         void report_error(const char *errmsg);
75         public:
76         /**
77          * Constructor.  Takes the name of this checker, which is which is used
78          * when reporting errors.
79          */
80         checker(const char *name) : checker_name(name) {}
81         /**
82          * Virtual destructor in case any subclasses need to do cleanup.
83          */
84         virtual ~checker() {}
85         /**
86          * Method for checking that a node is valid.  The root class version
87          * does nothing, subclasses should override this.
88          */
89         virtual bool check_node(device_tree *, const node_ptr &)
90         {
91                 return true;
92         }
93         /**
94          * Method for checking that a property is valid.  The root class
95          * version does nothing, subclasses should override this.
96          */
97         virtual bool check_property(device_tree *, const node_ptr &, property_ptr )
98         {
99                 return true;
100         }
101         /**
102          * Runs the checker on the specified device tree.
103          */
104         bool check_tree(fdt::device_tree *tree)
105         {
106                 return visit_node(tree, tree->get_root());
107         }
108 };
109
110 /**
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.
115  */
116 class property_checker : public checker
117 {
118         /**
119          * The name of the property that this checker is looking for.
120          */
121         std::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, const node_ptr &n, property_ptr 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, const std::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, const node_ptr &n, property_ptr p) = 0;
138 };
139
140 /**
141  * Property type checker.
142  */
143 template<property_value::value_type T>
144 struct 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, const std::string &property_name) :
151                 property_checker(name, property_name) {}
152         virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0;
153 };
154
155 /**
156  * Empty property checker.  This checks that the property has no value.
157  */
158 template<>
159 struct property_type_checker <property_value::EMPTY> : public property_checker
160 {
161         property_type_checker(const char* name, const std::string &property_name) :
162                 property_checker(name, property_name) {}
163         virtual bool check(device_tree *, const node_ptr &, property_ptr 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  */
173 template<>
174 struct property_type_checker <property_value::STRING> : public property_checker
175 {
176         property_type_checker(const char* name, const std::string &property_name) :
177                 property_checker(name, property_name) {}
178         virtual bool check(device_tree *, const node_ptr &, property_ptr 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  */
187 template<>
188 struct property_type_checker <property_value::STRING_LIST> :
189         public property_checker
190 {
191         property_type_checker(const char* name, const std::string &property_name) :
192                 property_checker(name, property_name) {}
193         virtual bool check(device_tree *, const node_ptr &, property_ptr 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  */
211 template<>
212 struct property_type_checker <property_value::PHANDLE> : public property_checker
213 {
214         property_type_checker(const char* name, const std::string &property_name) :
215                 property_checker(name, property_name) {}
216         virtual bool check(device_tree *tree, const node_ptr &, property_ptr 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  */
226 struct 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,
238                               const std::string &property_name,
239                               uint32_t bytes)
240                 : property_checker(name, property_name), size(bytes) {}
241         /**
242          * Check, validates that the property has the correct size.
243          */
244         virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p);
245 };
246
247
248 /**
249  * The check manager is the interface to running the checks.  This allows
250  * default checks to be enabled, non-default checks to be enabled, and so on.
251  */
252 class check_manager
253 {
254         /**
255          * The enabled checkers, indexed by their names.  The name is used when
256          * disabling checkers from the command line.  When this manager runs,
257          * it will only run the checkers from this map.
258          */
259         std::unordered_map<std::string, checker*> checkers;
260         /**
261          * The disabled checkers.  Moving checkers to this list disables them,
262          * but allows them to be easily moved back.
263          */
264         std::unordered_map<std::string, checker*> disabled_checkers;
265         /**
266          * Helper function for adding a property value checker.
267          */
268         template<property_value::value_type T>
269         void add_property_type_checker(const char *name, const std::string &prop);
270         /**
271          * Helper function for adding a simple type checker.
272          */
273         void add_property_type_checker(const char *name, const std::string &prop);
274         /**
275          * Helper function for adding a property value checker.
276          */
277         void add_property_size_checker(const char *name,
278                                        const std::string &prop,
279                                        uint32_t size);
280         public:
281         /**
282          * Delete all of the checkers that are part of this checker manager.
283          */
284         ~check_manager();
285         /**
286          * Default constructor, creates check manager containing all of the
287          * default checks.
288          */
289         check_manager();
290         /**
291          * Run all of the checks on the specified tree.
292          */
293         bool run_checks(device_tree *tree, bool keep_going);
294         /**
295          * Disables the named checker.
296          */
297         bool disable_checker(const std::string &name);
298         /**
299          * Enables the named checker.
300          */
301         bool enable_checker(const std::string &name);
302 };
303
304 } // namespace checking
305
306 } // namespace fdt
307
308 } // namespace dtc
309
310 #endif // !_CHECKING_HH_