• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #ifndef _LIBFDT_H
2  #define _LIBFDT_H
3  /*
4   * libfdt - Flat Device Tree manipulation
5   * Copyright (C) 2006 David Gibson, IBM Corporation.
6   *
7   * libfdt is dual licensed: you can use it either under the terms of
8   * the GPL, or the BSD license, at your option.
9   *
10   *  a) This library is free software; you can redistribute it and/or
11   *     modify it under the terms of the GNU General Public License as
12   *     published by the Free Software Foundation; either version 2 of the
13   *     License, or (at your option) any later version.
14   *
15   *     This library is distributed in the hope that it will be useful,
16   *     but WITHOUT ANY WARRANTY; without even the implied warranty of
17   *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   *     GNU General Public License for more details.
19   *
20   *     You should have received a copy of the GNU General Public
21   *     License along with this library; if not, write to the Free
22   *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
23   *     MA 02110-1301 USA
24   *
25   * Alternatively,
26   *
27   *  b) Redistribution and use in source and binary forms, with or
28   *     without modification, are permitted provided that the following
29   *     conditions are met:
30   *
31   *     1. Redistributions of source code must retain the above
32   *        copyright notice, this list of conditions and the following
33   *        disclaimer.
34   *     2. Redistributions in binary form must reproduce the above
35   *        copyright notice, this list of conditions and the following
36   *        disclaimer in the documentation and/or other materials
37   *        provided with the distribution.
38   *
39   *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
40   *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
41   *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42   *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43   *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44   *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45   *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46   *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47   *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48   *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49   *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
50   *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51   *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52   */
53  
54  #include <libfdt_env.h>
55  #include <fdt.h>
56  
57  #define FDT_FIRST_SUPPORTED_VERSION	0x10
58  #define FDT_LAST_SUPPORTED_VERSION	0x11
59  
60  /* Error codes: informative error codes */
61  #define FDT_ERR_NOTFOUND	1
62  	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
63  #define FDT_ERR_EXISTS		2
64  	/* FDT_ERR_EXISTS: Attempted to create a node or property which
65  	 * already exists */
66  #define FDT_ERR_NOSPACE		3
67  	/* FDT_ERR_NOSPACE: Operation needed to expand the device
68  	 * tree, but its buffer did not have sufficient space to
69  	 * contain the expanded tree. Use fdt_open_into() to move the
70  	 * device tree to a buffer with more space. */
71  
72  /* Error codes: codes for bad parameters */
73  #define FDT_ERR_BADOFFSET	4
74  	/* FDT_ERR_BADOFFSET: Function was passed a structure block
75  	 * offset which is out-of-bounds, or which points to an
76  	 * unsuitable part of the structure for the operation. */
77  #define FDT_ERR_BADPATH		5
78  	/* FDT_ERR_BADPATH: Function was passed a badly formatted path
79  	 * (e.g. missing a leading / for a function which requires an
80  	 * absolute path) */
81  #define FDT_ERR_BADPHANDLE	6
82  	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
83  	 * value.  phandle values of 0 and -1 are not permitted. */
84  #define FDT_ERR_BADSTATE	7
85  	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
86  	 * tree created by the sequential-write functions, which is
87  	 * not sufficiently complete for the requested operation. */
88  
89  /* Error codes: codes for bad device tree blobs */
90  #define FDT_ERR_TRUNCATED	8
91  	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
92  	 * ends without an FDT_END tag. */
93  #define FDT_ERR_BADMAGIC	9
94  	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
95  	 * device tree at all - it is missing the flattened device
96  	 * tree magic number. */
97  #define FDT_ERR_BADVERSION	10
98  	/* FDT_ERR_BADVERSION: Given device tree has a version which
99  	 * can't be handled by the requested operation.  For
100  	 * read-write functions, this may mean that fdt_open_into() is
101  	 * required to convert the tree to the expected version. */
102  #define FDT_ERR_BADSTRUCTURE	11
103  	/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
104  	 * structure block or other serious error (e.g. misnested
105  	 * nodes, or subnodes preceding properties). */
106  #define FDT_ERR_BADLAYOUT	12
107  	/* FDT_ERR_BADLAYOUT: For read-write functions, the given
108  	 * device tree has it's sub-blocks in an order that the
109  	 * function can't handle (memory reserve map, then structure,
110  	 * then strings).  Use fdt_open_into() to reorganize the tree
111  	 * into a form suitable for the read-write operations. */
112  
113  /* "Can't happen" error indicating a bug in libfdt */
114  #define FDT_ERR_INTERNAL	13
115  	/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
116  	 * Should never be returned, if it is, it indicates a bug in
117  	 * libfdt itself. */
118  
119  #define FDT_ERR_MAX		13
120  
121  /**********************************************************************/
122  /* Low-level functions (you probably don't need these)                */
123  /**********************************************************************/
124  
125  const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
fdt_offset_ptr_w(void * fdt,int offset,int checklen)126  static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
127  {
128  	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
129  }
130  
131  uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
132  
133  /**********************************************************************/
134  /* Traversal functions                                                */
135  /**********************************************************************/
136  
137  int fdt_next_node(const void *fdt, int offset, int *depth);
138  
139  /**********************************************************************/
140  /* General functions                                                  */
141  /**********************************************************************/
142  
143  #define fdt_get_header(fdt, field) \
144  	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
145  #define fdt_magic(fdt) 			(fdt_get_header(fdt, magic))
146  #define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
147  #define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
148  #define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
149  #define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
150  #define fdt_version(fdt)		(fdt_get_header(fdt, version))
151  #define fdt_last_comp_version(fdt) 	(fdt_get_header(fdt, last_comp_version))
152  #define fdt_boot_cpuid_phys(fdt) 	(fdt_get_header(fdt, boot_cpuid_phys))
153  #define fdt_size_dt_strings(fdt) 	(fdt_get_header(fdt, size_dt_strings))
154  #define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
155  
156  #define __fdt_set_hdr(name) \
157  	static inline void fdt_set_##name(void *fdt, uint32_t val) \
158  	{ \
159  		struct fdt_header *fdth = fdt; \
160  		fdth->name = cpu_to_fdt32(val); \
161  	}
162  __fdt_set_hdr(magic);
163  __fdt_set_hdr(totalsize);
164  __fdt_set_hdr(off_dt_struct);
165  __fdt_set_hdr(off_dt_strings);
166  __fdt_set_hdr(off_mem_rsvmap);
167  __fdt_set_hdr(version);
168  __fdt_set_hdr(last_comp_version);
169  __fdt_set_hdr(boot_cpuid_phys);
170  __fdt_set_hdr(size_dt_strings);
171  __fdt_set_hdr(size_dt_struct);
172  #undef __fdt_set_hdr
173  
174  /**
175   * fdt_check_header - sanity check a device tree or possible device tree
176   * @fdt: pointer to data which might be a flattened device tree
177   *
178   * fdt_check_header() checks that the given buffer contains what
179   * appears to be a flattened device tree with sane information in its
180   * header.
181   *
182   * returns:
183   *     0, if the buffer appears to contain a valid device tree
184   *     -FDT_ERR_BADMAGIC,
185   *     -FDT_ERR_BADVERSION,
186   *     -FDT_ERR_BADSTATE, standard meanings, as above
187   */
188  int fdt_check_header(const void *fdt);
189  
190  /**
191   * fdt_move - move a device tree around in memory
192   * @fdt: pointer to the device tree to move
193   * @buf: pointer to memory where the device is to be moved
194   * @bufsize: size of the memory space at buf
195   *
196   * fdt_move() relocates, if possible, the device tree blob located at
197   * fdt to the buffer at buf of size bufsize.  The buffer may overlap
198   * with the existing device tree blob at fdt.  Therefore,
199   *     fdt_move(fdt, fdt, fdt_totalsize(fdt))
200   * should always succeed.
201   *
202   * returns:
203   *     0, on success
204   *     -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
205   *     -FDT_ERR_BADMAGIC,
206   *     -FDT_ERR_BADVERSION,
207   *     -FDT_ERR_BADSTATE, standard meanings
208   */
209  int fdt_move(const void *fdt, void *buf, int bufsize);
210  
211  /**********************************************************************/
212  /* Read-only functions                                                */
213  /**********************************************************************/
214  
215  /**
216   * fdt_string - retrieve a string from the strings block of a device tree
217   * @fdt: pointer to the device tree blob
218   * @stroffset: offset of the string within the strings block (native endian)
219   *
220   * fdt_string() retrieves a pointer to a single string from the
221   * strings block of the device tree blob at fdt.
222   *
223   * returns:
224   *     a pointer to the string, on success
225   *     NULL, if stroffset is out of bounds
226   */
227  const char *fdt_string(const void *fdt, int stroffset);
228  
229  /**
230   * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
231   * @fdt: pointer to the device tree blob
232   *
233   * Returns the number of entries in the device tree blob's memory
234   * reservation map.  This does not include the terminating 0,0 entry
235   * or any other (0,0) entries reserved for expansion.
236   *
237   * returns:
238   *     the number of entries
239   */
240  int fdt_num_mem_rsv(const void *fdt);
241  
242  /**
243   * fdt_get_mem_rsv - retrieve one memory reserve map entry
244   * @fdt: pointer to the device tree blob
245   * @address, @size: pointers to 64-bit variables
246   *
247   * On success, *address and *size will contain the address and size of
248   * the n-th reserve map entry from the device tree blob, in
249   * native-endian format.
250   *
251   * returns:
252   *     0, on success
253   *     -FDT_ERR_BADMAGIC,
254   *     -FDT_ERR_BADVERSION,
255   *     -FDT_ERR_BADSTATE, standard meanings
256   */
257  int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
258  
259  /**
260   * fdt_subnode_offset_namelen - find a subnode based on substring
261   * @fdt: pointer to the device tree blob
262   * @parentoffset: structure block offset of a node
263   * @name: name of the subnode to locate
264   * @namelen: number of characters of name to consider
265   *
266   * Identical to fdt_subnode_offset(), but only examine the first
267   * namelen characters of name for matching the subnode name.  This is
268   * useful for finding subnodes based on a portion of a larger string,
269   * such as a full path.
270   */
271  int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
272  			       const char *name, int namelen);
273  /**
274   * fdt_subnode_offset - find a subnode of a given node
275   * @fdt: pointer to the device tree blob
276   * @parentoffset: structure block offset of a node
277   * @name: name of the subnode to locate
278   *
279   * fdt_subnode_offset() finds a subnode of the node at structure block
280   * offset parentoffset with the given name.  name may include a unit
281   * address, in which case fdt_subnode_offset() will find the subnode
282   * with that unit address, or the unit address may be omitted, in
283   * which case fdt_subnode_offset() will find an arbitrary subnode
284   * whose name excluding unit address matches the given name.
285   *
286   * returns:
287   *	structure block offset of the requested subnode (>=0), on success
288   *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
289   *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
290   *      -FDT_ERR_BADMAGIC,
291   *	-FDT_ERR_BADVERSION,
292   *	-FDT_ERR_BADSTATE,
293   *	-FDT_ERR_BADSTRUCTURE,
294   *	-FDT_ERR_TRUNCATED, standard meanings.
295   */
296  int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
297  
298  /**
299   * fdt_path_offset - find a tree node by its full path
300   * @fdt: pointer to the device tree blob
301   * @path: full path of the node to locate
302   *
303   * fdt_path_offset() finds a node of a given path in the device tree.
304   * Each path component may omit the unit address portion, but the
305   * results of this are undefined if any such path component is
306   * ambiguous (that is if there are multiple nodes at the relevant
307   * level matching the given component, differentiated only by unit
308   * address).
309   *
310   * returns:
311   *	structure block offset of the node with the requested path (>=0), on success
312   *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
313   *	-FDT_ERR_NOTFOUND, if the requested node does not exist
314   *      -FDT_ERR_BADMAGIC,
315   *	-FDT_ERR_BADVERSION,
316   *	-FDT_ERR_BADSTATE,
317   *	-FDT_ERR_BADSTRUCTURE,
318   *	-FDT_ERR_TRUNCATED, standard meanings.
319   */
320  int fdt_path_offset(const void *fdt, const char *path);
321  
322  /**
323   * fdt_get_name - retrieve the name of a given node
324   * @fdt: pointer to the device tree blob
325   * @nodeoffset: structure block offset of the starting node
326   * @lenp: pointer to an integer variable (will be overwritten) or NULL
327   *
328   * fdt_get_name() retrieves the name (including unit address) of the
329   * device tree node at structure block offset nodeoffset.  If lenp is
330   * non-NULL, the length of this name is also returned, in the integer
331   * pointed to by lenp.
332   *
333   * returns:
334   *	pointer to the node's name, on success
335   *		If lenp is non-NULL, *lenp contains the length of that name (>=0)
336   *	NULL, on error
337   *		if lenp is non-NULL *lenp contains an error code (<0):
338   *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
339   *		-FDT_ERR_BADMAGIC,
340   *		-FDT_ERR_BADVERSION,
341   *		-FDT_ERR_BADSTATE, standard meanings
342   */
343  const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
344  
345  /**
346   * fdt_get_property - find a given property in a given node
347   * @fdt: pointer to the device tree blob
348   * @nodeoffset: offset of the node whose property to find
349   * @name: name of the property to find
350   * @lenp: pointer to an integer variable (will be overwritten) or NULL
351   *
352   * fdt_get_property() retrieves a pointer to the fdt_property
353   * structure within the device tree blob corresponding to the property
354   * named 'name' of the node at offset nodeoffset.  If lenp is
355   * non-NULL, the length of the property value is also returned, in the
356   * integer pointed to by lenp.
357   *
358   * returns:
359   *	pointer to the structure representing the property
360   *		if lenp is non-NULL, *lenp contains the length of the property
361   *		value (>=0)
362   *	NULL, on error
363   *		if lenp is non-NULL, *lenp contains an error code (<0):
364   *		-FDT_ERR_NOTFOUND, node does not have named property
365   *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
366   *		-FDT_ERR_BADMAGIC,
367   *		-FDT_ERR_BADVERSION,
368   *		-FDT_ERR_BADSTATE,
369   *		-FDT_ERR_BADSTRUCTURE,
370   *		-FDT_ERR_TRUNCATED, standard meanings
371   */
372  const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
373  					    const char *name, int *lenp);
fdt_get_property_w(void * fdt,int nodeoffset,const char * name,int * lenp)374  static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
375  						      const char *name,
376  						      int *lenp)
377  {
378  	return (struct fdt_property *)(uintptr_t)
379  		fdt_get_property(fdt, nodeoffset, name, lenp);
380  }
381  
382  /**
383   * fdt_getprop - retrieve the value of a given property
384   * @fdt: pointer to the device tree blob
385   * @nodeoffset: offset of the node whose property to find
386   * @name: name of the property to find
387   * @lenp: pointer to an integer variable (will be overwritten) or NULL
388   *
389   * fdt_getprop() retrieves a pointer to the value of the property
390   * named 'name' of the node at offset nodeoffset (this will be a
391   * pointer to within the device blob itself, not a copy of the value).
392   * If lenp is non-NULL, the length of the property value is also
393   * returned, in the integer pointed to by lenp.
394   *
395   * returns:
396   *	pointer to the property's value
397   *		if lenp is non-NULL, *lenp contains the length of the property
398   *		value (>=0)
399   *	NULL, on error
400   *		if lenp is non-NULL, *lenp contains an error code (<0):
401   *		-FDT_ERR_NOTFOUND, node does not have named property
402   *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
403   *		-FDT_ERR_BADMAGIC,
404   *		-FDT_ERR_BADVERSION,
405   *		-FDT_ERR_BADSTATE,
406   *		-FDT_ERR_BADSTRUCTURE,
407   *		-FDT_ERR_TRUNCATED, standard meanings
408   */
409  const void *fdt_getprop(const void *fdt, int nodeoffset,
410  			const char *name, int *lenp);
fdt_getprop_w(void * fdt,int nodeoffset,const char * name,int * lenp)411  static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
412  				  const char *name, int *lenp)
413  {
414  	return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
415  }
416  
417  /**
418   * fdt_get_phandle - retrieve the phandle of a given node
419   * @fdt: pointer to the device tree blob
420   * @nodeoffset: structure block offset of the node
421   *
422   * fdt_get_phandle() retrieves the phandle of the device tree node at
423   * structure block offset nodeoffset.
424   *
425   * returns:
426   *	the phandle of the node at nodeoffset, on success (!= 0, != -1)
427   *	0, if the node has no phandle, or another error occurs
428   */
429  uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
430  
431  /**
432   * fdt_get_path - determine the full path of a node
433   * @fdt: pointer to the device tree blob
434   * @nodeoffset: offset of the node whose path to find
435   * @buf: character buffer to contain the returned path (will be overwritten)
436   * @buflen: size of the character buffer at buf
437   *
438   * fdt_get_path() computes the full path of the node at offset
439   * nodeoffset, and records that path in the buffer at buf.
440   *
441   * NOTE: This function is expensive, as it must scan the device tree
442   * structure from the start to nodeoffset.
443   *
444   * returns:
445   *	0, on success
446   *		buf contains the absolute path of the node at
447   *		nodeoffset, as a NUL-terminated string.
448   * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
449   *	-FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
450   *		characters and will not fit in the given buffer.
451   *	-FDT_ERR_BADMAGIC,
452   *	-FDT_ERR_BADVERSION,
453   *	-FDT_ERR_BADSTATE,
454   *	-FDT_ERR_BADSTRUCTURE, standard meanings
455   */
456  int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
457  
458  /**
459   * fdt_supernode_atdepth_offset - find a specific ancestor of a node
460   * @fdt: pointer to the device tree blob
461   * @nodeoffset: offset of the node whose parent to find
462   * @supernodedepth: depth of the ancestor to find
463   * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
464   *
465   * fdt_supernode_atdepth_offset() finds an ancestor of the given node
466   * at a specific depth from the root (where the root itself has depth
467   * 0, its immediate subnodes depth 1 and so forth).  So
468   *	fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
469   * will always return 0, the offset of the root node.  If the node at
470   * nodeoffset has depth D, then:
471   *	fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
472   * will return nodeoffset itself.
473   *
474   * NOTE: This function is expensive, as it must scan the device tree
475   * structure from the start to nodeoffset.
476   *
477   * returns:
478  
479   *	structure block offset of the node at node offset's ancestor
480   *		of depth supernodedepth (>=0), on success
481   * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
482  *	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
483   *	-FDT_ERR_BADMAGIC,
484   *	-FDT_ERR_BADVERSION,
485   *	-FDT_ERR_BADSTATE,
486   *	-FDT_ERR_BADSTRUCTURE, standard meanings
487   */
488  int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
489  				 int supernodedepth, int *nodedepth);
490  
491  /**
492   * fdt_node_depth - find the depth of a given node
493   * @fdt: pointer to the device tree blob
494   * @nodeoffset: offset of the node whose parent to find
495   *
496   * fdt_node_depth() finds the depth of a given node.  The root node
497   * has depth 0, its immediate subnodes depth 1 and so forth.
498   *
499   * NOTE: This function is expensive, as it must scan the device tree
500   * structure from the start to nodeoffset.
501   *
502   * returns:
503   *	depth of the node at nodeoffset (>=0), on success
504   * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
505   *	-FDT_ERR_BADMAGIC,
506   *	-FDT_ERR_BADVERSION,
507   *	-FDT_ERR_BADSTATE,
508   *	-FDT_ERR_BADSTRUCTURE, standard meanings
509   */
510  int fdt_node_depth(const void *fdt, int nodeoffset);
511  
512  /**
513   * fdt_parent_offset - find the parent of a given node
514   * @fdt: pointer to the device tree blob
515   * @nodeoffset: offset of the node whose parent to find
516   *
517   * fdt_parent_offset() locates the parent node of a given node (that
518   * is, it finds the offset of the node which contains the node at
519   * nodeoffset as a subnode).
520   *
521   * NOTE: This function is expensive, as it must scan the device tree
522   * structure from the start to nodeoffset, *twice*.
523   *
524   * returns:
525   *	structure block offset of the parent of the node at nodeoffset
526   *		(>=0), on success
527   * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
528   *	-FDT_ERR_BADMAGIC,
529   *	-FDT_ERR_BADVERSION,
530   *	-FDT_ERR_BADSTATE,
531   *	-FDT_ERR_BADSTRUCTURE, standard meanings
532   */
533  int fdt_parent_offset(const void *fdt, int nodeoffset);
534  
535  /**
536   * fdt_node_offset_by_prop_value - find nodes with a given property value
537   * @fdt: pointer to the device tree blob
538   * @startoffset: only find nodes after this offset
539   * @propname: property name to check
540   * @propval: property value to search for
541   * @proplen: length of the value in propval
542   *
543   * fdt_node_offset_by_prop_value() returns the offset of the first
544   * node after startoffset, which has a property named propname whose
545   * value is of length proplen and has value equal to propval; or if
546   * startoffset is -1, the very first such node in the tree.
547   *
548   * To iterate through all nodes matching the criterion, the following
549   * idiom can be used:
550   *	offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
551   *					       propval, proplen);
552   *	while (offset != -FDT_ERR_NOTFOUND) {
553   *		// other code here
554   *		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
555   *						       propval, proplen);
556   *	}
557   *
558   * Note the -1 in the first call to the function, if 0 is used here
559   * instead, the function will never locate the root node, even if it
560   * matches the criterion.
561   *
562   * returns:
563   *	structure block offset of the located node (>= 0, >startoffset),
564   *		 on success
565   *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
566   *		tree after startoffset
567   * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
568   *	-FDT_ERR_BADMAGIC,
569   *	-FDT_ERR_BADVERSION,
570   *	-FDT_ERR_BADSTATE,
571   *	-FDT_ERR_BADSTRUCTURE, standard meanings
572   */
573  int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
574  				  const char *propname,
575  				  const void *propval, int proplen);
576  
577  /**
578   * fdt_node_offset_by_phandle - find the node with a given phandle
579   * @fdt: pointer to the device tree blob
580   * @phandle: phandle value
581   *
582   * fdt_node_offset_by_phandle() returns the offset of the node
583   * which has the given phandle value.  If there is more than one node
584   * in the tree with the given phandle (an invalid tree), results are
585   * undefined.
586   *
587   * returns:
588   *	structure block offset of the located node (>= 0), on success
589   *	-FDT_ERR_NOTFOUND, no node with that phandle exists
590   *	-FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
591   *	-FDT_ERR_BADMAGIC,
592   *	-FDT_ERR_BADVERSION,
593   *	-FDT_ERR_BADSTATE,
594   *	-FDT_ERR_BADSTRUCTURE, standard meanings
595   */
596  int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
597  
598  /**
599   * fdt_node_check_compatible: check a node's compatible property
600   * @fdt: pointer to the device tree blob
601   * @nodeoffset: offset of a tree node
602   * @compatible: string to match against
603   *
604   *
605   * fdt_node_check_compatible() returns 0 if the given node contains a
606   * 'compatible' property with the given string as one of its elements,
607   * it returns non-zero otherwise, or on error.
608   *
609   * returns:
610   *	0, if the node has a 'compatible' property listing the given string
611   *	1, if the node has a 'compatible' property, but it does not list
612   *		the given string
613   *	-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
614   * 	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
615   *	-FDT_ERR_BADMAGIC,
616   *	-FDT_ERR_BADVERSION,
617   *	-FDT_ERR_BADSTATE,
618   *	-FDT_ERR_BADSTRUCTURE, standard meanings
619   */
620  int fdt_node_check_compatible(const void *fdt, int nodeoffset,
621  			      const char *compatible);
622  
623  /**
624   * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
625   * @fdt: pointer to the device tree blob
626   * @startoffset: only find nodes after this offset
627   * @compatible: 'compatible' string to match against
628   *
629   * fdt_node_offset_by_compatible() returns the offset of the first
630   * node after startoffset, which has a 'compatible' property which
631   * lists the given compatible string; or if startoffset is -1, the
632   * very first such node in the tree.
633   *
634   * To iterate through all nodes matching the criterion, the following
635   * idiom can be used:
636   *	offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
637   *	while (offset != -FDT_ERR_NOTFOUND) {
638   *		// other code here
639   *		offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
640   *	}
641   *
642   * Note the -1 in the first call to the function, if 0 is used here
643   * instead, the function will never locate the root node, even if it
644   * matches the criterion.
645   *
646   * returns:
647   *	structure block offset of the located node (>= 0, >startoffset),
648   *		 on success
649   *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
650   *		tree after startoffset
651   * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
652   *	-FDT_ERR_BADMAGIC,
653   *	-FDT_ERR_BADVERSION,
654   *	-FDT_ERR_BADSTATE,
655   *	-FDT_ERR_BADSTRUCTURE, standard meanings
656   */
657  int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
658  				  const char *compatible);
659  
660  /**********************************************************************/
661  /* Write-in-place functions                                           */
662  /**********************************************************************/
663  
664  /**
665   * fdt_setprop_inplace - change a property's value, but not its size
666   * @fdt: pointer to the device tree blob
667   * @nodeoffset: offset of the node whose property to change
668   * @name: name of the property to change
669   * @val: pointer to data to replace the property value with
670   * @len: length of the property value
671   *
672   * fdt_setprop_inplace() replaces the value of a given property with
673   * the data in val, of length len.  This function cannot change the
674   * size of a property, and so will only work if len is equal to the
675   * current length of the property.
676   *
677   * This function will alter only the bytes in the blob which contain
678   * the given property value, and will not alter or move any other part
679   * of the tree.
680   *
681   * returns:
682   *	0, on success
683   *	-FDT_ERR_NOSPACE, if len is not equal to the property's current length
684   *	-FDT_ERR_NOTFOUND, node does not have the named property
685   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
686   *	-FDT_ERR_BADMAGIC,
687   *	-FDT_ERR_BADVERSION,
688   *	-FDT_ERR_BADSTATE,
689   *	-FDT_ERR_BADSTRUCTURE,
690   *	-FDT_ERR_TRUNCATED, standard meanings
691   */
692  int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
693  			const void *val, int len);
694  
695  /**
696   * fdt_setprop_inplace_cell - change the value of a single-cell property
697   * @fdt: pointer to the device tree blob
698   * @nodeoffset: offset of the node whose property to change
699   * @name: name of the property to change
700   * @val: cell (32-bit integer) value to replace the property with
701   *
702   * fdt_setprop_inplace_cell() replaces the value of a given property
703   * with the 32-bit integer cell value in val, converting val to
704   * big-endian if necessary.  This function cannot change the size of a
705   * property, and so will only work if the property already exists and
706   * has length 4.
707   *
708   * This function will alter only the bytes in the blob which contain
709   * the given property value, and will not alter or move any other part
710   * of the tree.
711   *
712   * returns:
713   *	0, on success
714   *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
715    *	-FDT_ERR_NOTFOUND, node does not have the named property
716   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
717   *	-FDT_ERR_BADMAGIC,
718   *	-FDT_ERR_BADVERSION,
719   *	-FDT_ERR_BADSTATE,
720   *	-FDT_ERR_BADSTRUCTURE,
721   *	-FDT_ERR_TRUNCATED, standard meanings
722   */
fdt_setprop_inplace_cell(void * fdt,int nodeoffset,const char * name,uint32_t val)723  static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
724  					   const char *name, uint32_t val)
725  {
726  	val = cpu_to_fdt32(val);
727  	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
728  }
729  
730  /**
731   * fdt_nop_property - replace a property with nop tags
732   * @fdt: pointer to the device tree blob
733   * @nodeoffset: offset of the node whose property to nop
734   * @name: name of the property to nop
735   *
736   * fdt_nop_property() will replace a given property's representation
737   * in the blob with FDT_NOP tags, effectively removing it from the
738   * tree.
739   *
740   * This function will alter only the bytes in the blob which contain
741   * the property, and will not alter or move any other part of the
742   * tree.
743   *
744   * returns:
745   *	0, on success
746   *	-FDT_ERR_NOTFOUND, node does not have the named property
747   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
748   *	-FDT_ERR_BADMAGIC,
749   *	-FDT_ERR_BADVERSION,
750   *	-FDT_ERR_BADSTATE,
751   *	-FDT_ERR_BADSTRUCTURE,
752   *	-FDT_ERR_TRUNCATED, standard meanings
753   */
754  int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
755  
756  /**
757   * fdt_nop_node - replace a node (subtree) with nop tags
758   * @fdt: pointer to the device tree blob
759   * @nodeoffset: offset of the node to nop
760   *
761   * fdt_nop_node() will replace a given node's representation in the
762   * blob, including all its subnodes, if any, with FDT_NOP tags,
763   * effectively removing it from the tree.
764   *
765   * This function will alter only the bytes in the blob which contain
766   * the node and its properties and subnodes, and will not alter or
767   * move any other part of the tree.
768   *
769   * returns:
770   *	0, on success
771   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
772   *	-FDT_ERR_BADMAGIC,
773   *	-FDT_ERR_BADVERSION,
774   *	-FDT_ERR_BADSTATE,
775   *	-FDT_ERR_BADSTRUCTURE,
776   *	-FDT_ERR_TRUNCATED, standard meanings
777   */
778  int fdt_nop_node(void *fdt, int nodeoffset);
779  
780  /**********************************************************************/
781  /* Sequential write functions                                         */
782  /**********************************************************************/
783  
784  int fdt_create(void *buf, int bufsize);
785  int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
786  int fdt_finish_reservemap(void *fdt);
787  int fdt_begin_node(void *fdt, const char *name);
788  int fdt_property(void *fdt, const char *name, const void *val, int len);
fdt_property_cell(void * fdt,const char * name,uint32_t val)789  static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
790  {
791  	val = cpu_to_fdt32(val);
792  	return fdt_property(fdt, name, &val, sizeof(val));
793  }
794  #define fdt_property_string(fdt, name, str) \
795  	fdt_property(fdt, name, str, strlen(str)+1)
796  int fdt_end_node(void *fdt);
797  int fdt_finish(void *fdt);
798  
799  /**********************************************************************/
800  /* Read-write functions                                               */
801  /**********************************************************************/
802  
803  int fdt_open_into(const void *fdt, void *buf, int bufsize);
804  int fdt_pack(void *fdt);
805  
806  /**
807   * fdt_add_mem_rsv - add one memory reserve map entry
808   * @fdt: pointer to the device tree blob
809   * @address, @size: 64-bit values (native endian)
810   *
811   * Adds a reserve map entry to the given blob reserving a region at
812   * address address of length size.
813   *
814   * This function will insert data into the reserve map and will
815   * therefore change the indexes of some entries in the table.
816   *
817   * returns:
818   *	0, on success
819   *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
820   *		contain the new reservation entry
821   *	-FDT_ERR_BADMAGIC,
822   *	-FDT_ERR_BADVERSION,
823   *	-FDT_ERR_BADSTATE,
824   *	-FDT_ERR_BADSTRUCTURE,
825   *	-FDT_ERR_BADLAYOUT,
826   *	-FDT_ERR_TRUNCATED, standard meanings
827   */
828  int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
829  
830  /**
831   * fdt_del_mem_rsv - remove a memory reserve map entry
832   * @fdt: pointer to the device tree blob
833   * @n: entry to remove
834   *
835   * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
836   * the blob.
837   *
838   * This function will delete data from the reservation table and will
839   * therefore change the indexes of some entries in the table.
840   *
841   * returns:
842   *	0, on success
843   *	-FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
844   *		are less than n+1 reserve map entries)
845   *	-FDT_ERR_BADMAGIC,
846   *	-FDT_ERR_BADVERSION,
847   *	-FDT_ERR_BADSTATE,
848   *	-FDT_ERR_BADSTRUCTURE,
849   *	-FDT_ERR_BADLAYOUT,
850   *	-FDT_ERR_TRUNCATED, standard meanings
851   */
852  int fdt_del_mem_rsv(void *fdt, int n);
853  
854  /**
855   * fdt_set_name - change the name of a given node
856   * @fdt: pointer to the device tree blob
857   * @nodeoffset: structure block offset of a node
858   * @name: name to give the node
859   *
860   * fdt_set_name() replaces the name (including unit address, if any)
861   * of the given node with the given string.  NOTE: this function can't
862   * efficiently check if the new name is unique amongst the given
863   * node's siblings; results are undefined if this function is invoked
864   * with a name equal to one of the given node's siblings.
865   *
866   * This function may insert or delete data from the blob, and will
867   * therefore change the offsets of some existing nodes.
868   *
869   * returns:
870   *	0, on success
871   *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob
872   *		to contain the new name
873   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
874   *	-FDT_ERR_BADMAGIC,
875   *	-FDT_ERR_BADVERSION,
876   *	-FDT_ERR_BADSTATE, standard meanings
877   */
878  int fdt_set_name(void *fdt, int nodeoffset, const char *name);
879  
880  /**
881   * fdt_setprop - create or change a property
882   * @fdt: pointer to the device tree blob
883   * @nodeoffset: offset of the node whose property to change
884   * @name: name of the property to change
885   * @val: pointer to data to set the property value to
886   * @len: length of the property value
887   *
888   * fdt_setprop() sets the value of the named property in the given
889   * node to the given value and length, creating the property if it
890   * does not already exist.
891   *
892   * This function may insert or delete data from the blob, and will
893   * therefore change the offsets of some existing nodes.
894   *
895   * returns:
896   *	0, on success
897   *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
898   *		contain the new property value
899   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
900   *	-FDT_ERR_BADLAYOUT,
901   *	-FDT_ERR_BADMAGIC,
902   *	-FDT_ERR_BADVERSION,
903   *	-FDT_ERR_BADSTATE,
904   *	-FDT_ERR_BADSTRUCTURE,
905   *	-FDT_ERR_BADLAYOUT,
906   *	-FDT_ERR_TRUNCATED, standard meanings
907   */
908  int fdt_setprop(void *fdt, int nodeoffset, const char *name,
909  		const void *val, int len);
910  
911  /**
912   * fdt_setprop_cell - set a property to a single cell value
913   * @fdt: pointer to the device tree blob
914   * @nodeoffset: offset of the node whose property to change
915   * @name: name of the property to change
916   * @val: 32-bit integer value for the property (native endian)
917   *
918   * fdt_setprop_cell() sets the value of the named property in the
919   * given node to the given cell value (converting to big-endian if
920   * necessary), or creates a new property with that value if it does
921   * not already exist.
922   *
923   * This function may insert or delete data from the blob, and will
924   * therefore change the offsets of some existing nodes.
925   *
926   * returns:
927   *	0, on success
928   *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
929   *		contain the new property value
930   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
931   *	-FDT_ERR_BADLAYOUT,
932   *	-FDT_ERR_BADMAGIC,
933   *	-FDT_ERR_BADVERSION,
934   *	-FDT_ERR_BADSTATE,
935   *	-FDT_ERR_BADSTRUCTURE,
936   *	-FDT_ERR_BADLAYOUT,
937   *	-FDT_ERR_TRUNCATED, standard meanings
938   */
fdt_setprop_cell(void * fdt,int nodeoffset,const char * name,uint32_t val)939  static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
940  				   uint32_t val)
941  {
942  	val = cpu_to_fdt32(val);
943  	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
944  }
945  
946  /**
947   * fdt_setprop_string - set a property to a string value
948   * @fdt: pointer to the device tree blob
949   * @nodeoffset: offset of the node whose property to change
950   * @name: name of the property to change
951   * @str: string value for the property
952   *
953   * fdt_setprop_string() sets the value of the named property in the
954   * given node to the given string value (using the length of the
955   * string to determine the new length of the property), or creates a
956   * new property with that value if it does not already exist.
957   *
958   * This function may insert or delete data from the blob, and will
959   * therefore change the offsets of some existing nodes.
960   *
961   * returns:
962   *	0, on success
963   *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
964   *		contain the new property value
965   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
966   *	-FDT_ERR_BADLAYOUT,
967   *	-FDT_ERR_BADMAGIC,
968   *	-FDT_ERR_BADVERSION,
969   *	-FDT_ERR_BADSTATE,
970   *	-FDT_ERR_BADSTRUCTURE,
971   *	-FDT_ERR_BADLAYOUT,
972   *	-FDT_ERR_TRUNCATED, standard meanings
973   */
974  #define fdt_setprop_string(fdt, nodeoffset, name, str) \
975  	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
976  
977  /**
978   * fdt_delprop - delete a property
979   * @fdt: pointer to the device tree blob
980   * @nodeoffset: offset of the node whose property to nop
981   * @name: name of the property to nop
982   *
983   * fdt_del_property() will delete the given property.
984   *
985   * This function will delete data from the blob, and will therefore
986   * change the offsets of some existing nodes.
987   *
988   * returns:
989   *	0, on success
990   *	-FDT_ERR_NOTFOUND, node does not have the named property
991   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
992   *	-FDT_ERR_BADLAYOUT,
993   *	-FDT_ERR_BADMAGIC,
994   *	-FDT_ERR_BADVERSION,
995   *	-FDT_ERR_BADSTATE,
996   *	-FDT_ERR_BADSTRUCTURE,
997   *	-FDT_ERR_TRUNCATED, standard meanings
998   */
999  int fdt_delprop(void *fdt, int nodeoffset, const char *name);
1000  
1001  /**
1002   * fdt_add_subnode_namelen - creates a new node based on substring
1003   * @fdt: pointer to the device tree blob
1004   * @parentoffset: structure block offset of a node
1005   * @name: name of the subnode to locate
1006   * @namelen: number of characters of name to consider
1007   *
1008   * Identical to fdt_add_subnode(), but use only the first namelen
1009   * characters of name as the name of the new node.  This is useful for
1010   * creating subnodes based on a portion of a larger string, such as a
1011   * full path.
1012   */
1013  int fdt_add_subnode_namelen(void *fdt, int parentoffset,
1014  			    const char *name, int namelen);
1015  
1016  /**
1017   * fdt_add_subnode - creates a new node
1018   * @fdt: pointer to the device tree blob
1019   * @parentoffset: structure block offset of a node
1020   * @name: name of the subnode to locate
1021   *
1022   * fdt_add_subnode() creates a new node as a subnode of the node at
1023   * structure block offset parentoffset, with the given name (which
1024   * should include the unit address, if any).
1025   *
1026   * This function will insert data into the blob, and will therefore
1027   * change the offsets of some existing nodes.
1028  
1029   * returns:
1030   *	structure block offset of the created nodeequested subnode (>=0), on success
1031   *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
1032   *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
1033   *	-FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
1034   *		the given name
1035   *	-FDT_ERR_NOSPACE, if there is insufficient free space in the
1036   *		blob to contain the new node
1037   *	-FDT_ERR_NOSPACE
1038   *	-FDT_ERR_BADLAYOUT
1039   *      -FDT_ERR_BADMAGIC,
1040   *	-FDT_ERR_BADVERSION,
1041   *	-FDT_ERR_BADSTATE,
1042   *	-FDT_ERR_BADSTRUCTURE,
1043   *	-FDT_ERR_TRUNCATED, standard meanings.
1044   */
1045  int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
1046  
1047  /**
1048   * fdt_del_node - delete a node (subtree)
1049   * @fdt: pointer to the device tree blob
1050   * @nodeoffset: offset of the node to nop
1051   *
1052   * fdt_del_node() will remove the given node, including all its
1053   * subnodes if any, from the blob.
1054   *
1055   * This function will delete data from the blob, and will therefore
1056   * change the offsets of some existing nodes.
1057   *
1058   * returns:
1059   *	0, on success
1060   *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1061   *	-FDT_ERR_BADLAYOUT,
1062   *	-FDT_ERR_BADMAGIC,
1063   *	-FDT_ERR_BADVERSION,
1064   *	-FDT_ERR_BADSTATE,
1065   *	-FDT_ERR_BADSTRUCTURE,
1066   *	-FDT_ERR_TRUNCATED, standard meanings
1067   */
1068  int fdt_del_node(void *fdt, int nodeoffset);
1069  
1070  /**********************************************************************/
1071  /* Debugging / informational functions                                */
1072  /**********************************************************************/
1073  
1074  const char *fdt_strerror(int errval);
1075  
1076  #endif /* _LIBFDT_H */
1077