Commit 72c55878ecb1f0fdc8bc13516e5cb18fbae505e7

Authored by Wolfgang Denk

Merge branch 'master' of git://git.denx.de/u-boot-fdt

Showing 4 changed files Inline Diff

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