1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBUFDT_H 18 #define LIBUFDT_H 19 20 #include "libufdt_sysdeps.h" 21 #include "ufdt_types.h" 22 23 /* 24 * BEGIN of ufdt_node methods 25 */ 26 27 /* 28 * Allocates spaces for new ufdt_node who represents a fdt node at fdt_tag_ptr. 29 * In order to get name pointer, it's necessary to give the pointer to the 30 * entire fdt it belongs to. 31 * 32 * 33 * @return: a pointer to the newly created ufdt_node or 34 * NULL if dto_malloc failed 35 */ 36 struct ufdt_node *ufdt_node_construct(void *fdtp, fdt32_t *fdt_tag_ptr, 37 struct ufdt_node_pool *pool); 38 39 /* 40 * Frees all nodes in the subtree rooted at *node. 41 */ 42 void ufdt_node_destruct(struct ufdt_node *node, struct ufdt_node_pool *pool); 43 44 /* 45 * Adds the child as a subnode of the parent. 46 * It's been done by add entries in parent->prop_list or node_list depending on 47 * the tag type of child. 48 * 49 * @return: 0 if success 50 * < 0 otherwise 51 * 52 * @Time: O(1) w.h.p. 53 */ 54 int ufdt_node_add_child(struct ufdt_node *parent, struct ufdt_node *child); 55 56 /* BEGIN of FDT_PROP related functions .*/ 57 58 /* 59 * Gets pointer to FDT_PROP subnode of node with name equals to name[0..len-1] 60 * 61 * @return: a pointer to the subnode or 62 * NULL if no such subnode. 63 * 64 * @Time: O(len = length of name) w.h.p. 65 */ 66 struct ufdt_node *ufdt_node_get_property_by_name_len( 67 const struct ufdt_node *node, const char *name, int len); 68 struct ufdt_node *ufdt_node_get_property_by_name(const struct ufdt_node *node, 69 const char *name); 70 71 /* 72 * Gets the pointer to the FDT_PROP node's data in the corresponding fdt. 73 * Also writes the length of such data to *out_len if out_len is not NULL. 74 * 75 * @return: a pointer to some data located in fdt or 76 * NULL if *node is not a FDT_PROP 77 */ 78 char *ufdt_node_get_fdt_prop_data(const struct ufdt_node *node, int *out_len); 79 80 /* 81 * Gets pointer to FDT_PROP node's data in fdt with name equals to 82 * name[0..len-1], which is a subnode of *node. 83 * It's actually a composition of ufdt_node_get_property_by_name and 84 * ufdt_node_get_fdt_prop_data 85 * 86 * @return: a pointer to some data located in fdt or 87 * NULL if no such subnode. 88 * 89 * @Time: O(len = length of name) w.h.p. 90 */ 91 char *ufdt_node_get_fdt_prop_data_by_name_len(const struct ufdt_node *node, 92 const char *name, int len, 93 int *out_len); 94 char *ufdt_node_get_fdt_prop_data_by_name(const struct ufdt_node *node, 95 const char *name, int *out_len); 96 97 /* END of FDT_PROP related functions .*/ 98 99 /* 100 * Gets pointer to FDT_BEGIN_NODE subnode of node with name equals to 101 * name[0..len-1]. 102 * 103 * @return: a pointer to the subnode or 104 * NULL if no such subnode. 105 * 106 * @Time: O(len = length of name) w.h.p. 107 */ 108 109 struct ufdt_node *ufdt_node_get_subnode_by_name_len(const struct ufdt_node *node, 110 const char *name, int len); 111 struct ufdt_node *ufdt_node_get_subnode_by_name(const struct ufdt_node *node, 112 const char *name); 113 114 /* 115 * Gets the pointer to FDT_NODE node whose relative path to *node is 116 * path[0..len-1]. 117 * Note that the relative path doesn't support parent node like: 118 * "../path/to/node". 119 * 120 * @return: a pointer to the node or 121 * NULL if no such node. 122 * 123 * @Time: O(len = length of path) w.h.p. 124 */ 125 struct ufdt_node *ufdt_node_get_node_by_path_len(const struct ufdt_node *node, 126 const char *path, int len); 127 struct ufdt_node *ufdt_node_get_node_by_path(const struct ufdt_node *node, 128 const char *path); 129 130 /* 131 * Gets the phandle value of the node if it has. 132 * 133 * @return: phandle value of that node or 134 * 0 if *node is not FDT_NODE or there's no "phandle"/"linux,phandle" 135 * property. 136 * 137 * @Time: O(1) w.h.p. 138 */ 139 uint32_t ufdt_node_get_phandle(const struct ufdt_node *node); 140 141 /* 142 * END of ufdt_node methods 143 */ 144 145 /* 146 * BEGIN of ufdt methods. 147 */ 148 149 /* 150 * Constructs a ufdt whose base fdt is fdtp. 151 * Note that this function doesn't construct the entire tree. 152 * To get the whole tree please call `ufdt_from_fdt(fdtp, fdt_size)` 153 * 154 * @return: an empty ufdt with base fdtp = fdtp 155 */ 156 struct ufdt *ufdt_construct(void *fdtp, struct ufdt_node_pool *pool); 157 158 /* 159 * Frees the space occupied by the ufdt, including all ufdt_nodes 160 * with ufdt_static_phandle_table. 161 */ 162 void ufdt_destruct(struct ufdt *tree, struct ufdt_node_pool *pool); 163 164 /* 165 * Add a fdt into this ufdt. 166 * Note that this function just add the given fdtp into this ufdt, 167 * and doesn't create any node. 168 * 169 * @return: 0 if success. 170 */ 171 int ufdt_add_fdt(struct ufdt *tree, void *fdtp); 172 173 /* 174 * Calculate the offset in the string tables of the given string. 175 * All string tables will be concatenated in reversed order. 176 * 177 * @return: The offset is a negative number, base on the end position of 178 * all concatenated string tables 179 * Return 0 if not in any string table. 180 */ 181 int ufdt_get_string_off(const struct ufdt *tree, const char *s); 182 183 /* 184 * Gets the pointer to the ufdt_node in tree with phandle = phandle. 185 * The function do a binary search in tree->phandle_table. 186 * 187 * @return: a pointer to the target ufdt_node 188 * NULL if no ufdt_node has phandle = phandle 189 * 190 * @Time: O(log(# of nodes in tree)) = O(log(size of underlying fdt)) 191 */ 192 struct ufdt_node *ufdt_get_node_by_phandle(struct ufdt *tree, uint32_t phandle); 193 194 /* 195 * Gets the pointer to the ufdt_node in tree with absolute path = 196 * path[0..len-1]. 197 * Absolute path has form "/path/to/node" or "some_alias/to/node". 198 * In later example, some_alias is a property in "/aliases" with data is a path 199 * to some node X. Then the funcion will return node with relative 200 * path = "to/node" w.r.t. X. 201 * 202 * @return: a pointer to the target ufdt_node or 203 * NULL if such dnt doesn't exist. 204 * 205 * @Time: O(len = length of path) w.h.p. 206 */ 207 struct ufdt_node *ufdt_get_node_by_path_len(struct ufdt *tree, const char *path, 208 int len); 209 struct ufdt_node *ufdt_get_node_by_path(struct ufdt *tree, const char *path); 210 211 /* 212 * Determines whether node->name equals to name[0..len-1] 213 * 214 * @return: true if they're equal. 215 * false otherwise 216 */ 217 bool ufdt_node_name_eq(const struct ufdt_node *node, const char *name, int len); 218 219 /* 220 * Merges tree_b into tree_a with tree_b has all nodes except root disappeared. 221 * Overwrite property in tree_a if there's one with same name in tree_b. 222 * Otherwise add the property to tree_a. 223 * For subnodes with the same name, recursively run this function. 224 * 225 * Ex: 226 * tree_a : ta { 227 * b = "b"; 228 * c = "c"; 229 * d { 230 * e = "g"; 231 * }; 232 * }; 233 * 234 * tree_b : tb { 235 * c = "C"; 236 * g = "G"; 237 * d { 238 * da = "dad"; 239 * }; 240 * h { 241 * hh = "HH"; 242 * }; 243 * }; 244 * 245 * The resulting trees will be: 246 * 247 * tree_a : ta { 248 * b = "b"; 249 * c = "C"; 250 * g = "G"; 251 * d { 252 * da = "dad"; 253 * e = "g"; 254 * }; 255 * h { 256 * hh = "HH"; 257 * }; 258 * }; 259 * 260 * tree_b : tb { 261 * }; 262 * 263 * 264 * @return: 0 if merge success 265 * < 0 otherwise 266 * 267 * @Time: O(# of nodes in tree_b + total length of all names in tree_b) w.h.p. 268 */ 269 int ufdt_node_merge_into(struct ufdt_node *node_a, struct ufdt_node *node_b, 270 struct ufdt_node_pool *pool); 271 272 /* 273 * END of ufdt methods. 274 */ 275 276 /* 277 * BEGIN of ufdt output functions 278 */ 279 280 /* 281 * Builds the ufdt for FDT pointed by fdtp. 282 * 283 * @return: the ufdt T representing fdtp or 284 * T with T.fdtp == NULL if fdtp is unvalid. 285 * 286 * @Time: O(fdt_size + nlogn) where n = # of nodes in fdt. 287 */ 288 struct ufdt *ufdt_from_fdt(void *fdtp, size_t fdt_size, 289 struct ufdt_node_pool *pool); 290 291 /* 292 * Sequentially dumps the whole ufdt to FDT buffer fdtp with buffer size 293 * buf_size. 294 * 295 * Basically using functions provided by libfdt/fdt_sw.c. 296 * 297 * @return: 0 if successfully dump or 298 * < 0 otherwise 299 * 300 * @Time: O(total length of all names + # of nodes in tree) 301 */ 302 int ufdt_to_fdt(const struct ufdt *tree, void *buf, int buf_size); 303 304 /* 305 * prints the entire subtree rooted at *node in form: 306 * NODE :[node name]: 307 * PROP :[prop name]: 308 * ... 309 * NODE :[subnode1 name]: 310 * ... 311 * NODE :[subnode1 name]: 312 * ... 313 * ... 314 * There're (depth * TAB_SIZE) spaces in front of each line. 315 */ 316 void ufdt_node_print(const struct ufdt_node *node, int depth); 317 318 /* 319 * It's just ufdt_node_print(tree->root, 0). 320 */ 321 void ufdt_print(struct ufdt *tree); 322 323 /* 324 * END of ufdt output functions 325 */ 326 327 #endif /* LIBUFDT_H */ 328