aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/libfdt
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 12:44:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 12:44:08 -0400
commita54dfb1a845c38a97686268d8c4086a63d9493aa (patch)
tree3b31c81672fa89102aae929cc6c1e48e6e9382f4 /scripts/dtc/libfdt
parenteb0ad9c06d51edb5d18a7007fd4d77a8805b2ba7 (diff)
parent36165f55055781a0e4bf32d775241796414504b0 (diff)
Merge tag 'dt-for-3.7' of git://sources.calxeda.com/kernel/linux
Pull devicetree updates from Rob Herring: - Import of latest upstream device tree compiler (dtc) - New function of_get_child_by_name - Support for #size-cells of 0 and #addr-cells of >2 - Couple of DT binding documentation updates Fix up trivial conflicts due to of_get_child_by_name() having been added next to the new of_get_next_available_child(). * tag 'dt-for-3.7' of git://sources.calxeda.com/kernel/linux: MAINTAINERS: add scripts/dtc under Devicetree maintainers dtc: import latest upstream dtc dt: Document general interrupt controller bindings dt/s3c64xx/spi: Use of_get_child_by_name to get a named child dt: introduce of_get_child_by_name to get child node by name of: i2c: add support for wakeup-source property of/address: Handle #address-cells > 2 specially DT: export of_irq_to_resource_table() devicetree: serial: Add documentation for imx serial devicetree: pwm: mxs-pwm.txt: Fix reg field annotation of: Allow busses with #size-cells=0
Diffstat (limited to 'scripts/dtc/libfdt')
-rw-r--r--scripts/dtc/libfdt/Makefile.libfdt6
-rw-r--r--scripts/dtc/libfdt/fdt.c61
-rw-r--r--scripts/dtc/libfdt/fdt_empty_tree.c84
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c275
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c29
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c11
-rw-r--r--scripts/dtc/libfdt/fdt_wip.c41
-rw-r--r--scripts/dtc/libfdt/libfdt.h440
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h16
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h2
10 files changed, 793 insertions, 172 deletions
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 6c42acfa21ec..91126c000a1e 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -3,6 +3,8 @@
3# This is not a complete Makefile of itself. Instead, it is designed to 3# This is not a complete Makefile of itself. Instead, it is designed to
4# be easily embeddable into other systems of Makefiles. 4# be easily embeddable into other systems of Makefiles.
5# 5#
6LIBFDT_INCLUDES = fdt.h libfdt.h 6LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
7LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c 7LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
8LIBFDT_VERSION = version.lds
9LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
8LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) 10LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2acaec5923ae..e56833ae9b6f 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)
74 return 0; 74 return 0;
75} 75}
76 76
77const void *fdt_offset_ptr(const void *fdt, int offset, int len) 77const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
78{ 78{
79 const char *p; 79 const char *p;
80 80
@@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)
90 return p; 90 return p;
91} 91}
92 92
93uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) 93uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
94{ 94{
95 const uint32_t *tagp, *lenp; 95 const uint32_t *tagp, *lenp;
96 uint32_t tag; 96 uint32_t tag;
97 int offset = startoffset;
97 const char *p; 98 const char *p;
98 99
99 if (offset % FDT_TAGSIZE) 100 *nextoffset = -FDT_ERR_TRUNCATED;
100 return -1;
101
102 tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); 101 tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
103 if (! tagp) 102 if (!tagp)
104 return FDT_END; /* premature end */ 103 return FDT_END; /* premature end */
105 tag = fdt32_to_cpu(*tagp); 104 tag = fdt32_to_cpu(*tagp);
106 offset += FDT_TAGSIZE; 105 offset += FDT_TAGSIZE;
107 106
107 *nextoffset = -FDT_ERR_BADSTRUCTURE;
108 switch (tag) { 108 switch (tag) {
109 case FDT_BEGIN_NODE: 109 case FDT_BEGIN_NODE:
110 /* skip name */ 110 /* skip name */
111 do { 111 do {
112 p = fdt_offset_ptr(fdt, offset++, 1); 112 p = fdt_offset_ptr(fdt, offset++, 1);
113 } while (p && (*p != '\0')); 113 } while (p && (*p != '\0'));
114 if (! p) 114 if (!p)
115 return FDT_END; 115 return FDT_END; /* premature end */
116 break; 116 break;
117
117 case FDT_PROP: 118 case FDT_PROP:
118 lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); 119 lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
119 if (! lenp) 120 if (!lenp)
120 return FDT_END; 121 return FDT_END; /* premature end */
121 /* skip name offset, length and value */ 122 /* skip-name offset, length and value */
122 offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); 123 offset += sizeof(struct fdt_property) - FDT_TAGSIZE
124 + fdt32_to_cpu(*lenp);
125 break;
126
127 case FDT_END:
128 case FDT_END_NODE:
129 case FDT_NOP:
123 break; 130 break;
131
132 default:
133 return FDT_END;
124 } 134 }
125 135
126 if (nextoffset) 136 if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
127 *nextoffset = FDT_TAGALIGN(offset); 137 return FDT_END; /* premature end */
128 138
139 *nextoffset = FDT_TAGALIGN(offset);
129 return tag; 140 return tag;
130} 141}
131 142
@@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset)
138 return offset; 149 return offset;
139} 150}
140 151
152int _fdt_check_prop_offset(const void *fdt, int offset)
153{
154 if ((offset < 0) || (offset % FDT_TAGSIZE)
155 || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
156 return -FDT_ERR_BADOFFSET;
157
158 return offset;
159}
160
141int fdt_next_node(const void *fdt, int offset, int *depth) 161int fdt_next_node(const void *fdt, int offset, int *depth)
142{ 162{
143 int nextoffset = 0; 163 int nextoffset = 0;
@@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
162 break; 182 break;
163 183
164 case FDT_END_NODE: 184 case FDT_END_NODE:
165 if (depth) 185 if (depth && ((--(*depth)) < 0))
166 (*depth)--; 186 return nextoffset;
167 break; 187 break;
168 188
169 case FDT_END: 189 case FDT_END:
170 return -FDT_ERR_NOTFOUND; 190 if ((nextoffset >= 0)
171 191 || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
172 default: 192 return -FDT_ERR_NOTFOUND;
173 return -FDT_ERR_BADSTRUCTURE; 193 else
194 return nextoffset;
174 } 195 }
175 } while (tag != FDT_BEGIN_NODE); 196 } while (tag != FDT_BEGIN_NODE);
176 197
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
new file mode 100644
index 000000000000..f72d13b1d19c
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2012 David Gibson, IBM Corporation.
4 *
5 * libfdt is dual licensed: you can use it either under the terms of
6 * the GPL, or the BSD license, at your option.
7 *
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
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 * MA 02110-1301 USA
22 *
23 * Alternatively,
24 *
25 * b) Redistribution and use in source and binary forms, with or
26 * without modification, are permitted provided that the following
27 * conditions are met:
28 *
29 * 1. Redistributions of source code must retain the above
30 * copyright notice, this list of conditions and the following
31 * disclaimer.
32 * 2. Redistributions in binary form must reproduce the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer in the documentation and/or other materials
35 * provided with the distribution.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 */
51#include "libfdt_env.h"
52
53#include <fdt.h>
54#include <libfdt.h>
55
56#include "libfdt_internal.h"
57
58int fdt_create_empty_tree(void *buf, int bufsize)
59{
60 int err;
61
62 err = fdt_create(buf, bufsize);
63 if (err)
64 return err;
65
66 err = fdt_finish_reservemap(buf);
67 if (err)
68 return err;
69
70 err = fdt_begin_node(buf, "");
71 if (err)
72 return err;
73
74 err = fdt_end_node(buf);
75 if (err)
76 return err;
77
78 err = fdt_finish(buf);
79 if (err)
80 return err;
81
82 return fdt_open_into(buf, buf, bufsize);
83}
84
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 22e692919ff9..02b6d687537f 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)
80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; 80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
81} 81}
82 82
83static int _fdt_string_eq(const void *fdt, int stroffset,
84 const char *s, int len)
85{
86 const char *p = fdt_string(fdt, stroffset);
87
88 return (strlen(p) == len) && (memcmp(p, s, len) == 0);
89}
90
83int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) 91int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
84{ 92{
85 FDT_CHECK_HEADER(fdt); 93 FDT_CHECK_HEADER(fdt);
@@ -97,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt)
97 return i; 105 return i;
98} 106}
99 107
108static int _nextprop(const void *fdt, int offset)
109{
110 uint32_t tag;
111 int nextoffset;
112
113 do {
114 tag = fdt_next_tag(fdt, offset, &nextoffset);
115
116 switch (tag) {
117 case FDT_END:
118 if (nextoffset >= 0)
119 return -FDT_ERR_BADSTRUCTURE;
120 else
121 return nextoffset;
122
123 case FDT_PROP:
124 return offset;
125 }
126 offset = nextoffset;
127 } while (tag == FDT_NOP);
128
129 return -FDT_ERR_NOTFOUND;
130}
131
100int fdt_subnode_offset_namelen(const void *fdt, int offset, 132int fdt_subnode_offset_namelen(const void *fdt, int offset,
101 const char *name, int namelen) 133 const char *name, int namelen)
102{ 134{
@@ -104,20 +136,16 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
104 136
105 FDT_CHECK_HEADER(fdt); 137 FDT_CHECK_HEADER(fdt);
106 138
107 for (depth = 0, offset = fdt_next_node(fdt, offset, &depth); 139 for (depth = 0;
108 (offset >= 0) && (depth > 0); 140 (offset >= 0) && (depth >= 0);
109 offset = fdt_next_node(fdt, offset, &depth)) { 141 offset = fdt_next_node(fdt, offset, &depth))
110 if (depth < 0) 142 if ((depth == 1)
111 return -FDT_ERR_NOTFOUND; 143 && _fdt_nodename_eq(fdt, offset, name, namelen))
112 else if ((depth == 1)
113 && _fdt_nodename_eq(fdt, offset, name, namelen))
114 return offset; 144 return offset;
115 }
116 145
117 if (offset < 0) 146 if (depth < 0)
118 return offset; /* error */
119 else
120 return -FDT_ERR_NOTFOUND; 147 return -FDT_ERR_NOTFOUND;
148 return offset; /* error */
121} 149}
122 150
123int fdt_subnode_offset(const void *fdt, int parentoffset, 151int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -134,8 +162,20 @@ int fdt_path_offset(const void *fdt, const char *path)
134 162
135 FDT_CHECK_HEADER(fdt); 163 FDT_CHECK_HEADER(fdt);
136 164
137 if (*path != '/') 165 /* see if we have an alias */
138 return -FDT_ERR_BADPATH; 166 if (*path != '/') {
167 const char *q = strchr(path, '/');
168
169 if (!q)
170 q = end;
171
172 p = fdt_get_alias_namelen(fdt, p, q - p);
173 if (!p)
174 return -FDT_ERR_BADPATH;
175 offset = fdt_path_offset(fdt, p);
176
177 p = q;
178 }
139 179
140 while (*p) { 180 while (*p) {
141 const char *q; 181 const char *q;
@@ -178,93 +218,142 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
178 return NULL; 218 return NULL;
179} 219}
180 220
181const struct fdt_property *fdt_get_property(const void *fdt, 221int fdt_first_property_offset(const void *fdt, int nodeoffset)
182 int nodeoffset, 222{
183 const char *name, int *lenp) 223 int offset;
224
225 if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
226 return offset;
227
228 return _nextprop(fdt, offset);
229}
230
231int fdt_next_property_offset(const void *fdt, int offset)
232{
233 if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
234 return offset;
235
236 return _nextprop(fdt, offset);
237}
238
239const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
240 int offset,
241 int *lenp)
184{ 242{
185 uint32_t tag;
186 const struct fdt_property *prop;
187 int namestroff;
188 int offset, nextoffset;
189 int err; 243 int err;
244 const struct fdt_property *prop;
190 245
191 if (((err = fdt_check_header(fdt)) != 0) 246 if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
192 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) 247 if (lenp)
193 goto fail; 248 *lenp = err;
249 return NULL;
250 }
194 251
195 nextoffset = err; 252 prop = _fdt_offset_ptr(fdt, offset);
196 do {
197 offset = nextoffset;
198 253
199 tag = fdt_next_tag(fdt, offset, &nextoffset); 254 if (lenp)
200 switch (tag) { 255 *lenp = fdt32_to_cpu(prop->len);
201 case FDT_END:
202 err = -FDT_ERR_TRUNCATED;
203 goto fail;
204 256
205 case FDT_BEGIN_NODE: 257 return prop;
206 case FDT_END_NODE: 258}
207 case FDT_NOP:
208 break;
209 259
210 case FDT_PROP: 260const struct fdt_property *fdt_get_property_namelen(const void *fdt,
211 err = -FDT_ERR_BADSTRUCTURE; 261 int offset,
212 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); 262 const char *name,
213 if (! prop) 263 int namelen, int *lenp)
214 goto fail; 264{
215 namestroff = fdt32_to_cpu(prop->nameoff); 265 for (offset = fdt_first_property_offset(fdt, offset);
216 if (strcmp(fdt_string(fdt, namestroff), name) == 0) { 266 (offset >= 0);
217 /* Found it! */ 267 (offset = fdt_next_property_offset(fdt, offset))) {
218 int len = fdt32_to_cpu(prop->len); 268 const struct fdt_property *prop;
219 prop = fdt_offset_ptr(fdt, offset,
220 sizeof(*prop)+len);
221 if (! prop)
222 goto fail;
223
224 if (lenp)
225 *lenp = len;
226
227 return prop;
228 }
229 break;
230 269
231 default: 270 if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
232 err = -FDT_ERR_BADSTRUCTURE; 271 offset = -FDT_ERR_INTERNAL;
233 goto fail; 272 break;
234 } 273 }
235 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); 274 if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
275 name, namelen))
276 return prop;
277 }
236 278
237 err = -FDT_ERR_NOTFOUND;
238 fail:
239 if (lenp) 279 if (lenp)
240 *lenp = err; 280 *lenp = offset;
241 return NULL; 281 return NULL;
242} 282}
243 283
244const void *fdt_getprop(const void *fdt, int nodeoffset, 284const struct fdt_property *fdt_get_property(const void *fdt,
245 const char *name, int *lenp) 285 int nodeoffset,
286 const char *name, int *lenp)
287{
288 return fdt_get_property_namelen(fdt, nodeoffset, name,
289 strlen(name), lenp);
290}
291
292const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
293 const char *name, int namelen, int *lenp)
246{ 294{
247 const struct fdt_property *prop; 295 const struct fdt_property *prop;
248 296
249 prop = fdt_get_property(fdt, nodeoffset, name, lenp); 297 prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
250 if (! prop) 298 if (! prop)
251 return NULL; 299 return NULL;
252 300
253 return prop->data; 301 return prop->data;
254} 302}
255 303
304const void *fdt_getprop_by_offset(const void *fdt, int offset,
305 const char **namep, int *lenp)
306{
307 const struct fdt_property *prop;
308
309 prop = fdt_get_property_by_offset(fdt, offset, lenp);
310 if (!prop)
311 return NULL;
312 if (namep)
313 *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
314 return prop->data;
315}
316
317const void *fdt_getprop(const void *fdt, int nodeoffset,
318 const char *name, int *lenp)
319{
320 return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
321}
322
256uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) 323uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
257{ 324{
258 const uint32_t *php; 325 const uint32_t *php;
259 int len; 326 int len;
260 327
261 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); 328 /* FIXME: This is a bit sub-optimal, since we potentially scan
262 if (!php || (len != sizeof(*php))) 329 * over all the properties twice. */
263 return 0; 330 php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
331 if (!php || (len != sizeof(*php))) {
332 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
333 if (!php || (len != sizeof(*php)))
334 return 0;
335 }
264 336
265 return fdt32_to_cpu(*php); 337 return fdt32_to_cpu(*php);
266} 338}
267 339
340const char *fdt_get_alias_namelen(const void *fdt,
341 const char *name, int namelen)
342{
343 int aliasoffset;
344
345 aliasoffset = fdt_path_offset(fdt, "/aliases");
346 if (aliasoffset < 0)
347 return NULL;
348
349 return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
350}
351
352const char *fdt_get_alias(const void *fdt, const char *name)
353{
354 return fdt_get_alias_namelen(fdt, name, strlen(name));
355}
356
268int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) 357int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
269{ 358{
270 int pdepth = 0, p = 0; 359 int pdepth = 0, p = 0;
@@ -279,9 +368,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
279 for (offset = 0, depth = 0; 368 for (offset = 0, depth = 0;
280 (offset >= 0) && (offset <= nodeoffset); 369 (offset >= 0) && (offset <= nodeoffset);
281 offset = fdt_next_node(fdt, offset, &depth)) { 370 offset = fdt_next_node(fdt, offset, &depth)) {
282 if (pdepth < depth)
283 continue; /* overflowed buffer */
284
285 while (pdepth > depth) { 371 while (pdepth > depth) {
286 do { 372 do {
287 p--; 373 p--;
@@ -289,14 +375,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
289 pdepth--; 375 pdepth--;
290 } 376 }
291 377
292 name = fdt_get_name(fdt, offset, &namelen); 378 if (pdepth >= depth) {
293 if (!name) 379 name = fdt_get_name(fdt, offset, &namelen);
294 return namelen; 380 if (!name)
295 if ((p + namelen + 1) <= buflen) { 381 return namelen;
296 memcpy(buf + p, name, namelen); 382 if ((p + namelen + 1) <= buflen) {
297 p += namelen; 383 memcpy(buf + p, name, namelen);
298 buf[p++] = '/'; 384 p += namelen;
299 pdepth++; 385 buf[p++] = '/';
386 pdepth++;
387 }
300 } 388 }
301 389
302 if (offset == nodeoffset) { 390 if (offset == nodeoffset) {
@@ -306,7 +394,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
306 if (p > 1) /* special case so that root path is "/", not "" */ 394 if (p > 1) /* special case so that root path is "/", not "" */
307 p--; 395 p--;
308 buf[p] = '\0'; 396 buf[p] = '\0';
309 return p; 397 return 0;
310 } 398 }
311 } 399 }
312 400
@@ -404,14 +492,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
404 492
405int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) 493int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
406{ 494{
495 int offset;
496
407 if ((phandle == 0) || (phandle == -1)) 497 if ((phandle == 0) || (phandle == -1))
408 return -FDT_ERR_BADPHANDLE; 498 return -FDT_ERR_BADPHANDLE;
409 phandle = cpu_to_fdt32(phandle); 499
410 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", 500 FDT_CHECK_HEADER(fdt);
411 &phandle, sizeof(phandle)); 501
502 /* FIXME: The algorithm here is pretty horrible: we
503 * potentially scan each property of a node in
504 * fdt_get_phandle(), then if that didn't find what
505 * we want, we scan over them again making our way to the next
506 * node. Still it's the easiest to implement approach;
507 * performance can come later. */
508 for (offset = fdt_next_node(fdt, -1, NULL);
509 offset >= 0;
510 offset = fdt_next_node(fdt, offset, NULL)) {
511 if (fdt_get_phandle(fdt, offset) == phandle)
512 return offset;
513 }
514
515 return offset; /* error from fdt_next_node() */
412} 516}
413 517
414static int _stringlist_contains(const char *strlist, int listlen, const char *str) 518static int _fdt_stringlist_contains(const char *strlist, int listlen,
519 const char *str)
415{ 520{
416 int len = strlen(str); 521 int len = strlen(str);
417 const char *p; 522 const char *p;
@@ -437,7 +542,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
437 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); 542 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
438 if (!prop) 543 if (!prop)
439 return len; 544 return len;
440 if (_stringlist_contains(prop, len, compatible)) 545 if (_fdt_stringlist_contains(prop, len, compatible))
441 return 0; 546 return 0;
442 else 547 else
443 return 1; 548 return 1;
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8e7ec4cb7bcd..24437dfc32b8 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
289 return 0; 289 return 0;
290} 290}
291 291
292int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
293 const void *val, int len)
294{
295 struct fdt_property *prop;
296 int err, oldlen, newlen;
297
298 FDT_RW_CHECK_HEADER(fdt);
299
300 prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
301 if (prop) {
302 newlen = len + oldlen;
303 err = _fdt_splice_struct(fdt, prop->data,
304 FDT_TAGALIGN(oldlen),
305 FDT_TAGALIGN(newlen));
306 if (err)
307 return err;
308 prop->len = cpu_to_fdt32(newlen);
309 memcpy(prop->data + oldlen, val, len);
310 } else {
311 err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
312 if (err)
313 return err;
314 memcpy(prop->data, val, len);
315 }
316 return 0;
317}
318
292int fdt_delprop(void *fdt, int nodeoffset, const char *name) 319int fdt_delprop(void *fdt, int nodeoffset, const char *name)
293{ 320{
294 struct fdt_property *prop; 321 struct fdt_property *prop;
@@ -406,6 +433,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
406 struct_size = 0; 433 struct_size = 0;
407 while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) 434 while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
408 ; 435 ;
436 if (struct_size < 0)
437 return struct_size;
409 } 438 }
410 439
411 if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { 440 if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 698329e0ccaf..55ebebf1eb20 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)
70 return err; \ 70 return err; \
71 } 71 }
72 72
73static void *_fdt_grab_space(void *fdt, int len) 73static void *_fdt_grab_space(void *fdt, size_t len)
74{ 74{
75 int offset = fdt_size_dt_struct(fdt); 75 int offset = fdt_size_dt_struct(fdt);
76 int spaceleft; 76 int spaceleft;
@@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)
82 return NULL; 82 return NULL;
83 83
84 fdt_set_size_dt_struct(fdt, offset + len); 84 fdt_set_size_dt_struct(fdt, offset + len);
85 return fdt_offset_ptr_w(fdt, offset, len); 85 return _fdt_offset_ptr_w(fdt, offset);
86} 86}
87 87
88int fdt_create(void *buf, int bufsize) 88int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@ int fdt_finish(void *fdt)
237 while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { 237 while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
238 if (tag == FDT_PROP) { 238 if (tag == FDT_PROP) {
239 struct fdt_property *prop = 239 struct fdt_property *prop =
240 fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); 240 _fdt_offset_ptr_w(fdt, offset);
241 int nameoff; 241 int nameoff;
242 242
243 if (! prop)
244 return -FDT_ERR_BADSTRUCTURE;
245
246 nameoff = fdt32_to_cpu(prop->nameoff); 243 nameoff = fdt32_to_cpu(prop->nameoff);
247 nameoff += fdt_size_dt_strings(fdt); 244 nameoff += fdt_size_dt_strings(fdt);
248 prop->nameoff = cpu_to_fdt32(nameoff); 245 prop->nameoff = cpu_to_fdt32(nameoff);
249 } 246 }
250 offset = nextoffset; 247 offset = nextoffset;
251 } 248 }
249 if (nextoffset < 0)
250 return nextoffset;
252 251
253 /* Finally, adjust the header */ 252 /* Finally, adjust the header */
254 fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); 253 fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index a4652c6e787e..6025fa1fe8fe 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
94 return 0; 94 return 0;
95} 95}
96 96
97int _fdt_node_end_offset(void *fdt, int nodeoffset) 97int _fdt_node_end_offset(void *fdt, int offset)
98{ 98{
99 int level = 0; 99 int depth = 0;
100 uint32_t tag; 100
101 int offset, nextoffset; 101 while ((offset >= 0) && (depth >= 0))
102 102 offset = fdt_next_node(fdt, offset, &depth);
103 tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); 103
104 if (tag != FDT_BEGIN_NODE) 104 return offset;
105 return -FDT_ERR_BADOFFSET;
106 do {
107 offset = nextoffset;
108 tag = fdt_next_tag(fdt, offset, &nextoffset);
109
110 switch (tag) {
111 case FDT_END:
112 return offset;
113
114 case FDT_BEGIN_NODE:
115 level++;
116 break;
117
118 case FDT_END_NODE:
119 level--;
120 break;
121
122 case FDT_PROP:
123 case FDT_NOP:
124 break;
125
126 default:
127 return -FDT_ERR_BADSTRUCTURE;
128 }
129 } while (level >= 0);
130
131 return nextoffset;
132} 105}
133 106
134int fdt_nop_node(void *fdt, int nodeoffset) 107int fdt_nop_node(void *fdt, int nodeoffset)
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index ff6246f000ce..73f49759a5e7 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -61,7 +61,7 @@
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: Attempted 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
@@ -122,7 +122,7 @@
122/* Low-level functions (you probably don't need these) */ 122/* Low-level functions (you probably don't need these) */
123/**********************************************************************/ 123/**********************************************************************/
124 124
125const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); 125const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
126static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) 126static 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);
@@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
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 = (struct fdt_header*)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);
@@ -343,6 +343,91 @@ int fdt_path_offset(const void *fdt, const char *path);
343const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); 343const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
344 344
345/** 345/**
346 * fdt_first_property_offset - find the offset of a node's first property
347 * @fdt: pointer to the device tree blob
348 * @nodeoffset: structure block offset of a node
349 *
350 * fdt_first_property_offset() finds the first property of the node at
351 * the given structure block offset.
352 *
353 * returns:
354 * structure block offset of the property (>=0), on success
355 * -FDT_ERR_NOTFOUND, if the requested node has no properties
356 * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
357 * -FDT_ERR_BADMAGIC,
358 * -FDT_ERR_BADVERSION,
359 * -FDT_ERR_BADSTATE,
360 * -FDT_ERR_BADSTRUCTURE,
361 * -FDT_ERR_TRUNCATED, standard meanings.
362 */
363int fdt_first_property_offset(const void *fdt, int nodeoffset);
364
365/**
366 * fdt_next_property_offset - step through a node's properties
367 * @fdt: pointer to the device tree blob
368 * @offset: structure block offset of a property
369 *
370 * fdt_next_property_offset() finds the property immediately after the
371 * one at the given structure block offset. This will be a property
372 * of the same node as the given property.
373 *
374 * returns:
375 * structure block offset of the next property (>=0), on success
376 * -FDT_ERR_NOTFOUND, if the given property is the last in its node
377 * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
378 * -FDT_ERR_BADMAGIC,
379 * -FDT_ERR_BADVERSION,
380 * -FDT_ERR_BADSTATE,
381 * -FDT_ERR_BADSTRUCTURE,
382 * -FDT_ERR_TRUNCATED, standard meanings.
383 */
384int fdt_next_property_offset(const void *fdt, int offset);
385
386/**
387 * fdt_get_property_by_offset - retrieve the property at a given offset
388 * @fdt: pointer to the device tree blob
389 * @offset: offset of the property to retrieve
390 * @lenp: pointer to an integer variable (will be overwritten) or NULL
391 *
392 * fdt_get_property_by_offset() retrieves a pointer to the
393 * fdt_property structure within the device tree blob at the given
394 * offset. If lenp is non-NULL, the length of the property value is
395 * also returned, in the integer pointed to by lenp.
396 *
397 * returns:
398 * pointer to the structure representing the property
399 * if lenp is non-NULL, *lenp contains the length of the property
400 * value (>=0)
401 * NULL, on error
402 * if lenp is non-NULL, *lenp contains an error code (<0):
403 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
404 * -FDT_ERR_BADMAGIC,
405 * -FDT_ERR_BADVERSION,
406 * -FDT_ERR_BADSTATE,
407 * -FDT_ERR_BADSTRUCTURE,
408 * -FDT_ERR_TRUNCATED, standard meanings
409 */
410const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
411 int offset,
412 int *lenp);
413
414/**
415 * fdt_get_property_namelen - find a property based on substring
416 * @fdt: pointer to the device tree blob
417 * @nodeoffset: offset of the node whose property to find
418 * @name: name of the property to find
419 * @namelen: number of characters of name to consider
420 * @lenp: pointer to an integer variable (will be overwritten) or NULL
421 *
422 * Identical to fdt_get_property_namelen(), but only examine the first
423 * namelen characters of name for matching the property name.
424 */
425const struct fdt_property *fdt_get_property_namelen(const void *fdt,
426 int nodeoffset,
427 const char *name,
428 int namelen, int *lenp);
429
430/**
346 * fdt_get_property - find a given property in a given node 431 * fdt_get_property - find a given property in a given node
347 * @fdt: pointer to the device tree blob 432 * @fdt: pointer to the device tree blob
348 * @nodeoffset: offset of the node whose property to find 433 * @nodeoffset: offset of the node whose property to find
@@ -380,6 +465,54 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
380} 465}
381 466
382/** 467/**
468 * fdt_getprop_by_offset - retrieve the value of a property at a given offset
469 * @fdt: pointer to the device tree blob
470 * @ffset: offset of the property to read
471 * @namep: pointer to a string variable (will be overwritten) or NULL
472 * @lenp: pointer to an integer variable (will be overwritten) or NULL
473 *
474 * fdt_getprop_by_offset() retrieves a pointer to the value of the
475 * property at structure block offset 'offset' (this will be a pointer
476 * to within the device blob itself, not a copy of the value). If
477 * lenp is non-NULL, the length of the property value is also
478 * returned, in the integer pointed to by lenp. If namep is non-NULL,
479 * the property's namne will also be returned in the char * pointed to
480 * by namep (this will be a pointer to within the device tree's string
481 * block, not a new copy of the name).
482 *
483 * returns:
484 * pointer to the property's value
485 * if lenp is non-NULL, *lenp contains the length of the property
486 * value (>=0)
487 * if namep is non-NULL *namep contiains a pointer to the property
488 * name.
489 * NULL, on error
490 * if lenp is non-NULL, *lenp contains an error code (<0):
491 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
492 * -FDT_ERR_BADMAGIC,
493 * -FDT_ERR_BADVERSION,
494 * -FDT_ERR_BADSTATE,
495 * -FDT_ERR_BADSTRUCTURE,
496 * -FDT_ERR_TRUNCATED, standard meanings
497 */
498const void *fdt_getprop_by_offset(const void *fdt, int offset,
499 const char **namep, int *lenp);
500
501/**
502 * fdt_getprop_namelen - get property value based on substring
503 * @fdt: pointer to the device tree blob
504 * @nodeoffset: offset of the node whose property to find
505 * @name: name of the property to find
506 * @namelen: number of characters of name to consider
507 * @lenp: pointer to an integer variable (will be overwritten) or NULL
508 *
509 * Identical to fdt_getprop(), but only examine the first namelen
510 * characters of name for matching the property name.
511 */
512const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
513 const char *name, int namelen, int *lenp);
514
515/**
383 * fdt_getprop - retrieve the value of a given property 516 * fdt_getprop - retrieve the value of a given property
384 * @fdt: pointer to the device tree blob 517 * @fdt: pointer to the device tree blob
385 * @nodeoffset: offset of the node whose property to find 518 * @nodeoffset: offset of the node whose property to find
@@ -429,6 +562,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
429uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); 562uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
430 563
431/** 564/**
565 * fdt_get_alias_namelen - get alias based on substring
566 * @fdt: pointer to the device tree blob
567 * @name: name of the alias th look up
568 * @namelen: number of characters of name to consider
569 *
570 * Identical to fdt_get_alias(), but only examine the first namelen
571 * characters of name for matching the alias name.
572 */
573const char *fdt_get_alias_namelen(const void *fdt,
574 const char *name, int namelen);
575
576/**
577 * fdt_get_alias - retreive the path referenced by a given alias
578 * @fdt: pointer to the device tree blob
579 * @name: name of the alias th look up
580 *
581 * fdt_get_alias() retrieves the value of a given alias. That is, the
582 * value of the property named 'name' in the node /aliases.
583 *
584 * returns:
585 * a pointer to the expansion of the alias named 'name', of it exists
586 * NULL, if the given alias or the /aliases node does not exist
587 */
588const char *fdt_get_alias(const void *fdt, const char *name);
589
590/**
432 * fdt_get_path - determine the full path of a node 591 * fdt_get_path - determine the full path of a node
433 * @fdt: pointer to the device tree blob 592 * @fdt: pointer to the device tree blob
434 * @nodeoffset: offset of the node whose path to find 593 * @nodeoffset: offset of the node whose path to find
@@ -693,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
693 const void *val, int len); 852 const void *val, int len);
694 853
695/** 854/**
696 * fdt_setprop_inplace_cell - change the value of a single-cell property 855 * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
697 * @fdt: pointer to the device tree blob 856 * @fdt: pointer to the device tree blob
698 * @nodeoffset: offset of the node whose property to change 857 * @nodeoffset: offset of the node whose property to change
699 * @name: name of the property to change 858 * @name: name of the property to change
700 * @val: cell (32-bit integer) value to replace the property with 859 * @val: 32-bit integer value to replace the property with
701 * 860 *
702 * fdt_setprop_inplace_cell() replaces the value of a given property 861 * fdt_setprop_inplace_u32() replaces the value of a given property
703 * with the 32-bit integer cell value in val, converting val to 862 * with the 32-bit integer value in val, converting val to big-endian
704 * big-endian if necessary. This function cannot change the size of a 863 * if necessary. This function cannot change the size of a property,
705 * property, and so will only work if the property already exists and 864 * and so will only work if the property already exists and has length
706 * has length 4. 865 * 4.
707 * 866 *
708 * This function will alter only the bytes in the blob which contain 867 * This function will alter only the bytes in the blob which contain
709 * the given property value, and will not alter or move any other part 868 * the given property value, and will not alter or move any other part
@@ -712,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
712 * returns: 871 * returns:
713 * 0, on success 872 * 0, on success
714 * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 873 * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
715 * -FDT_ERR_NOTFOUND, node does not have the named property 874 * -FDT_ERR_NOTFOUND, node does not have the named property
716 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 875 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
717 * -FDT_ERR_BADMAGIC, 876 * -FDT_ERR_BADMAGIC,
718 * -FDT_ERR_BADVERSION, 877 * -FDT_ERR_BADVERSION,
@@ -720,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
720 * -FDT_ERR_BADSTRUCTURE, 879 * -FDT_ERR_BADSTRUCTURE,
721 * -FDT_ERR_TRUNCATED, standard meanings 880 * -FDT_ERR_TRUNCATED, standard meanings
722 */ 881 */
723static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, 882static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
724 const char *name, uint32_t val) 883 const char *name, uint32_t val)
725{ 884{
726 val = cpu_to_fdt32(val); 885 val = cpu_to_fdt32(val);
727 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); 886 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
728} 887}
729 888
730/** 889/**
890 * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
891 * @fdt: pointer to the device tree blob
892 * @nodeoffset: offset of the node whose property to change
893 * @name: name of the property to change
894 * @val: 64-bit integer value to replace the property with
895 *
896 * fdt_setprop_inplace_u64() replaces the value of a given property
897 * with the 64-bit integer value in val, converting val to big-endian
898 * if necessary. This function cannot change the size of a property,
899 * and so will only work if the property already exists and has length
900 * 8.
901 *
902 * This function will alter only the bytes in the blob which contain
903 * the given property value, and will not alter or move any other part
904 * of the tree.
905 *
906 * returns:
907 * 0, on success
908 * -FDT_ERR_NOSPACE, if the property's length is not equal to 8
909 * -FDT_ERR_NOTFOUND, node does not have the named property
910 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
911 * -FDT_ERR_BADMAGIC,
912 * -FDT_ERR_BADVERSION,
913 * -FDT_ERR_BADSTATE,
914 * -FDT_ERR_BADSTRUCTURE,
915 * -FDT_ERR_TRUNCATED, standard meanings
916 */
917static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
918 const char *name, uint64_t val)
919{
920 val = cpu_to_fdt64(val);
921 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
922}
923
924/**
925 * fdt_setprop_inplace_cell - change the value of a single-cell property
926 *
927 * This is an alternative name for fdt_setprop_inplace_u32()
928 */
929static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
930 const char *name, uint32_t val)
931{
932 return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
933}
934
935/**
731 * fdt_nop_property - replace a property with nop tags 936 * fdt_nop_property - replace a property with nop tags
732 * @fdt: pointer to the device tree blob 937 * @fdt: pointer to the device tree blob
733 * @nodeoffset: offset of the node whose property to nop 938 * @nodeoffset: offset of the node whose property to nop
@@ -786,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
786int fdt_finish_reservemap(void *fdt); 991int fdt_finish_reservemap(void *fdt);
787int fdt_begin_node(void *fdt, const char *name); 992int fdt_begin_node(void *fdt, const char *name);
788int fdt_property(void *fdt, const char *name, const void *val, int len); 993int fdt_property(void *fdt, const char *name, const void *val, int len);
789static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) 994static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
790{ 995{
791 val = cpu_to_fdt32(val); 996 val = cpu_to_fdt32(val);
792 return fdt_property(fdt, name, &val, sizeof(val)); 997 return fdt_property(fdt, name, &val, sizeof(val));
793} 998}
999static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
1000{
1001 val = cpu_to_fdt64(val);
1002 return fdt_property(fdt, name, &val, sizeof(val));
1003}
1004static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
1005{
1006 return fdt_property_u32(fdt, name, val);
1007}
794#define fdt_property_string(fdt, name, str) \ 1008#define fdt_property_string(fdt, name, str) \
795 fdt_property(fdt, name, str, strlen(str)+1) 1009 fdt_property(fdt, name, str, strlen(str)+1)
796int fdt_end_node(void *fdt); 1010int fdt_end_node(void *fdt);
@@ -800,6 +1014,7 @@ int fdt_finish(void *fdt);
800/* Read-write functions */ 1014/* Read-write functions */
801/**********************************************************************/ 1015/**********************************************************************/
802 1016
1017int fdt_create_empty_tree(void *buf, int bufsize);
803int fdt_open_into(const void *fdt, void *buf, int bufsize); 1018int fdt_open_into(const void *fdt, void *buf, int bufsize);
804int fdt_pack(void *fdt); 1019int fdt_pack(void *fdt);
805 1020
@@ -909,14 +1124,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
909 const void *val, int len); 1124 const void *val, int len);
910 1125
911/** 1126/**
912 * fdt_setprop_cell - set a property to a single cell value 1127 * fdt_setprop_u32 - set a property to a 32-bit integer
913 * @fdt: pointer to the device tree blob 1128 * @fdt: pointer to the device tree blob
914 * @nodeoffset: offset of the node whose property to change 1129 * @nodeoffset: offset of the node whose property to change
915 * @name: name of the property to change 1130 * @name: name of the property to change
916 * @val: 32-bit integer value for the property (native endian) 1131 * @val: 32-bit integer value for the property (native endian)
917 * 1132 *
918 * fdt_setprop_cell() sets the value of the named property in the 1133 * fdt_setprop_u32() sets the value of the named property in the given
919 * given node to the given cell value (converting to big-endian if 1134 * node to the given 32-bit integer value (converting to big-endian if
920 * necessary), or creates a new property with that value if it does 1135 * necessary), or creates a new property with that value if it does
921 * not already exist. 1136 * not already exist.
922 * 1137 *
@@ -936,14 +1151,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
936 * -FDT_ERR_BADLAYOUT, 1151 * -FDT_ERR_BADLAYOUT,
937 * -FDT_ERR_TRUNCATED, standard meanings 1152 * -FDT_ERR_TRUNCATED, standard meanings
938 */ 1153 */
939static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, 1154static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
940 uint32_t val) 1155 uint32_t val)
941{ 1156{
942 val = cpu_to_fdt32(val); 1157 val = cpu_to_fdt32(val);
943 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); 1158 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
944} 1159}
945 1160
946/** 1161/**
1162 * fdt_setprop_u64 - set a property to a 64-bit integer
1163 * @fdt: pointer to the device tree blob
1164 * @nodeoffset: offset of the node whose property to change
1165 * @name: name of the property to change
1166 * @val: 64-bit integer value for the property (native endian)
1167 *
1168 * fdt_setprop_u64() sets the value of the named property in the given
1169 * node to the given 64-bit integer value (converting to big-endian if
1170 * necessary), or creates a new property with that value if it does
1171 * not already exist.
1172 *
1173 * This function may insert or delete data from the blob, and will
1174 * therefore change the offsets of some existing nodes.
1175 *
1176 * returns:
1177 * 0, on success
1178 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
1179 * contain the new property value
1180 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1181 * -FDT_ERR_BADLAYOUT,
1182 * -FDT_ERR_BADMAGIC,
1183 * -FDT_ERR_BADVERSION,
1184 * -FDT_ERR_BADSTATE,
1185 * -FDT_ERR_BADSTRUCTURE,
1186 * -FDT_ERR_BADLAYOUT,
1187 * -FDT_ERR_TRUNCATED, standard meanings
1188 */
1189static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
1190 uint64_t val)
1191{
1192 val = cpu_to_fdt64(val);
1193 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
1194}
1195
1196/**
1197 * fdt_setprop_cell - set a property to a single cell value
1198 *
1199 * This is an alternative name for fdt_setprop_u32()
1200 */
1201static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
1202 uint32_t val)
1203{
1204 return fdt_setprop_u32(fdt, nodeoffset, name, val);
1205}
1206
1207/**
947 * fdt_setprop_string - set a property to a string value 1208 * fdt_setprop_string - set a property to a string value
948 * @fdt: pointer to the device tree blob 1209 * @fdt: pointer to the device tree blob
949 * @nodeoffset: offset of the node whose property to change 1210 * @nodeoffset: offset of the node whose property to change
@@ -975,6 +1236,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
975 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) 1236 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
976 1237
977/** 1238/**
1239 * fdt_appendprop - append to or create a property
1240 * @fdt: pointer to the device tree blob
1241 * @nodeoffset: offset of the node whose property to change
1242 * @name: name of the property to append to
1243 * @val: pointer to data to append to the property value
1244 * @len: length of the data to append to the property value
1245 *
1246 * fdt_appendprop() appends the value to the named property in the
1247 * given node, creating the property if it does not already exist.
1248 *
1249 * This function may insert data into the blob, and will therefore
1250 * change the offsets of some existing nodes.
1251 *
1252 * returns:
1253 * 0, on success
1254 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
1255 * contain the new property value
1256 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1257 * -FDT_ERR_BADLAYOUT,
1258 * -FDT_ERR_BADMAGIC,
1259 * -FDT_ERR_BADVERSION,
1260 * -FDT_ERR_BADSTATE,
1261 * -FDT_ERR_BADSTRUCTURE,
1262 * -FDT_ERR_BADLAYOUT,
1263 * -FDT_ERR_TRUNCATED, standard meanings
1264 */
1265int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
1266 const void *val, int len);
1267
1268/**
1269 * fdt_appendprop_u32 - append a 32-bit integer value to a property
1270 * @fdt: pointer to the device tree blob
1271 * @nodeoffset: offset of the node whose property to change
1272 * @name: name of the property to change
1273 * @val: 32-bit integer value to append to the property (native endian)
1274 *
1275 * fdt_appendprop_u32() appends the given 32-bit integer value
1276 * (converting to big-endian if necessary) to the value of the named
1277 * property in the given node, or creates a new property with that
1278 * value if it does not already exist.
1279 *
1280 * This function may insert data into the blob, and will therefore
1281 * change the offsets of some existing nodes.
1282 *
1283 * returns:
1284 * 0, on success
1285 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
1286 * contain the new property value
1287 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1288 * -FDT_ERR_BADLAYOUT,
1289 * -FDT_ERR_BADMAGIC,
1290 * -FDT_ERR_BADVERSION,
1291 * -FDT_ERR_BADSTATE,
1292 * -FDT_ERR_BADSTRUCTURE,
1293 * -FDT_ERR_BADLAYOUT,
1294 * -FDT_ERR_TRUNCATED, standard meanings
1295 */
1296static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
1297 const char *name, uint32_t val)
1298{
1299 val = cpu_to_fdt32(val);
1300 return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
1301}
1302
1303/**
1304 * fdt_appendprop_u64 - append a 64-bit integer value to a property
1305 * @fdt: pointer to the device tree blob
1306 * @nodeoffset: offset of the node whose property to change
1307 * @name: name of the property to change
1308 * @val: 64-bit integer value to append to the property (native endian)
1309 *
1310 * fdt_appendprop_u64() appends the given 64-bit integer value
1311 * (converting to big-endian if necessary) to the value of the named
1312 * property in the given node, or creates a new property with that
1313 * value if it does not already exist.
1314 *
1315 * This function may insert data into the blob, and will therefore
1316 * change the offsets of some existing nodes.
1317 *
1318 * returns:
1319 * 0, on success
1320 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
1321 * contain the new property value
1322 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1323 * -FDT_ERR_BADLAYOUT,
1324 * -FDT_ERR_BADMAGIC,
1325 * -FDT_ERR_BADVERSION,
1326 * -FDT_ERR_BADSTATE,
1327 * -FDT_ERR_BADSTRUCTURE,
1328 * -FDT_ERR_BADLAYOUT,
1329 * -FDT_ERR_TRUNCATED, standard meanings
1330 */
1331static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
1332 const char *name, uint64_t val)
1333{
1334 val = cpu_to_fdt64(val);
1335 return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
1336}
1337
1338/**
1339 * fdt_appendprop_cell - append a single cell value to a property
1340 *
1341 * This is an alternative name for fdt_appendprop_u32()
1342 */
1343static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
1344 const char *name, uint32_t val)
1345{
1346 return fdt_appendprop_u32(fdt, nodeoffset, name, val);
1347}
1348
1349/**
1350 * fdt_appendprop_string - append a string to a property
1351 * @fdt: pointer to the device tree blob
1352 * @nodeoffset: offset of the node whose property to change
1353 * @name: name of the property to change
1354 * @str: string value to append to the property
1355 *
1356 * fdt_appendprop_string() appends the given string to the value of
1357 * the named property in the given node, or creates a new property
1358 * with that value if it does not already exist.
1359 *
1360 * This function may insert data into the blob, and will therefore
1361 * change the offsets of some existing nodes.
1362 *
1363 * returns:
1364 * 0, on success
1365 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
1366 * contain the new property value
1367 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1368 * -FDT_ERR_BADLAYOUT,
1369 * -FDT_ERR_BADMAGIC,
1370 * -FDT_ERR_BADVERSION,
1371 * -FDT_ERR_BADSTATE,
1372 * -FDT_ERR_BADSTRUCTURE,
1373 * -FDT_ERR_BADLAYOUT,
1374 * -FDT_ERR_TRUNCATED, standard meanings
1375 */
1376#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
1377 fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
1378
1379/**
978 * fdt_delprop - delete a property 1380 * fdt_delprop - delete a property
979 * @fdt: pointer to the device tree blob 1381 * @fdt: pointer to the device tree blob
980 * @nodeoffset: offset of the node whose property to nop 1382 * @nodeoffset: offset of the node whose property to nop
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index 449bf602daf1..213d7fb81c42 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -5,19 +5,25 @@
5#include <stdint.h> 5#include <stdint.h>
6#include <string.h> 6#include <string.h>
7 7
8#define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) 8#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n])
9static inline uint16_t fdt16_to_cpu(uint16_t x)
10{
11 return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
12}
13#define cpu_to_fdt16(x) fdt16_to_cpu(x)
14
9static inline uint32_t fdt32_to_cpu(uint32_t x) 15static inline uint32_t fdt32_to_cpu(uint32_t x)
10{ 16{
11 return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); 17 return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
12} 18}
13#define cpu_to_fdt32(x) fdt32_to_cpu(x) 19#define cpu_to_fdt32(x) fdt32_to_cpu(x)
14 20
15static inline uint64_t fdt64_to_cpu(uint64_t x) 21static inline uint64_t fdt64_to_cpu(uint64_t x)
16{ 22{
17 return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) 23 return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
18 | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); 24 | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
19} 25}
20#define cpu_to_fdt64(x) fdt64_to_cpu(x) 26#define cpu_to_fdt64(x) fdt64_to_cpu(x)
21#undef _B 27#undef EXTRACT_BYTE
22 28
23#endif /* _LIBFDT_ENV_H */ 29#endif /* _LIBFDT_ENV_H */
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 46eb93e4af5c..381133ba81df 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -62,8 +62,8 @@
62 return err; \ 62 return err; \
63 } 63 }
64 64
65uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
66int _fdt_check_node_offset(const void *fdt, int offset); 65int _fdt_check_node_offset(const void *fdt, int offset);
66int _fdt_check_prop_offset(const void *fdt, int offset);
67const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); 67const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
68int _fdt_node_end_offset(void *fdt, int nodeoffset); 68int _fdt_node_end_offset(void *fdt, int nodeoffset);
69 69