Commit 72c55878ecb1f0fdc8bc13516e5cb18fbae505e7
Exists in
master
and in
54 other branches
Merge branch 'master' of git://git.denx.de/u-boot-fdt
Showing 4 changed files Inline Diff
include/libfdt.h
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 |
lib_ppc/bootm.c
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 |
libfdt/fdt.c
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 |
libfdt/fdt_ro.c
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)) |