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