]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/checking.cc
Import libyaml as libbsdyml (private brand name)
[FreeBSD/FreeBSD.git] / usr.bin / dtc / checking.cc
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 #include "checking.hh"
34 #include <stdio.h>
35
36 namespace dtc
37 {
38 namespace fdt
39 {
40 namespace checking
41 {
42
43 bool
44 checker::visit_node(device_tree *tree, node *n)
45 {
46         path.push_back(std::make_pair(n->name, n->unit_address));
47         // Check this node
48         if (!check_node(tree, n))
49         {
50                 return false;
51         }
52         // Now check its properties
53         for (node::property_iterator i=n->property_begin(), e=n->property_end()
54              ; i!=e ; ++i)
55         {
56                 if (!check_property(tree, n, *i))
57                 {
58                         return false;
59                 }
60         }
61         // And then recursively check the children
62         for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ;
63              ++i)
64         {
65                 if (!visit_node(tree, *i))
66                 {
67                         return false;
68                 }
69         }
70         path.pop_back();
71         return true;
72 }
73
74 void
75 checker::report_error(const char *errmsg)
76 {
77         fprintf(stderr, "Error: %s, while checking node: ", errmsg);
78         for (device_tree::node_path::iterator p=path.begin()+1, pe=path.end() ;
79              p!=pe ; ++p)
80         {
81                 putc('/', stderr);
82                 p->first.dump();
83                 if (!(p->second.empty()))
84                 {
85                         putc('@', stderr);
86                         p->second.dump();
87                 }
88         }
89         fprintf(stderr, " [-W%s]\n", checker_name);
90 }
91
92 bool
93 property_checker::check_property(device_tree *tree, node *n, property *p)
94 {
95         if (p->get_key() == key)
96         {
97                 if (!check(tree, n, p))
98                 {
99                         report_error("property check failed");
100                         return false;
101                 }
102         }
103         return true;
104 }
105
106 bool
107 property_size_checker::check(device_tree *tree, node *n, property *p)
108 {
109         uint32_t psize = 0;
110         for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; ++i)
111         {
112                 if (!i->is_binary())
113                 {
114                         return false;
115                 }
116                 psize += i->byte_data.size();
117         }
118         return psize == size;
119 }
120
121 template<property_value::value_type T>
122 void
123 check_manager::add_property_type_checker(const char *name, string prop)
124 {
125         checkers.insert(std::make_pair(string(name),
126                 new property_type_checker<T>(name, prop)));
127 }
128
129 void
130 check_manager::add_property_size_checker(const char *name,
131                                          string prop,
132                                          uint32_t size)
133 {
134         checkers.insert(std::make_pair(string(name),
135                 new property_size_checker(name, prop, size)));
136 }
137
138 check_manager::~check_manager()
139 {
140         while (checkers.begin() != checkers.end())
141         {
142                 delete checkers.begin()->second;
143                 checkers.erase(checkers.begin());
144         }
145         while (disabled_checkers.begin() != disabled_checkers.end())
146         {
147                 delete disabled_checkers.begin()->second;
148         }
149 }
150
151 check_manager::check_manager()
152 {
153         // NOTE: All checks listed here MUST have a corresponding line
154         // in the man page!
155         add_property_type_checker<property_value::STRING_LIST>(
156                         "type-compatible", string("compatible"));
157         add_property_type_checker<property_value::STRING>(
158                         "type-model", string("model"));
159         add_property_size_checker("type-phandle", string("phandle"), 4);
160 }
161
162 bool
163 check_manager::run_checks(device_tree *tree, bool keep_going)
164 {
165         bool success = true;
166         for (std::map<string, checker*>::iterator i=checkers.begin(),
167              e=checkers.end() ; i!=e ; ++i)
168         {
169                 success &= i->second->check_tree(tree);
170                 if (!(success || keep_going))
171                 {
172                         break;
173                 }
174         }
175         return success;
176 }
177
178 bool
179 check_manager::disable_checker(string name)
180 {
181         std::map<string, checker*>::iterator checker = checkers.find(name);
182         if (checker != checkers.end())
183         {
184                 disabled_checkers.insert(std::make_pair(name,
185                                                         checker->second));
186                 checkers.erase(checker);
187                 return true;
188         }
189         return false;
190 }
191
192 bool
193 check_manager::enable_checker(string name)
194 {
195         std::map<string, checker*>::iterator checker =
196                 disabled_checkers.find(name);
197         if (checker != disabled_checkers.end())
198         {
199                 checkers.insert(std::make_pair(name, checker->second));
200                 disabled_checkers.erase(checker);
201                 return true;
202         }
203         return false;
204 }
205
206 } // namespace checking
207
208 } // namespace fdt
209
210 } // namespace dtc
211