]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.bin/dtc/checking.hh
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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.hh"
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, node *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 *tree, node *n)
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 *tree, node *n, property *p)
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         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  */
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, 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  */
158 template<>
159 struct 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  */
173 template<>
174 struct 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  */
187 template<>
188 struct 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  */
211 template<>
212 struct 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  */
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, 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  */
250 class 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_