xref: /aosp_15_r20/system/libufdt/ufdt_node.c (revision 13e8728f0cffde9369df671f7b293a048a99c7ed)
1*13e8728fSAndroid Build Coastguard Worker /*
2*13e8728fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*13e8728fSAndroid Build Coastguard Worker  *
4*13e8728fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*13e8728fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*13e8728fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*13e8728fSAndroid Build Coastguard Worker  *
8*13e8728fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*13e8728fSAndroid Build Coastguard Worker  *
10*13e8728fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*13e8728fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*13e8728fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*13e8728fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*13e8728fSAndroid Build Coastguard Worker  * limitations under the License.
15*13e8728fSAndroid Build Coastguard Worker  */
16*13e8728fSAndroid Build Coastguard Worker 
17*13e8728fSAndroid Build Coastguard Worker #include "libufdt.h"
18*13e8728fSAndroid Build Coastguard Worker 
19*13e8728fSAndroid Build Coastguard Worker #include "ufdt_node_pool.h"
20*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_construct(void * fdtp,fdt32_t * fdt_tag_ptr,struct ufdt_node_pool * pool)21*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_construct(void *fdtp, fdt32_t *fdt_tag_ptr,
22*13e8728fSAndroid Build Coastguard Worker                                       struct ufdt_node_pool *pool) {
23*13e8728fSAndroid Build Coastguard Worker   void *buf = ufdt_node_pool_alloc(pool);
24*13e8728fSAndroid Build Coastguard Worker   uint32_t tag = fdt32_to_cpu(*fdt_tag_ptr);
25*13e8728fSAndroid Build Coastguard Worker   if (tag == FDT_PROP) {
26*13e8728fSAndroid Build Coastguard Worker     const struct fdt_property *prop = (const struct fdt_property *)fdt_tag_ptr;
27*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node_fdt_prop *res = (struct ufdt_node_fdt_prop *)buf;
28*13e8728fSAndroid Build Coastguard Worker     if (res == NULL) return NULL;
29*13e8728fSAndroid Build Coastguard Worker     res->parent.fdt_tag_ptr = fdt_tag_ptr;
30*13e8728fSAndroid Build Coastguard Worker     res->parent.sibling = NULL;
31*13e8728fSAndroid Build Coastguard Worker     res->name = fdt_string(fdtp, fdt32_to_cpu(prop->nameoff));
32*13e8728fSAndroid Build Coastguard Worker 
33*13e8728fSAndroid Build Coastguard Worker     /* fdt_string() may fail */
34*13e8728fSAndroid Build Coastguard Worker     if (!res->name) {
35*13e8728fSAndroid Build Coastguard Worker       dto_error("Failed to get property name\n");
36*13e8728fSAndroid Build Coastguard Worker       ufdt_node_pool_free(pool, res);
37*13e8728fSAndroid Build Coastguard Worker       res = NULL;
38*13e8728fSAndroid Build Coastguard Worker     }
39*13e8728fSAndroid Build Coastguard Worker 
40*13e8728fSAndroid Build Coastguard Worker     return (struct ufdt_node *)res;
41*13e8728fSAndroid Build Coastguard Worker   } else {
42*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node_fdt_node *res = (struct ufdt_node_fdt_node *)buf;
43*13e8728fSAndroid Build Coastguard Worker     if (res == NULL) return NULL;
44*13e8728fSAndroid Build Coastguard Worker     res->parent.fdt_tag_ptr = fdt_tag_ptr;
45*13e8728fSAndroid Build Coastguard Worker     res->parent.sibling = NULL;
46*13e8728fSAndroid Build Coastguard Worker     res->child = NULL;
47*13e8728fSAndroid Build Coastguard Worker     res->last_child_p = &res->child;
48*13e8728fSAndroid Build Coastguard Worker     return (struct ufdt_node *)res;
49*13e8728fSAndroid Build Coastguard Worker   }
50*13e8728fSAndroid Build Coastguard Worker }
51*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_destruct(struct ufdt_node * node,struct ufdt_node_pool * pool)52*13e8728fSAndroid Build Coastguard Worker void ufdt_node_destruct(struct ufdt_node *node, struct ufdt_node_pool *pool) {
53*13e8728fSAndroid Build Coastguard Worker   if (node == NULL) return;
54*13e8728fSAndroid Build Coastguard Worker 
55*13e8728fSAndroid Build Coastguard Worker   if (ufdt_node_tag(node) == FDT_BEGIN_NODE) {
56*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node *it = ((struct ufdt_node_fdt_node *)node)->child;
57*13e8728fSAndroid Build Coastguard Worker     while (it != NULL) {
58*13e8728fSAndroid Build Coastguard Worker       struct ufdt_node *next = it->sibling;
59*13e8728fSAndroid Build Coastguard Worker       ufdt_node_destruct(it, pool);
60*13e8728fSAndroid Build Coastguard Worker       it = next;
61*13e8728fSAndroid Build Coastguard Worker     }
62*13e8728fSAndroid Build Coastguard Worker   }
63*13e8728fSAndroid Build Coastguard Worker 
64*13e8728fSAndroid Build Coastguard Worker   ufdt_node_pool_free(pool, node);
65*13e8728fSAndroid Build Coastguard Worker }
66*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_add_child(struct ufdt_node * parent,struct ufdt_node * child)67*13e8728fSAndroid Build Coastguard Worker int ufdt_node_add_child(struct ufdt_node *parent, struct ufdt_node *child) {
68*13e8728fSAndroid Build Coastguard Worker   if (!parent || !child) return -1;
69*13e8728fSAndroid Build Coastguard Worker   if (ufdt_node_tag(parent) != FDT_BEGIN_NODE) return -1;
70*13e8728fSAndroid Build Coastguard Worker 
71*13e8728fSAndroid Build Coastguard Worker   int err = 0;
72*13e8728fSAndroid Build Coastguard Worker   uint32_t child_tag = ufdt_node_tag(child);
73*13e8728fSAndroid Build Coastguard Worker   switch (child_tag) {
74*13e8728fSAndroid Build Coastguard Worker     case FDT_PROP:
75*13e8728fSAndroid Build Coastguard Worker     case FDT_BEGIN_NODE:
76*13e8728fSAndroid Build Coastguard Worker       // Append the child node to the last child of parant node
77*13e8728fSAndroid Build Coastguard Worker       *((struct ufdt_node_fdt_node *)parent)->last_child_p = child;
78*13e8728fSAndroid Build Coastguard Worker       ((struct ufdt_node_fdt_node *)parent)->last_child_p = &child->sibling;
79*13e8728fSAndroid Build Coastguard Worker       break;
80*13e8728fSAndroid Build Coastguard Worker 
81*13e8728fSAndroid Build Coastguard Worker     default:
82*13e8728fSAndroid Build Coastguard Worker       err = -1;
83*13e8728fSAndroid Build Coastguard Worker       dto_error("invalid children tag type\n");
84*13e8728fSAndroid Build Coastguard Worker   }
85*13e8728fSAndroid Build Coastguard Worker 
86*13e8728fSAndroid Build Coastguard Worker   return err;
87*13e8728fSAndroid Build Coastguard Worker }
88*13e8728fSAndroid Build Coastguard Worker 
89*13e8728fSAndroid Build Coastguard Worker /*
90*13e8728fSAndroid Build Coastguard Worker  * BEGIN of FDT_PROP related methods.
91*13e8728fSAndroid Build Coastguard Worker  */
92*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_subnode_by_name_len(const struct ufdt_node * node,const char * name,int len)93*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_get_subnode_by_name_len(const struct ufdt_node *node,
94*13e8728fSAndroid Build Coastguard Worker                                                   const char *name, int len) {
95*13e8728fSAndroid Build Coastguard Worker   struct ufdt_node **it = NULL;
96*13e8728fSAndroid Build Coastguard Worker   for_each_node(it, node) {
97*13e8728fSAndroid Build Coastguard Worker     if (ufdt_node_name_eq(*it, name, len)) return *it;
98*13e8728fSAndroid Build Coastguard Worker   }
99*13e8728fSAndroid Build Coastguard Worker   return NULL;
100*13e8728fSAndroid Build Coastguard Worker }
101*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_subnode_by_name(const struct ufdt_node * node,const char * name)102*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_get_subnode_by_name(const struct ufdt_node *node,
103*13e8728fSAndroid Build Coastguard Worker                                               const char *name) {
104*13e8728fSAndroid Build Coastguard Worker   return ufdt_node_get_subnode_by_name_len(node, name, strlen(name));
105*13e8728fSAndroid Build Coastguard Worker }
106*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_property_by_name_len(const struct ufdt_node * node,const char * name,int len)107*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_get_property_by_name_len(
108*13e8728fSAndroid Build Coastguard Worker     const struct ufdt_node *node, const char *name, int len) {
109*13e8728fSAndroid Build Coastguard Worker   if (!node) return NULL;
110*13e8728fSAndroid Build Coastguard Worker 
111*13e8728fSAndroid Build Coastguard Worker   struct ufdt_node **it = NULL;
112*13e8728fSAndroid Build Coastguard Worker   for_each_prop(it, node) {
113*13e8728fSAndroid Build Coastguard Worker     if (ufdt_node_name_eq(*it, name, len)) return *it;
114*13e8728fSAndroid Build Coastguard Worker   }
115*13e8728fSAndroid Build Coastguard Worker   return NULL;
116*13e8728fSAndroid Build Coastguard Worker }
117*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_property_by_name(const struct ufdt_node * node,const char * name)118*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_get_property_by_name(const struct ufdt_node *node,
119*13e8728fSAndroid Build Coastguard Worker                                                  const char *name) {
120*13e8728fSAndroid Build Coastguard Worker   return ufdt_node_get_property_by_name_len(node, name, dto_strlen(name));
121*13e8728fSAndroid Build Coastguard Worker }
122*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_fdt_prop_data(const struct ufdt_node * node,int * out_len)123*13e8728fSAndroid Build Coastguard Worker char *ufdt_node_get_fdt_prop_data(const struct ufdt_node *node, int *out_len) {
124*13e8728fSAndroid Build Coastguard Worker   if (!node || ufdt_node_tag(node) != FDT_PROP) {
125*13e8728fSAndroid Build Coastguard Worker     return NULL;
126*13e8728fSAndroid Build Coastguard Worker   }
127*13e8728fSAndroid Build Coastguard Worker   const struct fdt_property *prop = (struct fdt_property *)node->fdt_tag_ptr;
128*13e8728fSAndroid Build Coastguard Worker   if (out_len != NULL) {
129*13e8728fSAndroid Build Coastguard Worker     uint32_t prop_len = fdt32_to_cpu(prop->len);
130*13e8728fSAndroid Build Coastguard Worker 
131*13e8728fSAndroid Build Coastguard Worker     if (prop_len > INT_MAX) {
132*13e8728fSAndroid Build Coastguard Worker       return NULL;
133*13e8728fSAndroid Build Coastguard Worker     }
134*13e8728fSAndroid Build Coastguard Worker 
135*13e8728fSAndroid Build Coastguard Worker     *out_len = prop_len;
136*13e8728fSAndroid Build Coastguard Worker   }
137*13e8728fSAndroid Build Coastguard Worker   return (char *)prop->data;
138*13e8728fSAndroid Build Coastguard Worker }
139*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_fdt_prop_data_by_name_len(const struct ufdt_node * node,const char * name,int len,int * out_len)140*13e8728fSAndroid Build Coastguard Worker char *ufdt_node_get_fdt_prop_data_by_name_len(const struct ufdt_node *node,
141*13e8728fSAndroid Build Coastguard Worker                                               const char *name, int len,
142*13e8728fSAndroid Build Coastguard Worker                                               int *out_len) {
143*13e8728fSAndroid Build Coastguard Worker   return ufdt_node_get_fdt_prop_data(
144*13e8728fSAndroid Build Coastguard Worker       ufdt_node_get_property_by_name_len(node, name, len), out_len);
145*13e8728fSAndroid Build Coastguard Worker }
146*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_fdt_prop_data_by_name(const struct ufdt_node * node,const char * name,int * out_len)147*13e8728fSAndroid Build Coastguard Worker char *ufdt_node_get_fdt_prop_data_by_name(const struct ufdt_node *node,
148*13e8728fSAndroid Build Coastguard Worker                                           const char *name, int *out_len) {
149*13e8728fSAndroid Build Coastguard Worker   return ufdt_node_get_fdt_prop_data(ufdt_node_get_property_by_name(node, name),
150*13e8728fSAndroid Build Coastguard Worker                                      out_len);
151*13e8728fSAndroid Build Coastguard Worker }
152*13e8728fSAndroid Build Coastguard Worker 
153*13e8728fSAndroid Build Coastguard Worker /*
154*13e8728fSAndroid Build Coastguard Worker  * END of FDT_PROP related methods.
155*13e8728fSAndroid Build Coastguard Worker  */
156*13e8728fSAndroid Build Coastguard Worker 
157*13e8728fSAndroid Build Coastguard Worker /*
158*13e8728fSAndroid Build Coastguard Worker  * BEGIN of searching-in-ufdt_node methods.
159*13e8728fSAndroid Build Coastguard Worker  */
160*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_phandle(const struct ufdt_node * node)161*13e8728fSAndroid Build Coastguard Worker uint32_t ufdt_node_get_phandle(const struct ufdt_node *node) {
162*13e8728fSAndroid Build Coastguard Worker   if (!node || ufdt_node_tag(node) != FDT_BEGIN_NODE) {
163*13e8728fSAndroid Build Coastguard Worker     return 0;
164*13e8728fSAndroid Build Coastguard Worker   }
165*13e8728fSAndroid Build Coastguard Worker   int len = 0;
166*13e8728fSAndroid Build Coastguard Worker   void *ptr = ufdt_node_get_fdt_prop_data_by_name(node, "phandle", &len);
167*13e8728fSAndroid Build Coastguard Worker   if (!ptr || len != sizeof(fdt32_t)) {
168*13e8728fSAndroid Build Coastguard Worker     ptr = ufdt_node_get_fdt_prop_data_by_name(node, "linux,phandle", &len);
169*13e8728fSAndroid Build Coastguard Worker     if (!ptr || len != sizeof(fdt32_t)) {
170*13e8728fSAndroid Build Coastguard Worker       return 0;
171*13e8728fSAndroid Build Coastguard Worker     }
172*13e8728fSAndroid Build Coastguard Worker   }
173*13e8728fSAndroid Build Coastguard Worker   return fdt32_to_cpu(*((fdt32_t *)ptr));
174*13e8728fSAndroid Build Coastguard Worker }
175*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_node_by_path_len(const struct ufdt_node * node,const char * path,int len)176*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_get_node_by_path_len(const struct ufdt_node *node,
177*13e8728fSAndroid Build Coastguard Worker                                                  const char *path, int len) {
178*13e8728fSAndroid Build Coastguard Worker   const char *end = path + len;
179*13e8728fSAndroid Build Coastguard Worker 
180*13e8728fSAndroid Build Coastguard Worker   struct ufdt_node *cur = (struct ufdt_node *)node;
181*13e8728fSAndroid Build Coastguard Worker 
182*13e8728fSAndroid Build Coastguard Worker   while (path < end) {
183*13e8728fSAndroid Build Coastguard Worker     while (path[0] == '/') path++;
184*13e8728fSAndroid Build Coastguard Worker     if (path == end) return cur;
185*13e8728fSAndroid Build Coastguard Worker 
186*13e8728fSAndroid Build Coastguard Worker     const char *next_slash;
187*13e8728fSAndroid Build Coastguard Worker     next_slash = dto_memchr(path, '/', end - path);
188*13e8728fSAndroid Build Coastguard Worker     if (!next_slash) next_slash = end;
189*13e8728fSAndroid Build Coastguard Worker 
190*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node *next = NULL;
191*13e8728fSAndroid Build Coastguard Worker 
192*13e8728fSAndroid Build Coastguard Worker     next = ufdt_node_get_subnode_by_name_len(cur, path, next_slash - path);
193*13e8728fSAndroid Build Coastguard Worker 
194*13e8728fSAndroid Build Coastguard Worker     cur = next;
195*13e8728fSAndroid Build Coastguard Worker     path = next_slash;
196*13e8728fSAndroid Build Coastguard Worker     if (!cur) return cur;
197*13e8728fSAndroid Build Coastguard Worker   }
198*13e8728fSAndroid Build Coastguard Worker 
199*13e8728fSAndroid Build Coastguard Worker   return cur;
200*13e8728fSAndroid Build Coastguard Worker }
201*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_get_node_by_path(const struct ufdt_node * node,const char * path)202*13e8728fSAndroid Build Coastguard Worker struct ufdt_node *ufdt_node_get_node_by_path(const struct ufdt_node *node,
203*13e8728fSAndroid Build Coastguard Worker                                              const char *path) {
204*13e8728fSAndroid Build Coastguard Worker   return ufdt_node_get_node_by_path_len(node, path, dto_strlen(path));
205*13e8728fSAndroid Build Coastguard Worker }
206*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_name_eq(const struct ufdt_node * node,const char * name,int len)207*13e8728fSAndroid Build Coastguard Worker bool ufdt_node_name_eq(const struct ufdt_node *node, const char *name, int len) {
208*13e8728fSAndroid Build Coastguard Worker   if (!node) return false;
209*13e8728fSAndroid Build Coastguard Worker   if (!name) return false;
210*13e8728fSAndroid Build Coastguard Worker   if (dto_strncmp(ufdt_node_name(node), name, len) != 0) return false;
211*13e8728fSAndroid Build Coastguard Worker   if (ufdt_node_name(node)[len] != '\0') return false;
212*13e8728fSAndroid Build Coastguard Worker   return true;
213*13e8728fSAndroid Build Coastguard Worker }
214*13e8728fSAndroid Build Coastguard Worker 
215*13e8728fSAndroid Build Coastguard Worker /*
216*13e8728fSAndroid Build Coastguard Worker  * END of searching-in-ufdt_node methods.
217*13e8728fSAndroid Build Coastguard Worker  */
218*13e8728fSAndroid Build Coastguard Worker 
merge_children(struct ufdt_node * node_a,struct ufdt_node * node_b,struct ufdt_node_pool * pool)219*13e8728fSAndroid Build Coastguard Worker static int merge_children(struct ufdt_node *node_a, struct ufdt_node *node_b,
220*13e8728fSAndroid Build Coastguard Worker                           struct ufdt_node_pool *pool) {
221*13e8728fSAndroid Build Coastguard Worker   int err = 0;
222*13e8728fSAndroid Build Coastguard Worker   struct ufdt_node *it;
223*13e8728fSAndroid Build Coastguard Worker   for (it = ((struct ufdt_node_fdt_node *)node_b)->child; it;) {
224*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node *cur_node = it;
225*13e8728fSAndroid Build Coastguard Worker     it = it->sibling;
226*13e8728fSAndroid Build Coastguard Worker     cur_node->sibling = NULL;
227*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node *target_node = NULL;
228*13e8728fSAndroid Build Coastguard Worker     if (ufdt_node_tag(cur_node) == FDT_BEGIN_NODE) {
229*13e8728fSAndroid Build Coastguard Worker       target_node =
230*13e8728fSAndroid Build Coastguard Worker           ufdt_node_get_subnode_by_name(node_a, ufdt_node_name(cur_node));
231*13e8728fSAndroid Build Coastguard Worker     } else {
232*13e8728fSAndroid Build Coastguard Worker       target_node =
233*13e8728fSAndroid Build Coastguard Worker           ufdt_node_get_property_by_name(node_a, ufdt_node_name(cur_node));
234*13e8728fSAndroid Build Coastguard Worker     }
235*13e8728fSAndroid Build Coastguard Worker     if (target_node == NULL) {
236*13e8728fSAndroid Build Coastguard Worker       err = ufdt_node_add_child(node_a, cur_node);
237*13e8728fSAndroid Build Coastguard Worker     } else {
238*13e8728fSAndroid Build Coastguard Worker       err = ufdt_node_merge_into(target_node, cur_node, pool);
239*13e8728fSAndroid Build Coastguard Worker       ufdt_node_pool_free(pool, cur_node);
240*13e8728fSAndroid Build Coastguard Worker     }
241*13e8728fSAndroid Build Coastguard Worker     if (err < 0) return -1;
242*13e8728fSAndroid Build Coastguard Worker   }
243*13e8728fSAndroid Build Coastguard Worker   /*
244*13e8728fSAndroid Build Coastguard Worker    * The ufdt_node* in node_b will be copied to node_a.
245*13e8728fSAndroid Build Coastguard Worker    * To prevent the ufdt_node from being freed twice
246*13e8728fSAndroid Build Coastguard Worker    * (main_tree and overlay_tree) at the end of function
247*13e8728fSAndroid Build Coastguard Worker    * ufdt_apply_overlay(), set this node in node_b
248*13e8728fSAndroid Build Coastguard Worker    * (overlay_tree) to NULL.
249*13e8728fSAndroid Build Coastguard Worker    */
250*13e8728fSAndroid Build Coastguard Worker   ((struct ufdt_node_fdt_node *)node_b)->child = NULL;
251*13e8728fSAndroid Build Coastguard Worker 
252*13e8728fSAndroid Build Coastguard Worker   return 0;
253*13e8728fSAndroid Build Coastguard Worker }
254*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_merge_into(struct ufdt_node * node_a,struct ufdt_node * node_b,struct ufdt_node_pool * pool)255*13e8728fSAndroid Build Coastguard Worker int ufdt_node_merge_into(struct ufdt_node *node_a, struct ufdt_node *node_b,
256*13e8728fSAndroid Build Coastguard Worker                          struct ufdt_node_pool *pool) {
257*13e8728fSAndroid Build Coastguard Worker   if (ufdt_node_tag(node_a) == FDT_PROP) {
258*13e8728fSAndroid Build Coastguard Worker     node_a->fdt_tag_ptr = node_b->fdt_tag_ptr;
259*13e8728fSAndroid Build Coastguard Worker     return 0;
260*13e8728fSAndroid Build Coastguard Worker   }
261*13e8728fSAndroid Build Coastguard Worker 
262*13e8728fSAndroid Build Coastguard Worker   int err = 0;
263*13e8728fSAndroid Build Coastguard Worker   err = merge_children(node_a, node_b, pool);
264*13e8728fSAndroid Build Coastguard Worker   if (err < 0) return -1;
265*13e8728fSAndroid Build Coastguard Worker 
266*13e8728fSAndroid Build Coastguard Worker   return 0;
267*13e8728fSAndroid Build Coastguard Worker }
268*13e8728fSAndroid Build Coastguard Worker 
269*13e8728fSAndroid Build Coastguard Worker #define TAB_SIZE 2
270*13e8728fSAndroid Build Coastguard Worker 
ufdt_node_print(const struct ufdt_node * node,int depth)271*13e8728fSAndroid Build Coastguard Worker void ufdt_node_print(const struct ufdt_node *node, int depth) {
272*13e8728fSAndroid Build Coastguard Worker   if (!node) return;
273*13e8728fSAndroid Build Coastguard Worker 
274*13e8728fSAndroid Build Coastguard Worker   int i;
275*13e8728fSAndroid Build Coastguard Worker   for (i = 0; i < depth * TAB_SIZE; i++) dto_print(" ");
276*13e8728fSAndroid Build Coastguard Worker 
277*13e8728fSAndroid Build Coastguard Worker   uint32_t tag;
278*13e8728fSAndroid Build Coastguard Worker   tag = ufdt_node_tag(node);
279*13e8728fSAndroid Build Coastguard Worker 
280*13e8728fSAndroid Build Coastguard Worker   switch (tag) {
281*13e8728fSAndroid Build Coastguard Worker     case FDT_BEGIN_NODE:
282*13e8728fSAndroid Build Coastguard Worker       dto_print("NODE ");
283*13e8728fSAndroid Build Coastguard Worker       break;
284*13e8728fSAndroid Build Coastguard Worker     case FDT_PROP:
285*13e8728fSAndroid Build Coastguard Worker       dto_print("PROP ");
286*13e8728fSAndroid Build Coastguard Worker       break;
287*13e8728fSAndroid Build Coastguard Worker     default:
288*13e8728fSAndroid Build Coastguard Worker       dto_print("UNKNOWN ");
289*13e8728fSAndroid Build Coastguard Worker       break;
290*13e8728fSAndroid Build Coastguard Worker   }
291*13e8728fSAndroid Build Coastguard Worker 
292*13e8728fSAndroid Build Coastguard Worker   if (ufdt_node_name(node)) {
293*13e8728fSAndroid Build Coastguard Worker     dto_print(":%s:\n", ufdt_node_name(node));
294*13e8728fSAndroid Build Coastguard Worker   } else {
295*13e8728fSAndroid Build Coastguard Worker     dto_print("node name is NULL.\n");
296*13e8728fSAndroid Build Coastguard Worker   }
297*13e8728fSAndroid Build Coastguard Worker 
298*13e8728fSAndroid Build Coastguard Worker   if (ufdt_node_tag(node) == FDT_BEGIN_NODE) {
299*13e8728fSAndroid Build Coastguard Worker     struct ufdt_node **it;
300*13e8728fSAndroid Build Coastguard Worker 
301*13e8728fSAndroid Build Coastguard Worker     for_each_prop(it, node) ufdt_node_print(*it, depth + 1);
302*13e8728fSAndroid Build Coastguard Worker 
303*13e8728fSAndroid Build Coastguard Worker     for_each_node(it, node) ufdt_node_print(*it, depth + 1);
304*13e8728fSAndroid Build Coastguard Worker   }
305*13e8728fSAndroid Build Coastguard Worker }
306