aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/libfdt
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/boot/libfdt')
-rw-r--r--arch/powerpc/boot/libfdt/Makefile.libfdt8
-rw-r--r--arch/powerpc/boot/libfdt/fdt.c61
-rw-r--r--arch/powerpc/boot/libfdt/fdt_ro.c329
-rw-r--r--arch/powerpc/boot/libfdt/fdt_rw.c200
-rw-r--r--arch/powerpc/boot/libfdt/fdt_strerror.c34
-rw-r--r--arch/powerpc/boot/libfdt/fdt_sw.c55
-rw-r--r--arch/powerpc/boot/libfdt/fdt_wip.c9
-rw-r--r--arch/powerpc/boot/libfdt/libfdt.h383
-rw-r--r--arch/powerpc/boot/libfdt/libfdt_internal.h24
9 files changed, 701 insertions, 402 deletions
diff --git a/arch/powerpc/boot/libfdt/Makefile.libfdt b/arch/powerpc/boot/libfdt/Makefile.libfdt
index 82f9c6a8287..6c42acfa21e 100644
--- a/arch/powerpc/boot/libfdt/Makefile.libfdt
+++ b/arch/powerpc/boot/libfdt/Makefile.libfdt
@@ -3,12 +3,6 @@
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_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
7LIBFDT_INCLUDES = fdt.h libfdt.h 6LIBFDT_INCLUDES = fdt.h libfdt.h
8LIBFDT_EXTRA = libfdt_internal.h 7LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
9LIBFDT_LIB = libfdt/libfdt.a
10
11LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) 8LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
12
13$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
14
diff --git a/arch/powerpc/boot/libfdt/fdt.c b/arch/powerpc/boot/libfdt/fdt.c
index 586a36136db..2acaec5923a 100644
--- a/arch/powerpc/boot/libfdt/fdt.c
+++ b/arch/powerpc/boot/libfdt/fdt.c
@@ -63,7 +63,7 @@ int fdt_check_header(const void *fdt)
63 return -FDT_ERR_BADVERSION; 63 return -FDT_ERR_BADVERSION;
64 if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) 64 if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
65 return -FDT_ERR_BADVERSION; 65 return -FDT_ERR_BADVERSION;
66 } else if (fdt_magic(fdt) == SW_MAGIC) { 66 } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
67 /* Unfinished sequential-write blob */ 67 /* Unfinished sequential-write blob */
68 if (fdt_size_dt_struct(fdt) == 0) 68 if (fdt_size_dt_struct(fdt) == 0)
69 return -FDT_ERR_BADSTATE; 69 return -FDT_ERR_BADSTATE;
@@ -76,7 +76,7 @@ int fdt_check_header(const void *fdt)
76 76
77const void *fdt_offset_ptr(const void *fdt, int offset, int len) 77const void *fdt_offset_ptr(const void *fdt, int offset, int len)
78{ 78{
79 const void *p; 79 const char *p;
80 80
81 if (fdt_version(fdt) >= 0x11) 81 if (fdt_version(fdt) >= 0x11)
82 if (((offset + len) < offset) 82 if (((offset + len) < offset)
@@ -124,11 +124,59 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
124 } 124 }
125 125
126 if (nextoffset) 126 if (nextoffset)
127 *nextoffset = ALIGN(offset, FDT_TAGSIZE); 127 *nextoffset = FDT_TAGALIGN(offset);
128 128
129 return tag; 129 return tag;
130} 130}
131 131
132int _fdt_check_node_offset(const void *fdt, int offset)
133{
134 if ((offset < 0) || (offset % FDT_TAGSIZE)
135 || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
136 return -FDT_ERR_BADOFFSET;
137
138 return offset;
139}
140
141int fdt_next_node(const void *fdt, int offset, int *depth)
142{
143 int nextoffset = 0;
144 uint32_t tag;
145
146 if (offset >= 0)
147 if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
148 return nextoffset;
149
150 do {
151 offset = nextoffset;
152 tag = fdt_next_tag(fdt, offset, &nextoffset);
153
154 switch (tag) {
155 case FDT_PROP:
156 case FDT_NOP:
157 break;
158
159 case FDT_BEGIN_NODE:
160 if (depth)
161 (*depth)++;
162 break;
163
164 case FDT_END_NODE:
165 if (depth)
166 (*depth)--;
167 break;
168
169 case FDT_END:
170 return -FDT_ERR_NOTFOUND;
171
172 default:
173 return -FDT_ERR_BADSTRUCTURE;
174 }
175 } while (tag != FDT_BEGIN_NODE);
176
177 return offset;
178}
179
132const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) 180const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
133{ 181{
134 int len = strlen(s) + 1; 182 int len = strlen(s) + 1;
@@ -136,17 +184,14 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
136 const char *p; 184 const char *p;
137 185
138 for (p = strtab; p <= last; p++) 186 for (p = strtab; p <= last; p++)
139 if (memeq(p, s, len)) 187 if (memcmp(p, s, len) == 0)
140 return p; 188 return p;
141 return NULL; 189 return NULL;
142} 190}
143 191
144int fdt_move(const void *fdt, void *buf, int bufsize) 192int fdt_move(const void *fdt, void *buf, int bufsize)
145{ 193{
146 int err = fdt_check_header(fdt); 194 FDT_CHECK_HEADER(fdt);
147
148 if (err)
149 return err;
150 195
151 if (fdt_totalsize(fdt) > bufsize) 196 if (fdt_totalsize(fdt) > bufsize)
152 return -FDT_ERR_NOSPACE; 197 return -FDT_ERR_NOSPACE;
diff --git a/arch/powerpc/boot/libfdt/fdt_ro.c b/arch/powerpc/boot/libfdt/fdt_ro.c
index 12a37d59f96..129b532bcc1 100644
--- a/arch/powerpc/boot/libfdt/fdt_ro.c
+++ b/arch/powerpc/boot/libfdt/fdt_ro.c
@@ -55,17 +55,10 @@
55 55
56#include "libfdt_internal.h" 56#include "libfdt_internal.h"
57 57
58#define CHECK_HEADER(fdt) \ 58static int _fdt_nodename_eq(const void *fdt, int offset,
59 { \ 59 const char *s, int len)
60 int err; \
61 if ((err = fdt_check_header(fdt)) != 0) \
62 return err; \
63 }
64
65static int nodename_eq(const void *fdt, int offset,
66 const char *s, int len)
67{ 60{
68 const char *p = fdt_offset_ptr(fdt, offset, len+1); 61 const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
69 62
70 if (! p) 63 if (! p)
71 /* short match */ 64 /* short match */
@@ -84,12 +77,12 @@ static int nodename_eq(const void *fdt, int offset,
84 77
85const char *fdt_string(const void *fdt, int stroffset) 78const char *fdt_string(const void *fdt, int stroffset)
86{ 79{
87 return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset; 80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
88} 81}
89 82
90int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) 83int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
91{ 84{
92 CHECK_HEADER(fdt); 85 FDT_CHECK_HEADER(fdt);
93 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); 86 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
94 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); 87 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
95 return 0; 88 return 0;
@@ -104,50 +97,24 @@ int fdt_num_mem_rsv(const void *fdt)
104 return i; 97 return i;
105} 98}
106 99
107int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, 100int fdt_subnode_offset_namelen(const void *fdt, int offset,
108 const char *name, int namelen) 101 const char *name, int namelen)
109{ 102{
110 int level = 0; 103 int depth;
111 uint32_t tag;
112 int offset, nextoffset;
113
114 CHECK_HEADER(fdt);
115
116 tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
117 if (tag != FDT_BEGIN_NODE)
118 return -FDT_ERR_BADOFFSET;
119
120 do {
121 offset = nextoffset;
122 tag = fdt_next_tag(fdt, offset, &nextoffset);
123
124 switch (tag) {
125 case FDT_END:
126 return -FDT_ERR_TRUNCATED;
127
128 case FDT_BEGIN_NODE:
129 level++;
130 if (level != 1)
131 continue;
132 if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen))
133 /* Found it! */
134 return offset;
135 break;
136
137 case FDT_END_NODE:
138 level--;
139 break;
140 104
141 case FDT_PROP: 105 FDT_CHECK_HEADER(fdt);
142 case FDT_NOP:
143 break;
144 106
145 default: 107 for (depth = 0;
146 return -FDT_ERR_BADSTRUCTURE; 108 offset >= 0;
147 } 109 offset = fdt_next_node(fdt, offset, &depth)) {
148 } while (level >= 0); 110 if (depth < 0)
111 return -FDT_ERR_NOTFOUND;
112 else if ((depth == 1)
113 && _fdt_nodename_eq(fdt, offset, name, namelen))
114 return offset;
115 }
149 116
150 return -FDT_ERR_NOTFOUND; 117 return offset; /* error */
151} 118}
152 119
153int fdt_subnode_offset(const void *fdt, int parentoffset, 120int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -162,7 +129,7 @@ int fdt_path_offset(const void *fdt, const char *path)
162 const char *p = path; 129 const char *p = path;
163 int offset = 0; 130 int offset = 0;
164 131
165 CHECK_HEADER(fdt); 132 FDT_CHECK_HEADER(fdt);
166 133
167 if (*path != '/') 134 if (*path != '/')
168 return -FDT_ERR_BADPATH; 135 return -FDT_ERR_BADPATH;
@@ -190,16 +157,12 @@ int fdt_path_offset(const void *fdt, const char *path)
190 157
191const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) 158const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
192{ 159{
193 const struct fdt_node_header *nh; 160 const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
194 int err; 161 int err;
195 162
196 if ((err = fdt_check_header(fdt)) != 0) 163 if (((err = fdt_check_header(fdt)) != 0)
197 goto fail; 164 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
198 165 goto fail;
199 err = -FDT_ERR_BADOFFSET;
200 nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
201 if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
202 goto fail;
203 166
204 if (len) 167 if (len)
205 *len = strlen(nh->name); 168 *len = strlen(nh->name);
@@ -222,17 +185,11 @@ const struct fdt_property *fdt_get_property(const void *fdt,
222 int offset, nextoffset; 185 int offset, nextoffset;
223 int err; 186 int err;
224 187
225 if ((err = fdt_check_header(fdt)) != 0) 188 if (((err = fdt_check_header(fdt)) != 0)
226 goto fail; 189 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
227 190 goto fail;
228 err = -FDT_ERR_BADOFFSET;
229 if (nodeoffset % FDT_TAGSIZE)
230 goto fail;
231
232 tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
233 if (tag != FDT_BEGIN_NODE)
234 goto fail;
235 191
192 nextoffset = err;
236 do { 193 do {
237 offset = nextoffset; 194 offset = nextoffset;
238 195
@@ -253,7 +210,7 @@ const struct fdt_property *fdt_get_property(const void *fdt,
253 if (! prop) 210 if (! prop)
254 goto fail; 211 goto fail;
255 namestroff = fdt32_to_cpu(prop->nameoff); 212 namestroff = fdt32_to_cpu(prop->nameoff);
256 if (streq(fdt_string(fdt, namestroff), name)) { 213 if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
257 /* Found it! */ 214 /* Found it! */
258 int len = fdt32_to_cpu(prop->len); 215 int len = fdt32_to_cpu(prop->len);
259 prop = fdt_offset_ptr(fdt, offset, 216 prop = fdt_offset_ptr(fdt, offset,
@@ -307,115 +264,91 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
307 264
308int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) 265int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
309{ 266{
310 uint32_t tag; 267 int pdepth = 0, p = 0;
311 int p = 0, overflow = 0; 268 int offset, depth, namelen;
312 int offset, nextoffset, namelen;
313 const char *name; 269 const char *name;
314 270
315 CHECK_HEADER(fdt); 271 FDT_CHECK_HEADER(fdt);
316
317 tag = fdt_next_tag(fdt, 0, &nextoffset);
318 if (tag != FDT_BEGIN_NODE)
319 return -FDT_ERR_BADSTRUCTURE;
320 272
321 if (buflen < 2) 273 if (buflen < 2)
322 return -FDT_ERR_NOSPACE; 274 return -FDT_ERR_NOSPACE;
323 buf[0] = '/';
324 p = 1;
325 275
326 while (nextoffset <= nodeoffset) { 276 for (offset = 0, depth = 0;
327 offset = nextoffset; 277 (offset >= 0) && (offset <= nodeoffset);
328 tag = fdt_next_tag(fdt, offset, &nextoffset); 278 offset = fdt_next_node(fdt, offset, &depth)) {
329 switch (tag) { 279 if (pdepth < depth)
330 case FDT_END: 280 continue; /* overflowed buffer */
331 return -FDT_ERR_BADOFFSET;
332 281
333 case FDT_BEGIN_NODE: 282 while (pdepth > depth) {
334 name = fdt_get_name(fdt, offset, &namelen); 283 do {
335 if (!name) 284 p--;
336 return namelen; 285 } while (buf[p-1] != '/');
337 if (overflow || ((p + namelen + 1) > buflen)) { 286 pdepth--;
338 overflow++; 287 }
339 break; 288
340 } 289 name = fdt_get_name(fdt, offset, &namelen);
290 if (!name)
291 return namelen;
292 if ((p + namelen + 1) <= buflen) {
341 memcpy(buf + p, name, namelen); 293 memcpy(buf + p, name, namelen);
342 p += namelen; 294 p += namelen;
343 buf[p++] = '/'; 295 buf[p++] = '/';
344 break; 296 pdepth++;
345 297 }
346 case FDT_END_NODE:
347 if (overflow) {
348 overflow--;
349 break;
350 }
351 do {
352 p--;
353 } while (buf[p-1] != '/');
354 break;
355 298
356 case FDT_PROP: 299 if (offset == nodeoffset) {
357 case FDT_NOP: 300 if (pdepth < (depth + 1))
358 break; 301 return -FDT_ERR_NOSPACE;
359 302
360 default: 303 if (p > 1) /* special case so that root path is "/", not "" */
361 return -FDT_ERR_BADSTRUCTURE; 304 p--;
305 buf[p] = '\0';
306 return p;
362 } 307 }
363 } 308 }
364 309
365 if (overflow) 310 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
366 return -FDT_ERR_NOSPACE; 311 return -FDT_ERR_BADOFFSET;
312 else if (offset == -FDT_ERR_BADOFFSET)
313 return -FDT_ERR_BADSTRUCTURE;
367 314
368 if (p > 1) /* special case so that root path is "/", not "" */ 315 return offset; /* error from fdt_next_node() */
369 p--;
370 buf[p] = '\0';
371 return p;
372} 316}
373 317
374int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, 318int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
375 int supernodedepth, int *nodedepth) 319 int supernodedepth, int *nodedepth)
376{ 320{
377 int level = -1; 321 int offset, depth;
378 uint32_t tag;
379 int offset, nextoffset = 0;
380 int supernodeoffset = -FDT_ERR_INTERNAL; 322 int supernodeoffset = -FDT_ERR_INTERNAL;
381 323
382 CHECK_HEADER(fdt); 324 FDT_CHECK_HEADER(fdt);
383 325
384 if (supernodedepth < 0) 326 if (supernodedepth < 0)
385 return -FDT_ERR_NOTFOUND; 327 return -FDT_ERR_NOTFOUND;
386 328
387 do { 329 for (offset = 0, depth = 0;
388 offset = nextoffset; 330 (offset >= 0) && (offset <= nodeoffset);
389 tag = fdt_next_tag(fdt, offset, &nextoffset); 331 offset = fdt_next_node(fdt, offset, &depth)) {
390 switch (tag) { 332 if (depth == supernodedepth)
391 case FDT_END: 333 supernodeoffset = offset;
392 return -FDT_ERR_BADOFFSET;
393
394 case FDT_BEGIN_NODE:
395 level++;
396 if (level == supernodedepth)
397 supernodeoffset = offset;
398 break;
399
400 case FDT_END_NODE:
401 level--;
402 break;
403 334
404 case FDT_PROP: 335 if (offset == nodeoffset) {
405 case FDT_NOP: 336 if (nodedepth)
406 break; 337 *nodedepth = depth;
407 338
408 default: 339 if (supernodedepth > depth)
409 return -FDT_ERR_BADSTRUCTURE; 340 return -FDT_ERR_NOTFOUND;
341 else
342 return supernodeoffset;
410 } 343 }
411 } while (offset < nodeoffset); 344 }
412 345
413 if (nodedepth) 346 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
414 *nodedepth = level; 347 return -FDT_ERR_BADOFFSET;
348 else if (offset == -FDT_ERR_BADOFFSET)
349 return -FDT_ERR_BADSTRUCTURE;
415 350
416 if (supernodedepth > level) 351 return offset; /* error from fdt_next_node() */
417 return -FDT_ERR_NOTFOUND;
418 return supernodeoffset;
419} 352}
420 353
421int fdt_node_depth(const void *fdt, int nodeoffset) 354int fdt_node_depth(const void *fdt, int nodeoffset)
@@ -443,51 +376,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
443 const char *propname, 376 const char *propname,
444 const void *propval, int proplen) 377 const void *propval, int proplen)
445{ 378{
446 uint32_t tag; 379 int offset;
447 int offset, nextoffset;
448 const void *val; 380 const void *val;
449 int len; 381 int len;
450 382
451 CHECK_HEADER(fdt); 383 FDT_CHECK_HEADER(fdt);
452
453 if (startoffset >= 0) {
454 tag = fdt_next_tag(fdt, startoffset, &nextoffset);
455 if (tag != FDT_BEGIN_NODE)
456 return -FDT_ERR_BADOFFSET;
457 } else {
458 nextoffset = 0;
459 }
460 384
461 /* FIXME: The algorithm here is pretty horrible: we scan each 385 /* FIXME: The algorithm here is pretty horrible: we scan each
462 * property of a node in fdt_getprop(), then if that didn't 386 * property of a node in fdt_getprop(), then if that didn't
463 * find what we want, we scan over them again making our way 387 * find what we want, we scan over them again making our way
464 * to the next node. Still it's the easiest to implement 388 * to the next node. Still it's the easiest to implement
465 * approach; performance can come later. */ 389 * approach; performance can come later. */
466 do { 390 for (offset = fdt_next_node(fdt, startoffset, NULL);
467 offset = nextoffset; 391 offset >= 0;
468 tag = fdt_next_tag(fdt, offset, &nextoffset); 392 offset = fdt_next_node(fdt, offset, NULL)) {
469 393 val = fdt_getprop(fdt, offset, propname, &len);
470 switch (tag) { 394 if (val && (len == proplen)
471 case FDT_BEGIN_NODE: 395 && (memcmp(val, propval, len) == 0))
472 val = fdt_getprop(fdt, offset, propname, &len); 396 return offset;
473 if (val 397 }
474 && (len == proplen)
475 && (memcmp(val, propval, len) == 0))
476 return offset;
477 break;
478
479 case FDT_PROP:
480 case FDT_END:
481 case FDT_END_NODE:
482 case FDT_NOP:
483 break;
484
485 default:
486 return -FDT_ERR_BADSTRUCTURE;
487 }
488 } while (tag != FDT_END);
489 398
490 return -FDT_ERR_NOTFOUND; 399 return offset; /* error from fdt_next_node() */
491} 400}
492 401
493int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) 402int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
@@ -499,10 +408,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
499 &phandle, sizeof(phandle)); 408 &phandle, sizeof(phandle));
500} 409}
501 410
502int _stringlist_contains(const void *strlist, int listlen, const char *str) 411int _stringlist_contains(const char *strlist, int listlen, const char *str)
503{ 412{
504 int len = strlen(str); 413 int len = strlen(str);
505 const void *p; 414 const char *p;
506 415
507 while (listlen >= len) { 416 while (listlen >= len) {
508 if (memcmp(str, strlist, len+1) == 0) 417 if (memcmp(str, strlist, len+1) == 0)
@@ -534,50 +443,24 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
534int fdt_node_offset_by_compatible(const void *fdt, int startoffset, 443int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
535 const char *compatible) 444 const char *compatible)
536{ 445{
537 uint32_t tag; 446 int offset, err;
538 int offset, nextoffset;
539 int err;
540
541 CHECK_HEADER(fdt);
542 447
543 if (startoffset >= 0) { 448 FDT_CHECK_HEADER(fdt);
544 tag = fdt_next_tag(fdt, startoffset, &nextoffset);
545 if (tag != FDT_BEGIN_NODE)
546 return -FDT_ERR_BADOFFSET;
547 } else {
548 nextoffset = 0;
549 }
550 449
551 /* FIXME: The algorithm here is pretty horrible: we scan each 450 /* FIXME: The algorithm here is pretty horrible: we scan each
552 * property of a node in fdt_node_check_compatible(), then if 451 * property of a node in fdt_node_check_compatible(), then if
553 * that didn't find what we want, we scan over them again 452 * that didn't find what we want, we scan over them again
554 * making our way to the next node. Still it's the easiest to 453 * making our way to the next node. Still it's the easiest to
555 * implement approach; performance can come later. */ 454 * implement approach; performance can come later. */
556 do { 455 for (offset = fdt_next_node(fdt, startoffset, NULL);
557 offset = nextoffset; 456 offset >= 0;
558 tag = fdt_next_tag(fdt, offset, &nextoffset); 457 offset = fdt_next_node(fdt, offset, NULL)) {
559 458 err = fdt_node_check_compatible(fdt, offset, compatible);
560 switch (tag) { 459 if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
561 case FDT_BEGIN_NODE: 460 return err;
562 err = fdt_node_check_compatible(fdt, offset, 461 else if (err == 0)
563 compatible); 462 return offset;
564 if ((err < 0) 463 }
565 && (err != -FDT_ERR_NOTFOUND))
566 return err;
567 else if (err == 0)
568 return offset;
569 break;
570
571 case FDT_PROP:
572 case FDT_END:
573 case FDT_END_NODE:
574 case FDT_NOP:
575 break;
576
577 default:
578 return -FDT_ERR_BADSTRUCTURE;
579 }
580 } while (tag != FDT_END);
581 464
582 return -FDT_ERR_NOTFOUND; 465 return offset; /* error from fdt_next_node() */
583} 466}
diff --git a/arch/powerpc/boot/libfdt/fdt_rw.c b/arch/powerpc/boot/libfdt/fdt_rw.c
index 6673f8ec962..8e7ec4cb7bc 100644
--- a/arch/powerpc/boot/libfdt/fdt_rw.c
+++ b/arch/powerpc/boot/libfdt/fdt_rw.c
@@ -55,10 +55,10 @@
55 55
56#include "libfdt_internal.h" 56#include "libfdt_internal.h"
57 57
58static int _blocks_misordered(const void *fdt, 58static int _fdt_blocks_misordered(const void *fdt,
59 int mem_rsv_size, int struct_size) 59 int mem_rsv_size, int struct_size)
60{ 60{
61 return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8)) 61 return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
62 || (fdt_off_dt_struct(fdt) < 62 || (fdt_off_dt_struct(fdt) <
63 (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) 63 (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
64 || (fdt_off_dt_strings(fdt) < 64 || (fdt_off_dt_strings(fdt) <
@@ -67,16 +67,14 @@ static int _blocks_misordered(const void *fdt,
67 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); 67 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
68} 68}
69 69
70static int rw_check_header(void *fdt) 70static int _fdt_rw_check_header(void *fdt)
71{ 71{
72 int err; 72 FDT_CHECK_HEADER(fdt);
73 73
74 if ((err = fdt_check_header(fdt)))
75 return err;
76 if (fdt_version(fdt) < 17) 74 if (fdt_version(fdt) < 17)
77 return -FDT_ERR_BADVERSION; 75 return -FDT_ERR_BADVERSION;
78 if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), 76 if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
79 fdt_size_dt_struct(fdt))) 77 fdt_size_dt_struct(fdt)))
80 return -FDT_ERR_BADLAYOUT; 78 return -FDT_ERR_BADLAYOUT;
81 if (fdt_version(fdt) > 17) 79 if (fdt_version(fdt) > 17)
82 fdt_set_version(fdt, 17); 80 fdt_set_version(fdt, 17);
@@ -84,36 +82,37 @@ static int rw_check_header(void *fdt)
84 return 0; 82 return 0;
85} 83}
86 84
87#define RW_CHECK_HEADER(fdt) \ 85#define FDT_RW_CHECK_HEADER(fdt) \
88 { \ 86 { \
89 int err; \ 87 int err; \
90 if ((err = rw_check_header(fdt)) != 0) \ 88 if ((err = _fdt_rw_check_header(fdt)) != 0) \
91 return err; \ 89 return err; \
92 } 90 }
93 91
94static inline int _blob_data_size(void *fdt) 92static inline int _fdt_data_size(void *fdt)
95{ 93{
96 return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); 94 return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
97} 95}
98 96
99static int _blob_splice(void *fdt, void *p, int oldlen, int newlen) 97static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
100{ 98{
101 void *end = fdt + _blob_data_size(fdt); 99 char *p = splicepoint;
100 char *end = (char *)fdt + _fdt_data_size(fdt);
102 101
103 if (((p + oldlen) < p) || ((p + oldlen) > end)) 102 if (((p + oldlen) < p) || ((p + oldlen) > end))
104 return -FDT_ERR_BADOFFSET; 103 return -FDT_ERR_BADOFFSET;
105 if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt))) 104 if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
106 return -FDT_ERR_NOSPACE; 105 return -FDT_ERR_NOSPACE;
107 memmove(p + newlen, p + oldlen, end - p - oldlen); 106 memmove(p + newlen, p + oldlen, end - p - oldlen);
108 return 0; 107 return 0;
109} 108}
110 109
111static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, 110static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
112 int oldn, int newn) 111 int oldn, int newn)
113{ 112{
114 int delta = (newn - oldn) * sizeof(*p); 113 int delta = (newn - oldn) * sizeof(*p);
115 int err; 114 int err;
116 err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); 115 err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
117 if (err) 116 if (err)
118 return err; 117 return err;
119 fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); 118 fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
@@ -121,13 +120,13 @@ static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
121 return 0; 120 return 0;
122} 121}
123 122
124static int _blob_splice_struct(void *fdt, void *p, 123static int _fdt_splice_struct(void *fdt, void *p,
125 int oldlen, int newlen) 124 int oldlen, int newlen)
126{ 125{
127 int delta = newlen - oldlen; 126 int delta = newlen - oldlen;
128 int err; 127 int err;
129 128
130 if ((err = _blob_splice(fdt, p, oldlen, newlen))) 129 if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
131 return err; 130 return err;
132 131
133 fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); 132 fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
@@ -135,19 +134,20 @@ static int _blob_splice_struct(void *fdt, void *p,
135 return 0; 134 return 0;
136} 135}
137 136
138static int _blob_splice_string(void *fdt, int newlen) 137static int _fdt_splice_string(void *fdt, int newlen)
139{ 138{
140 void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); 139 void *p = (char *)fdt
140 + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
141 int err; 141 int err;
142 142
143 if ((err = _blob_splice(fdt, p, 0, newlen))) 143 if ((err = _fdt_splice(fdt, p, 0, newlen)))
144 return err; 144 return err;
145 145
146 fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); 146 fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
147 return 0; 147 return 0;
148} 148}
149 149
150static int _find_add_string(void *fdt, const char *s) 150static int _fdt_find_add_string(void *fdt, const char *s)
151{ 151{
152 char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); 152 char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
153 const char *p; 153 const char *p;
@@ -161,7 +161,7 @@ static int _find_add_string(void *fdt, const char *s)
161 return (p - strtab); 161 return (p - strtab);
162 162
163 new = strtab + fdt_size_dt_strings(fdt); 163 new = strtab + fdt_size_dt_strings(fdt);
164 err = _blob_splice_string(fdt, len); 164 err = _fdt_splice_string(fdt, len);
165 if (err) 165 if (err)
166 return err; 166 return err;
167 167
@@ -174,11 +174,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
174 struct fdt_reserve_entry *re; 174 struct fdt_reserve_entry *re;
175 int err; 175 int err;
176 176
177 if ((err = rw_check_header(fdt))) 177 FDT_RW_CHECK_HEADER(fdt);
178 return err;
179 178
180 re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); 179 re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
181 err = _blob_splice_mem_rsv(fdt, re, 0, 1); 180 err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
182 if (err) 181 if (err)
183 return err; 182 return err;
184 183
@@ -192,19 +191,19 @@ int fdt_del_mem_rsv(void *fdt, int n)
192 struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); 191 struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
193 int err; 192 int err;
194 193
195 if ((err = rw_check_header(fdt))) 194 FDT_RW_CHECK_HEADER(fdt);
196 return err; 195
197 if (n >= fdt_num_mem_rsv(fdt)) 196 if (n >= fdt_num_mem_rsv(fdt))
198 return -FDT_ERR_NOTFOUND; 197 return -FDT_ERR_NOTFOUND;
199 198
200 err = _blob_splice_mem_rsv(fdt, re, 1, 0); 199 err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
201 if (err) 200 if (err)
202 return err; 201 return err;
203 return 0; 202 return 0;
204} 203}
205 204
206static int _resize_property(void *fdt, int nodeoffset, const char *name, int len, 205static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
207 struct fdt_property **prop) 206 int len, struct fdt_property **prop)
208{ 207{
209 int oldlen; 208 int oldlen;
210 int err; 209 int err;
@@ -213,36 +212,33 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len
213 if (! (*prop)) 212 if (! (*prop))
214 return oldlen; 213 return oldlen;
215 214
216 if ((err = _blob_splice_struct(fdt, (*prop)->data, 215 if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
217 ALIGN(oldlen, FDT_TAGSIZE), 216 FDT_TAGALIGN(len))))
218 ALIGN(len, FDT_TAGSIZE))))
219 return err; 217 return err;
220 218
221 (*prop)->len = cpu_to_fdt32(len); 219 (*prop)->len = cpu_to_fdt32(len);
222 return 0; 220 return 0;
223} 221}
224 222
225static int _add_property(void *fdt, int nodeoffset, const char *name, int len, 223static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
226 struct fdt_property **prop) 224 int len, struct fdt_property **prop)
227{ 225{
228 uint32_t tag;
229 int proplen; 226 int proplen;
230 int nextoffset; 227 int nextoffset;
231 int namestroff; 228 int namestroff;
232 int err; 229 int err;
233 230
234 tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); 231 if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
235 if (tag != FDT_BEGIN_NODE) 232 return nextoffset;
236 return -FDT_ERR_BADOFFSET;
237 233
238 namestroff = _find_add_string(fdt, name); 234 namestroff = _fdt_find_add_string(fdt, name);
239 if (namestroff < 0) 235 if (namestroff < 0)
240 return namestroff; 236 return namestroff;
241 237
242 *prop = _fdt_offset_ptr_w(fdt, nextoffset); 238 *prop = _fdt_offset_ptr_w(fdt, nextoffset);
243 proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE); 239 proplen = sizeof(**prop) + FDT_TAGALIGN(len);
244 240
245 err = _blob_splice_struct(fdt, *prop, 0, proplen); 241 err = _fdt_splice_struct(fdt, *prop, 0, proplen);
246 if (err) 242 if (err)
247 return err; 243 return err;
248 244
@@ -252,18 +248,40 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
252 return 0; 248 return 0;
253} 249}
254 250
251int fdt_set_name(void *fdt, int nodeoffset, const char *name)
252{
253 char *namep;
254 int oldlen, newlen;
255 int err;
256
257 FDT_RW_CHECK_HEADER(fdt);
258
259 namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
260 if (!namep)
261 return oldlen;
262
263 newlen = strlen(name);
264
265 err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
266 FDT_TAGALIGN(newlen+1));
267 if (err)
268 return err;
269
270 memcpy(namep, name, newlen+1);
271 return 0;
272}
273
255int fdt_setprop(void *fdt, int nodeoffset, const char *name, 274int fdt_setprop(void *fdt, int nodeoffset, const char *name,
256 const void *val, int len) 275 const void *val, int len)
257{ 276{
258 struct fdt_property *prop; 277 struct fdt_property *prop;
259 int err; 278 int err;
260 279
261 if ((err = rw_check_header(fdt))) 280 FDT_RW_CHECK_HEADER(fdt);
262 return err;
263 281
264 err = _resize_property(fdt, nodeoffset, name, len, &prop); 282 err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
265 if (err == -FDT_ERR_NOTFOUND) 283 if (err == -FDT_ERR_NOTFOUND)
266 err = _add_property(fdt, nodeoffset, name, len, &prop); 284 err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
267 if (err) 285 if (err)
268 return err; 286 return err;
269 287
@@ -276,14 +294,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
276 struct fdt_property *prop; 294 struct fdt_property *prop;
277 int len, proplen; 295 int len, proplen;
278 296
279 RW_CHECK_HEADER(fdt); 297 FDT_RW_CHECK_HEADER(fdt);
280 298
281 prop = fdt_get_property_w(fdt, nodeoffset, name, &len); 299 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
282 if (! prop) 300 if (! prop)
283 return len; 301 return len;
284 302
285 proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE); 303 proplen = sizeof(*prop) + FDT_TAGALIGN(len);
286 return _blob_splice_struct(fdt, prop, proplen, 0); 304 return _fdt_splice_struct(fdt, prop, proplen, 0);
287} 305}
288 306
289int fdt_add_subnode_namelen(void *fdt, int parentoffset, 307int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -296,7 +314,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
296 uint32_t tag; 314 uint32_t tag;
297 uint32_t *endtag; 315 uint32_t *endtag;
298 316
299 RW_CHECK_HEADER(fdt); 317 FDT_RW_CHECK_HEADER(fdt);
300 318
301 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); 319 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
302 if (offset >= 0) 320 if (offset >= 0)
@@ -309,19 +327,19 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
309 do { 327 do {
310 offset = nextoffset; 328 offset = nextoffset;
311 tag = fdt_next_tag(fdt, offset, &nextoffset); 329 tag = fdt_next_tag(fdt, offset, &nextoffset);
312 } while (tag == FDT_PROP); 330 } while ((tag == FDT_PROP) || (tag == FDT_NOP));
313 331
314 nh = _fdt_offset_ptr_w(fdt, offset); 332 nh = _fdt_offset_ptr_w(fdt, offset);
315 nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE; 333 nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
316 334
317 err = _blob_splice_struct(fdt, nh, 0, nodelen); 335 err = _fdt_splice_struct(fdt, nh, 0, nodelen);
318 if (err) 336 if (err)
319 return err; 337 return err;
320 338
321 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); 339 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
322 memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE)); 340 memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
323 memcpy(nh->name, name, namelen); 341 memcpy(nh->name, name, namelen);
324 endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE); 342 endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
325 *endtag = cpu_to_fdt32(FDT_END_NODE); 343 *endtag = cpu_to_fdt32(FDT_END_NODE);
326 344
327 return offset; 345 return offset;
@@ -336,36 +354,36 @@ int fdt_del_node(void *fdt, int nodeoffset)
336{ 354{
337 int endoffset; 355 int endoffset;
338 356
339 RW_CHECK_HEADER(fdt); 357 FDT_RW_CHECK_HEADER(fdt);
340 358
341 endoffset = _fdt_node_end_offset(fdt, nodeoffset); 359 endoffset = _fdt_node_end_offset(fdt, nodeoffset);
342 if (endoffset < 0) 360 if (endoffset < 0)
343 return endoffset; 361 return endoffset;
344 362
345 return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), 363 return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
346 endoffset - nodeoffset, 0); 364 endoffset - nodeoffset, 0);
347} 365}
348 366
349static void _packblocks(const void *fdt, void *buf, 367static void _fdt_packblocks(const char *old, char *new,
350 int mem_rsv_size, int struct_size) 368 int mem_rsv_size, int struct_size)
351{ 369{
352 int mem_rsv_off, struct_off, strings_off; 370 int mem_rsv_off, struct_off, strings_off;
353 371
354 mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8); 372 mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
355 struct_off = mem_rsv_off + mem_rsv_size; 373 struct_off = mem_rsv_off + mem_rsv_size;
356 strings_off = struct_off + struct_size; 374 strings_off = struct_off + struct_size;
357 375
358 memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size); 376 memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
359 fdt_set_off_mem_rsvmap(buf, mem_rsv_off); 377 fdt_set_off_mem_rsvmap(new, mem_rsv_off);
360 378
361 memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size); 379 memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
362 fdt_set_off_dt_struct(buf, struct_off); 380 fdt_set_off_dt_struct(new, struct_off);
363 fdt_set_size_dt_struct(buf, struct_size); 381 fdt_set_size_dt_struct(new, struct_size);
364 382
365 memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt), 383 memmove(new + strings_off, old + fdt_off_dt_strings(old),
366 fdt_size_dt_strings(fdt)); 384 fdt_size_dt_strings(old));
367 fdt_set_off_dt_strings(buf, strings_off); 385 fdt_set_off_dt_strings(new, strings_off);
368 fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt)); 386 fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
369} 387}
370 388
371int fdt_open_into(const void *fdt, void *buf, int bufsize) 389int fdt_open_into(const void *fdt, void *buf, int bufsize)
@@ -373,11 +391,11 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
373 int err; 391 int err;
374 int mem_rsv_size, struct_size; 392 int mem_rsv_size, struct_size;
375 int newsize; 393 int newsize;
376 void *tmp; 394 const char *fdtstart = fdt;
395 const char *fdtend = fdtstart + fdt_totalsize(fdt);
396 char *tmp;
377 397
378 err = fdt_check_header(fdt); 398 FDT_CHECK_HEADER(fdt);
379 if (err)
380 return err;
381 399
382 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) 400 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
383 * sizeof(struct fdt_reserve_entry); 401 * sizeof(struct fdt_reserve_entry);
@@ -390,7 +408,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
390 ; 408 ;
391 } 409 }
392 410
393 if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) { 411 if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
394 /* no further work necessary */ 412 /* no further work necessary */
395 err = fdt_move(fdt, buf, bufsize); 413 err = fdt_move(fdt, buf, bufsize);
396 if (err) 414 if (err)
@@ -402,22 +420,23 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
402 } 420 }
403 421
404 /* Need to reorder */ 422 /* Need to reorder */
405 newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size 423 newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
406 + struct_size + fdt_size_dt_strings(fdt); 424 + struct_size + fdt_size_dt_strings(fdt);
407 425
408 if (bufsize < newsize) 426 if (bufsize < newsize)
409 return -FDT_ERR_NOSPACE; 427 return -FDT_ERR_NOSPACE;
410 428
411 if (((buf + newsize) <= fdt) 429 /* First attempt to build converted tree at beginning of buffer */
412 || (buf >= (fdt + fdt_totalsize(fdt)))) { 430 tmp = buf;
413 tmp = buf; 431 /* But if that overlaps with the old tree... */
414 } else { 432 if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
415 tmp = (void *)fdt + fdt_totalsize(fdt); 433 /* Try right after the old tree instead */
416 if ((tmp + newsize) > (buf + bufsize)) 434 tmp = (char *)(uintptr_t)fdtend;
435 if ((tmp + newsize) > ((char *)buf + bufsize))
417 return -FDT_ERR_NOSPACE; 436 return -FDT_ERR_NOSPACE;
418 } 437 }
419 438
420 _packblocks(fdt, tmp, mem_rsv_size, struct_size); 439 _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
421 memmove(buf, tmp, newsize); 440 memmove(buf, tmp, newsize);
422 441
423 fdt_set_magic(buf, FDT_MAGIC); 442 fdt_set_magic(buf, FDT_MAGIC);
@@ -432,16 +451,13 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
432int fdt_pack(void *fdt) 451int fdt_pack(void *fdt)
433{ 452{
434 int mem_rsv_size; 453 int mem_rsv_size;
435 int err;
436 454
437 err = rw_check_header(fdt); 455 FDT_RW_CHECK_HEADER(fdt);
438 if (err)
439 return err;
440 456
441 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) 457 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
442 * sizeof(struct fdt_reserve_entry); 458 * sizeof(struct fdt_reserve_entry);
443 _packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); 459 _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
444 fdt_set_totalsize(fdt, _blob_data_size(fdt)); 460 fdt_set_totalsize(fdt, _fdt_data_size(fdt));
445 461
446 return 0; 462 return 0;
447} 463}
diff --git a/arch/powerpc/boot/libfdt/fdt_strerror.c b/arch/powerpc/boot/libfdt/fdt_strerror.c
index f9d32ef5360..e6c3ceee8c5 100644
--- a/arch/powerpc/boot/libfdt/fdt_strerror.c
+++ b/arch/powerpc/boot/libfdt/fdt_strerror.c
@@ -55,29 +55,29 @@
55 55
56#include "libfdt_internal.h" 56#include "libfdt_internal.h"
57 57
58struct errtabent { 58struct fdt_errtabent {
59 const char *str; 59 const char *str;
60}; 60};
61 61
62#define ERRTABENT(val) \ 62#define FDT_ERRTABENT(val) \
63 [(val)] = { .str = #val, } 63 [(val)] = { .str = #val, }
64 64
65static struct errtabent errtable[] = { 65static struct fdt_errtabent fdt_errtable[] = {
66 ERRTABENT(FDT_ERR_NOTFOUND), 66 FDT_ERRTABENT(FDT_ERR_NOTFOUND),
67 ERRTABENT(FDT_ERR_EXISTS), 67 FDT_ERRTABENT(FDT_ERR_EXISTS),
68 ERRTABENT(FDT_ERR_NOSPACE), 68 FDT_ERRTABENT(FDT_ERR_NOSPACE),
69 69
70 ERRTABENT(FDT_ERR_BADOFFSET), 70 FDT_ERRTABENT(FDT_ERR_BADOFFSET),
71 ERRTABENT(FDT_ERR_BADPATH), 71 FDT_ERRTABENT(FDT_ERR_BADPATH),
72 ERRTABENT(FDT_ERR_BADSTATE), 72 FDT_ERRTABENT(FDT_ERR_BADSTATE),
73 73
74 ERRTABENT(FDT_ERR_TRUNCATED), 74 FDT_ERRTABENT(FDT_ERR_TRUNCATED),
75 ERRTABENT(FDT_ERR_BADMAGIC), 75 FDT_ERRTABENT(FDT_ERR_BADMAGIC),
76 ERRTABENT(FDT_ERR_BADVERSION), 76 FDT_ERRTABENT(FDT_ERR_BADVERSION),
77 ERRTABENT(FDT_ERR_BADSTRUCTURE), 77 FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
78 ERRTABENT(FDT_ERR_BADLAYOUT), 78 FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
79}; 79};
80#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0])) 80#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
81 81
82const char *fdt_strerror(int errval) 82const char *fdt_strerror(int errval)
83{ 83{
@@ -85,8 +85,8 @@ const char *fdt_strerror(int errval)
85 return "<valid offset/length>"; 85 return "<valid offset/length>";
86 else if (errval == 0) 86 else if (errval == 0)
87 return "<no error>"; 87 return "<no error>";
88 else if (errval > -ERRTABSIZE) { 88 else if (errval > -FDT_ERRTABSIZE) {
89 const char *s = errtable[-errval].str; 89 const char *s = fdt_errtable[-errval].str;
90 90
91 if (s) 91 if (s)
92 return s; 92 return s;
diff --git a/arch/powerpc/boot/libfdt/fdt_sw.c b/arch/powerpc/boot/libfdt/fdt_sw.c
index dda2de34b2e..698329e0cca 100644
--- a/arch/powerpc/boot/libfdt/fdt_sw.c
+++ b/arch/powerpc/boot/libfdt/fdt_sw.c
@@ -55,14 +55,22 @@
55 55
56#include "libfdt_internal.h" 56#include "libfdt_internal.h"
57 57
58static int check_header_sw(void *fdt) 58static int _fdt_sw_check_header(void *fdt)
59{ 59{
60 if (fdt_magic(fdt) != SW_MAGIC) 60 if (fdt_magic(fdt) != FDT_SW_MAGIC)
61 return -FDT_ERR_BADMAGIC; 61 return -FDT_ERR_BADMAGIC;
62 /* FIXME: should check more details about the header state */
62 return 0; 63 return 0;
63} 64}
64 65
65static void *grab_space(void *fdt, int len) 66#define FDT_SW_CHECK_HEADER(fdt) \
67 { \
68 int err; \
69 if ((err = _fdt_sw_check_header(fdt)) != 0) \
70 return err; \
71 }
72
73static void *_fdt_grab_space(void *fdt, int len)
66{ 74{
67 int offset = fdt_size_dt_struct(fdt); 75 int offset = fdt_size_dt_struct(fdt);
68 int spaceleft; 76 int spaceleft;
@@ -86,13 +94,13 @@ int fdt_create(void *buf, int bufsize)
86 94
87 memset(buf, 0, bufsize); 95 memset(buf, 0, bufsize);
88 96
89 fdt_set_magic(fdt, SW_MAGIC); 97 fdt_set_magic(fdt, FDT_SW_MAGIC);
90 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); 98 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
91 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); 99 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
92 fdt_set_totalsize(fdt, bufsize); 100 fdt_set_totalsize(fdt, bufsize);
93 101
94 fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header), 102 fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
95 sizeof(struct fdt_reserve_entry))); 103 sizeof(struct fdt_reserve_entry)));
96 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); 104 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
97 fdt_set_off_dt_strings(fdt, bufsize); 105 fdt_set_off_dt_strings(fdt, bufsize);
98 106
@@ -102,11 +110,10 @@ int fdt_create(void *buf, int bufsize)
102int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) 110int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
103{ 111{
104 struct fdt_reserve_entry *re; 112 struct fdt_reserve_entry *re;
105 int err = check_header_sw(fdt);
106 int offset; 113 int offset;
107 114
108 if (err) 115 FDT_SW_CHECK_HEADER(fdt);
109 return err; 116
110 if (fdt_size_dt_struct(fdt)) 117 if (fdt_size_dt_struct(fdt))
111 return -FDT_ERR_BADSTATE; 118 return -FDT_ERR_BADSTATE;
112 119
@@ -114,7 +121,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
114 if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) 121 if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
115 return -FDT_ERR_NOSPACE; 122 return -FDT_ERR_NOSPACE;
116 123
117 re = (struct fdt_reserve_entry *)(fdt + offset); 124 re = (struct fdt_reserve_entry *)((char *)fdt + offset);
118 re->address = cpu_to_fdt64(addr); 125 re->address = cpu_to_fdt64(addr);
119 re->size = cpu_to_fdt64(size); 126 re->size = cpu_to_fdt64(size);
120 127
@@ -131,13 +138,11 @@ int fdt_finish_reservemap(void *fdt)
131int fdt_begin_node(void *fdt, const char *name) 138int fdt_begin_node(void *fdt, const char *name)
132{ 139{
133 struct fdt_node_header *nh; 140 struct fdt_node_header *nh;
134 int err = check_header_sw(fdt);
135 int namelen = strlen(name) + 1; 141 int namelen = strlen(name) + 1;
136 142
137 if (err) 143 FDT_SW_CHECK_HEADER(fdt);
138 return err;
139 144
140 nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE)); 145 nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
141 if (! nh) 146 if (! nh)
142 return -FDT_ERR_NOSPACE; 147 return -FDT_ERR_NOSPACE;
143 148
@@ -149,12 +154,10 @@ int fdt_begin_node(void *fdt, const char *name)
149int fdt_end_node(void *fdt) 154int fdt_end_node(void *fdt)
150{ 155{
151 uint32_t *en; 156 uint32_t *en;
152 int err = check_header_sw(fdt);
153 157
154 if (err) 158 FDT_SW_CHECK_HEADER(fdt);
155 return err;
156 159
157 en = grab_space(fdt, FDT_TAGSIZE); 160 en = _fdt_grab_space(fdt, FDT_TAGSIZE);
158 if (! en) 161 if (! en)
159 return -FDT_ERR_NOSPACE; 162 return -FDT_ERR_NOSPACE;
160 163
@@ -162,7 +165,7 @@ int fdt_end_node(void *fdt)
162 return 0; 165 return 0;
163} 166}
164 167
165static int find_add_string(void *fdt, const char *s) 168static int _fdt_find_add_string(void *fdt, const char *s)
166{ 169{
167 char *strtab = (char *)fdt + fdt_totalsize(fdt); 170 char *strtab = (char *)fdt + fdt_totalsize(fdt);
168 const char *p; 171 const char *p;
@@ -188,17 +191,15 @@ static int find_add_string(void *fdt, const char *s)
188int fdt_property(void *fdt, const char *name, const void *val, int len) 191int fdt_property(void *fdt, const char *name, const void *val, int len)
189{ 192{
190 struct fdt_property *prop; 193 struct fdt_property *prop;
191 int err = check_header_sw(fdt);
192 int nameoff; 194 int nameoff;
193 195
194 if (err) 196 FDT_SW_CHECK_HEADER(fdt);
195 return err;
196 197
197 nameoff = find_add_string(fdt, name); 198 nameoff = _fdt_find_add_string(fdt, name);
198 if (nameoff == 0) 199 if (nameoff == 0)
199 return -FDT_ERR_NOSPACE; 200 return -FDT_ERR_NOSPACE;
200 201
201 prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE)); 202 prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
202 if (! prop) 203 if (! prop)
203 return -FDT_ERR_NOSPACE; 204 return -FDT_ERR_NOSPACE;
204 205
@@ -211,18 +212,16 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
211 212
212int fdt_finish(void *fdt) 213int fdt_finish(void *fdt)
213{ 214{
214 int err = check_header_sw(fdt);
215 char *p = (char *)fdt; 215 char *p = (char *)fdt;
216 uint32_t *end; 216 uint32_t *end;
217 int oldstroffset, newstroffset; 217 int oldstroffset, newstroffset;
218 uint32_t tag; 218 uint32_t tag;
219 int offset, nextoffset; 219 int offset, nextoffset;
220 220
221 if (err) 221 FDT_SW_CHECK_HEADER(fdt);
222 return err;
223 222
224 /* Add terminator */ 223 /* Add terminator */
225 end = grab_space(fdt, sizeof(*end)); 224 end = _fdt_grab_space(fdt, sizeof(*end));
226 if (! end) 225 if (! end)
227 return -FDT_ERR_NOSPACE; 226 return -FDT_ERR_NOSPACE;
228 *end = cpu_to_fdt32(FDT_END); 227 *end = cpu_to_fdt32(FDT_END);
diff --git a/arch/powerpc/boot/libfdt/fdt_wip.c b/arch/powerpc/boot/libfdt/fdt_wip.c
index 88e24b8318f..a4652c6e787 100644
--- a/arch/powerpc/boot/libfdt/fdt_wip.c
+++ b/arch/powerpc/boot/libfdt/fdt_wip.c
@@ -72,11 +72,11 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
72 return 0; 72 return 0;
73} 73}
74 74
75static void nop_region(void *start, int len) 75static void _fdt_nop_region(void *start, int len)
76{ 76{
77 uint32_t *p; 77 uint32_t *p;
78 78
79 for (p = start; (void *)p < (start + len); p++) 79 for (p = start; (char *)p < ((char *)start + len); p++)
80 *p = cpu_to_fdt32(FDT_NOP); 80 *p = cpu_to_fdt32(FDT_NOP);
81} 81}
82 82
@@ -89,7 +89,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
89 if (! prop) 89 if (! prop)
90 return len; 90 return len;
91 91
92 nop_region(prop, len + sizeof(*prop)); 92 _fdt_nop_region(prop, len + sizeof(*prop));
93 93
94 return 0; 94 return 0;
95} 95}
@@ -139,6 +139,7 @@ int fdt_nop_node(void *fdt, int nodeoffset)
139 if (endoffset < 0) 139 if (endoffset < 0)
140 return endoffset; 140 return endoffset;
141 141
142 nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset); 142 _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
143 endoffset - nodeoffset);
143 return 0; 144 return 0;
144} 145}
diff --git a/arch/powerpc/boot/libfdt/libfdt.h b/arch/powerpc/boot/libfdt/libfdt.h
index 6b2fb92ea35..ce80e4fb41b 100644
--- a/arch/powerpc/boot/libfdt/libfdt.h
+++ b/arch/powerpc/boot/libfdt/libfdt.h
@@ -125,12 +125,18 @@
125const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); 125const void *fdt_offset_ptr(const void *fdt, int offset, 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 *)fdt_offset_ptr(fdt, offset, checklen); 128 return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
129} 129}
130 130
131uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); 131uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
132 132
133/**********************************************************************/ 133/**********************************************************************/
134/* Traversal functions */
135/**********************************************************************/
136
137int fdt_next_node(const void *fdt, int offset, int *depth);
138
139/**********************************************************************/
134/* General functions */ 140/* General functions */
135/**********************************************************************/ 141/**********************************************************************/
136 142
@@ -207,7 +213,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
207/**********************************************************************/ 213/**********************************************************************/
208 214
209/** 215/**
210 * fdt_string - retreive a string from the strings block of a device tree 216 * fdt_string - retrieve a string from the strings block of a device tree
211 * @fdt: pointer to the device tree blob 217 * @fdt: pointer to the device tree blob
212 * @stroffset: offset of the string within the strings block (native endian) 218 * @stroffset: offset of the string within the strings block (native endian)
213 * 219 *
@@ -221,7 +227,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
221const char *fdt_string(const void *fdt, int stroffset); 227const char *fdt_string(const void *fdt, int stroffset);
222 228
223/** 229/**
224 * fdt_num_mem_rsv - retreive the number of memory reserve map entries 230 * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
225 * @fdt: pointer to the device tree blob 231 * @fdt: pointer to the device tree blob
226 * 232 *
227 * 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,7 +240,7 @@ const char *fdt_string(const void *fdt, int stroffset);
234int fdt_num_mem_rsv(const void *fdt); 240int fdt_num_mem_rsv(const void *fdt);
235 241
236/** 242/**
237 * fdt_get_mem_rsv - retreive one memory reserve map entry 243 * fdt_get_mem_rsv - retrieve one memory reserve map entry
238 * @fdt: pointer to the device tree blob 244 * @fdt: pointer to the device tree blob
239 * @address, @size: pointers to 64-bit variables 245 * @address, @size: pointers to 64-bit variables
240 * 246 *
@@ -314,7 +320,7 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
314int fdt_path_offset(const void *fdt, const char *path); 320int fdt_path_offset(const void *fdt, const char *path);
315 321
316/** 322/**
317 * fdt_get_name - retreive the name of a given node 323 * fdt_get_name - retrieve the name of a given node
318 * @fdt: pointer to the device tree blob 324 * @fdt: pointer to the device tree blob
319 * @nodeoffset: structure block offset of the starting node 325 * @nodeoffset: structure block offset of the starting node
320 * @lenp: pointer to an integer variable (will be overwritten) or NULL 326 * @lenp: pointer to an integer variable (will be overwritten) or NULL
@@ -346,7 +352,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
346 * fdt_get_property() retrieves a pointer to the fdt_property 352 * fdt_get_property() retrieves a pointer to the fdt_property
347 * structure within the device tree blob corresponding to the property 353 * structure within the device tree blob corresponding to the property
348 * named 'name' of the node at offset nodeoffset. If lenp is 354 * named 'name' of the node at offset nodeoffset. If lenp is
349 * non-NULL, the length of the property value also returned, in the 355 * non-NULL, the length of the property value is also returned, in the
350 * integer pointed to by lenp. 356 * integer pointed to by lenp.
351 * 357 *
352 * returns: 358 * returns:
@@ -369,8 +375,8 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
369 const char *name, 375 const char *name,
370 int *lenp) 376 int *lenp)
371{ 377{
372 return (struct fdt_property *)fdt_get_property(fdt, nodeoffset, 378 return (struct fdt_property *)(uintptr_t)
373 name, lenp); 379 fdt_get_property(fdt, nodeoffset, name, lenp);
374} 380}
375 381
376/** 382/**
@@ -383,7 +389,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
383 * fdt_getprop() retrieves a pointer to the value of the property 389 * fdt_getprop() retrieves a pointer to the value of the property
384 * named 'name' of the node at offset nodeoffset (this will be a 390 * named 'name' of the node at offset nodeoffset (this will be a
385 * pointer to within the device blob itself, not a copy of the value). 391 * pointer to within the device blob itself, not a copy of the value).
386 * If lenp is non-NULL, the length of the property value also 392 * If lenp is non-NULL, the length of the property value is also
387 * returned, in the integer pointed to by lenp. 393 * returned, in the integer pointed to by lenp.
388 * 394 *
389 * returns: 395 * returns:
@@ -405,11 +411,11 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
405static inline void *fdt_getprop_w(void *fdt, int nodeoffset, 411static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
406 const char *name, int *lenp) 412 const char *name, int *lenp)
407{ 413{
408 return (void *)fdt_getprop(fdt, nodeoffset, name, lenp); 414 return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
409} 415}
410 416
411/** 417/**
412 * fdt_get_phandle - retreive the phandle of a given node 418 * fdt_get_phandle - retrieve the phandle of a given node
413 * @fdt: pointer to the device tree blob 419 * @fdt: pointer to the device tree blob
414 * @nodeoffset: structure block offset of the node 420 * @nodeoffset: structure block offset of the node
415 * 421 *
@@ -417,7 +423,7 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
417 * structure block offset nodeoffset. 423 * structure block offset nodeoffset.
418 * 424 *
419 * returns: 425 * returns:
420 * the phandle of the node at nodeoffset, on succes (!= 0, != -1) 426 * the phandle of the node at nodeoffset, on success (!= 0, != -1)
421 * 0, if the node has no phandle, or another error occurs 427 * 0, if the node has no phandle, or another error occurs
422 */ 428 */
423uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); 429uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
@@ -516,7 +522,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
516 * structure from the start to nodeoffset, *twice*. 522 * structure from the start to nodeoffset, *twice*.
517 * 523 *
518 * returns: 524 * returns:
519 * stucture block offset of the parent of the node at nodeoffset 525 * structure block offset of the parent of the node at nodeoffset
520 * (>=0), on success 526 * (>=0), on success
521 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 527 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
522 * -FDT_ERR_BADMAGIC, 528 * -FDT_ERR_BADMAGIC,
@@ -573,7 +579,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
573 * @fdt: pointer to the device tree blob 579 * @fdt: pointer to the device tree blob
574 * @phandle: phandle value 580 * @phandle: phandle value
575 * 581 *
576 * fdt_node_offset_by_prop_value() returns the offset of the node 582 * fdt_node_offset_by_phandle() returns the offset of the node
577 * which has the given phandle value. If there is more than one node 583 * which has the given phandle value. If there is more than one node
578 * in the tree with the given phandle (an invalid tree), results are 584 * in the tree with the given phandle (an invalid tree), results are
579 * undefined. 585 * undefined.
@@ -655,8 +661,65 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
655/* Write-in-place functions */ 661/* Write-in-place functions */
656/**********************************************************************/ 662/**********************************************************************/
657 663
664/**
665 * fdt_setprop_inplace - change a property's value, but not its size
666 * @fdt: pointer to the device tree blob
667 * @nodeoffset: offset of the node whose property to change
668 * @name: name of the property to change
669 * @val: pointer to data to replace the property value with
670 * @len: length of the property value
671 *
672 * fdt_setprop_inplace() replaces the value of a given property with
673 * the data in val, of length len. This function cannot change the
674 * size of a property, and so will only work if len is equal to the
675 * current length of the property.
676 *
677 * This function will alter only the bytes in the blob which contain
678 * the given property value, and will not alter or move any other part
679 * of the tree.
680 *
681 * returns:
682 * 0, on success
683 * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
684 * -FDT_ERR_NOTFOUND, node does not have the named property
685 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
686 * -FDT_ERR_BADMAGIC,
687 * -FDT_ERR_BADVERSION,
688 * -FDT_ERR_BADSTATE,
689 * -FDT_ERR_BADSTRUCTURE,
690 * -FDT_ERR_TRUNCATED, standard meanings
691 */
658int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, 692int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
659 const void *val, int len); 693 const void *val, int len);
694
695/**
696 * fdt_setprop_inplace_cell - change the value of a single-cell property
697 * @fdt: pointer to the device tree blob
698 * @nodeoffset: offset of the node whose property to change
699 * @name: name of the property to change
700 * @val: cell (32-bit integer) value to replace the property with
701 *
702 * fdt_setprop_inplace_cell() replaces the value of a given property
703 * with the 32-bit integer cell value in val, converting val to
704 * big-endian if necessary. This function cannot change the size of a
705 * property, and so will only work if the property already exists and
706 * has length 4.
707 *
708 * This function will alter only the bytes in the blob which contain
709 * the given property value, and will not alter or move any other part
710 * of the tree.
711 *
712 * returns:
713 * 0, on success
714 * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
715 * -FDT_ERR_NOTFOUND, node does not have the named property
716 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
717 * -FDT_ERR_BADMAGIC,
718 * -FDT_ERR_BADVERSION,
719 * -FDT_ERR_BADSTATE,
720 * -FDT_ERR_BADSTRUCTURE,
721 * -FDT_ERR_TRUNCATED, standard meanings
722 */
660static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, 723static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
661 const char *name, uint32_t val) 724 const char *name, uint32_t val)
662{ 725{
@@ -664,7 +727,54 @@ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
664 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); 727 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
665} 728}
666 729
730/**
731 * fdt_nop_property - replace a property with nop tags
732 * @fdt: pointer to the device tree blob
733 * @nodeoffset: offset of the node whose property to nop
734 * @name: name of the property to nop
735 *
736 * fdt_nop_property() will replace a given property's representation
737 * in the blob with FDT_NOP tags, effectively removing it from the
738 * tree.
739 *
740 * This function will alter only the bytes in the blob which contain
741 * the property, and will not alter or move any other part of the
742 * tree.
743 *
744 * returns:
745 * 0, on success
746 * -FDT_ERR_NOTFOUND, node does not have the named property
747 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
748 * -FDT_ERR_BADMAGIC,
749 * -FDT_ERR_BADVERSION,
750 * -FDT_ERR_BADSTATE,
751 * -FDT_ERR_BADSTRUCTURE,
752 * -FDT_ERR_TRUNCATED, standard meanings
753 */
667int fdt_nop_property(void *fdt, int nodeoffset, const char *name); 754int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
755
756/**
757 * fdt_nop_node - replace a node (subtree) with nop tags
758 * @fdt: pointer to the device tree blob
759 * @nodeoffset: offset of the node to nop
760 *
761 * fdt_nop_node() will replace a given node's representation in the
762 * blob, including all its subnodes, if any, with FDT_NOP tags,
763 * effectively removing it from the tree.
764 *
765 * This function will alter only the bytes in the blob which contain
766 * the node and its properties and subnodes, and will not alter or
767 * move any other part of the tree.
768 *
769 * returns:
770 * 0, on success
771 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
772 * -FDT_ERR_BADMAGIC,
773 * -FDT_ERR_BADVERSION,
774 * -FDT_ERR_BADSTATE,
775 * -FDT_ERR_BADSTRUCTURE,
776 * -FDT_ERR_TRUNCATED, standard meanings
777 */
668int fdt_nop_node(void *fdt, int nodeoffset); 778int fdt_nop_node(void *fdt, int nodeoffset);
669 779
670/**********************************************************************/ 780/**********************************************************************/
@@ -693,23 +803,268 @@ int fdt_finish(void *fdt);
693int fdt_open_into(const void *fdt, void *buf, int bufsize); 803int fdt_open_into(const void *fdt, void *buf, int bufsize);
694int fdt_pack(void *fdt); 804int fdt_pack(void *fdt);
695 805
806/**
807 * fdt_add_mem_rsv - add one memory reserve map entry
808 * @fdt: pointer to the device tree blob
809 * @address, @size: 64-bit values (native endian)
810 *
811 * Adds a reserve map entry to the given blob reserving a region at
812 * address address of length size.
813 *
814 * This function will insert data into the reserve map and will
815 * therefore change the indexes of some entries in the table.
816 *
817 * returns:
818 * 0, on success
819 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
820 * contain the new reservation entry
821 * -FDT_ERR_BADMAGIC,
822 * -FDT_ERR_BADVERSION,
823 * -FDT_ERR_BADSTATE,
824 * -FDT_ERR_BADSTRUCTURE,
825 * -FDT_ERR_BADLAYOUT,
826 * -FDT_ERR_TRUNCATED, standard meanings
827 */
696int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); 828int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
829
830/**
831 * fdt_del_mem_rsv - remove a memory reserve map entry
832 * @fdt: pointer to the device tree blob
833 * @n: entry to remove
834 *
835 * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
836 * the blob.
837 *
838 * This function will delete data from the reservation table and will
839 * therefore change the indexes of some entries in the table.
840 *
841 * returns:
842 * 0, on success
843 * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
844 * are less than n+1 reserve map entries)
845 * -FDT_ERR_BADMAGIC,
846 * -FDT_ERR_BADVERSION,
847 * -FDT_ERR_BADSTATE,
848 * -FDT_ERR_BADSTRUCTURE,
849 * -FDT_ERR_BADLAYOUT,
850 * -FDT_ERR_TRUNCATED, standard meanings
851 */
697int fdt_del_mem_rsv(void *fdt, int n); 852int fdt_del_mem_rsv(void *fdt, int n);
698 853
854/**
855 * fdt_set_name - change the name of a given node
856 * @fdt: pointer to the device tree blob
857 * @nodeoffset: structure block offset of a node
858 * @name: name to give the node
859 *
860 * fdt_set_name() replaces the name (including unit address, if any)
861 * of the given node with the given string. NOTE: this function can't
862 * efficiently check if the new name is unique amongst the given
863 * node's siblings; results are undefined if this function is invoked
864 * with a name equal to one of the given node's siblings.
865 *
866 * This function may insert or delete data from the blob, and will
867 * therefore change the offsets of some existing nodes.
868 *
869 * returns:
870 * 0, on success
871 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
872 * to contain the new name
873 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
874 * -FDT_ERR_BADMAGIC,
875 * -FDT_ERR_BADVERSION,
876 * -FDT_ERR_BADSTATE, standard meanings
877 */
878int fdt_set_name(void *fdt, int nodeoffset, const char *name);
879
880/**
881 * fdt_setprop - create or change a property
882 * @fdt: pointer to the device tree blob
883 * @nodeoffset: offset of the node whose property to change
884 * @name: name of the property to change
885 * @val: pointer to data to set the property value to
886 * @len: length of the property value
887 *
888 * fdt_setprop() sets the value of the named property in the given
889 * node to the given value and length, creating the property if it
890 * does not already exist.
891 *
892 * This function may insert or delete data from the blob, and will
893 * therefore change the offsets of some existing nodes.
894 *
895 * returns:
896 * 0, on success
897 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
898 * contain the new property value
899 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
900 * -FDT_ERR_BADLAYOUT,
901 * -FDT_ERR_BADMAGIC,
902 * -FDT_ERR_BADVERSION,
903 * -FDT_ERR_BADSTATE,
904 * -FDT_ERR_BADSTRUCTURE,
905 * -FDT_ERR_BADLAYOUT,
906 * -FDT_ERR_TRUNCATED, standard meanings
907 */
699int fdt_setprop(void *fdt, int nodeoffset, const char *name, 908int fdt_setprop(void *fdt, int nodeoffset, const char *name,
700 const void *val, int len); 909 const void *val, int len);
910
911/**
912 * fdt_setprop_cell - set a property to a single cell value
913 * @fdt: pointer to the device tree blob
914 * @nodeoffset: offset of the node whose property to change
915 * @name: name of the property to change
916 * @val: 32-bit integer value for the property (native endian)
917 *
918 * fdt_setprop_cell() sets the value of the named property in the
919 * given node to the given cell value (converting to big-endian if
920 * necessary), or creates a new property with that value if it does
921 * not already exist.
922 *
923 * This function may insert or delete data from the blob, and will
924 * therefore change the offsets of some existing nodes.
925 *
926 * returns:
927 * 0, on success
928 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
929 * contain the new property value
930 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
931 * -FDT_ERR_BADLAYOUT,
932 * -FDT_ERR_BADMAGIC,
933 * -FDT_ERR_BADVERSION,
934 * -FDT_ERR_BADSTATE,
935 * -FDT_ERR_BADSTRUCTURE,
936 * -FDT_ERR_BADLAYOUT,
937 * -FDT_ERR_TRUNCATED, standard meanings
938 */
701static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, 939static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
702 uint32_t val) 940 uint32_t val)
703{ 941{
704 val = cpu_to_fdt32(val); 942 val = cpu_to_fdt32(val);
705 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); 943 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
706} 944}
945
946/**
947 * fdt_setprop_string - set a property to a string value
948 * @fdt: pointer to the device tree blob
949 * @nodeoffset: offset of the node whose property to change
950 * @name: name of the property to change
951 * @str: string value for the property
952 *
953 * fdt_setprop_string() sets the value of the named property in the
954 * given node to the given string value (using the length of the
955 * string to determine the new length of the property), or creates a
956 * new property with that value if it does not already exist.
957 *
958 * This function may insert or delete data from the blob, and will
959 * therefore change the offsets of some existing nodes.
960 *
961 * returns:
962 * 0, on success
963 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
964 * contain the new property value
965 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
966 * -FDT_ERR_BADLAYOUT,
967 * -FDT_ERR_BADMAGIC,
968 * -FDT_ERR_BADVERSION,
969 * -FDT_ERR_BADSTATE,
970 * -FDT_ERR_BADSTRUCTURE,
971 * -FDT_ERR_BADLAYOUT,
972 * -FDT_ERR_TRUNCATED, standard meanings
973 */
707#define fdt_setprop_string(fdt, nodeoffset, name, str) \ 974#define fdt_setprop_string(fdt, nodeoffset, name, str) \
708 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) 975 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
976
977/**
978 * fdt_delprop - delete a property
979 * @fdt: pointer to the device tree blob
980 * @nodeoffset: offset of the node whose property to nop
981 * @name: name of the property to nop
982 *
983 * fdt_del_property() will delete the given property.
984 *
985 * This function will delete data from the blob, and will therefore
986 * change the offsets of some existing nodes.
987 *
988 * returns:
989 * 0, on success
990 * -FDT_ERR_NOTFOUND, node does not have the named property
991 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
992 * -FDT_ERR_BADLAYOUT,
993 * -FDT_ERR_BADMAGIC,
994 * -FDT_ERR_BADVERSION,
995 * -FDT_ERR_BADSTATE,
996 * -FDT_ERR_BADSTRUCTURE,
997 * -FDT_ERR_TRUNCATED, standard meanings
998 */
709int fdt_delprop(void *fdt, int nodeoffset, const char *name); 999int fdt_delprop(void *fdt, int nodeoffset, const char *name);
1000
1001/**
1002 * fdt_add_subnode_namelen - creates a new node based on substring
1003 * @fdt: pointer to the device tree blob
1004 * @parentoffset: structure block offset of a node
1005 * @name: name of the subnode to locate
1006 * @namelen: number of characters of name to consider
1007 *
1008 * Identical to fdt_add_subnode(), but use only the first namelen
1009 * characters of name as the name of the new node. This is useful for
1010 * creating subnodes based on a portion of a larger string, such as a
1011 * full path.
1012 */
710int fdt_add_subnode_namelen(void *fdt, int parentoffset, 1013int fdt_add_subnode_namelen(void *fdt, int parentoffset,
711 const char *name, int namelen); 1014 const char *name, int namelen);
1015
1016/**
1017 * fdt_add_subnode - creates a new node
1018 * @fdt: pointer to the device tree blob
1019 * @parentoffset: structure block offset of a node
1020 * @name: name of the subnode to locate
1021 *
1022 * fdt_add_subnode() creates a new node as a subnode of the node at
1023 * structure block offset parentoffset, with the given name (which
1024 * should include the unit address, if any).
1025 *
1026 * This function will insert data into the blob, and will therefore
1027 * change the offsets of some existing nodes.
1028
1029 * returns:
1030 * structure block offset of the created nodeequested subnode (>=0), on success
1031 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
1032 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
1033 * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
1034 * the given name
1035 * -FDT_ERR_NOSPACE, if there is insufficient free space in the
1036 * blob to contain the new node
1037 * -FDT_ERR_NOSPACE
1038 * -FDT_ERR_BADLAYOUT
1039 * -FDT_ERR_BADMAGIC,
1040 * -FDT_ERR_BADVERSION,
1041 * -FDT_ERR_BADSTATE,
1042 * -FDT_ERR_BADSTRUCTURE,
1043 * -FDT_ERR_TRUNCATED, standard meanings.
1044 */
712int fdt_add_subnode(void *fdt, int parentoffset, const char *name); 1045int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
1046
1047/**
1048 * fdt_del_node - delete a node (subtree)
1049 * @fdt: pointer to the device tree blob
1050 * @nodeoffset: offset of the node to nop
1051 *
1052 * fdt_del_node() will remove the given node, including all its
1053 * subnodes if any, from the blob.
1054 *
1055 * This function will delete data from the blob, and will therefore
1056 * change the offsets of some existing nodes.
1057 *
1058 * returns:
1059 * 0, on success
1060 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
1061 * -FDT_ERR_BADLAYOUT,
1062 * -FDT_ERR_BADMAGIC,
1063 * -FDT_ERR_BADVERSION,
1064 * -FDT_ERR_BADSTATE,
1065 * -FDT_ERR_BADSTRUCTURE,
1066 * -FDT_ERR_TRUNCATED, standard meanings
1067 */
713int fdt_del_node(void *fdt, int nodeoffset); 1068int fdt_del_node(void *fdt, int nodeoffset);
714 1069
715/**********************************************************************/ 1070/**********************************************************************/
diff --git a/arch/powerpc/boot/libfdt/libfdt_internal.h b/arch/powerpc/boot/libfdt/libfdt_internal.h
index 1e60936beb5..46eb93e4af5 100644
--- a/arch/powerpc/boot/libfdt/libfdt_internal.h
+++ b/arch/powerpc/boot/libfdt/libfdt_internal.h
@@ -52,38 +52,44 @@
52 */ 52 */
53#include <fdt.h> 53#include <fdt.h>
54 54
55#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) 55#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
56#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) 56#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
57 57
58#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0) 58#define FDT_CHECK_HEADER(fdt) \
59#define streq(p, q) (strcmp((p), (q)) == 0) 59 { \
60 int err; \
61 if ((err = fdt_check_header(fdt)) != 0) \
62 return err; \
63 }
60 64
61uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); 65uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
66int _fdt_check_node_offset(const void *fdt, int offset);
62const 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);
63int _fdt_node_end_offset(void *fdt, int nodeoffset); 68int _fdt_node_end_offset(void *fdt, int nodeoffset);
64 69
65static inline const void *_fdt_offset_ptr(const void *fdt, int offset) 70static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
66{ 71{
67 return fdt + fdt_off_dt_struct(fdt) + offset; 72 return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
68} 73}
69 74
70static inline void *_fdt_offset_ptr_w(void *fdt, int offset) 75static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
71{ 76{
72 return (void *)_fdt_offset_ptr(fdt, offset); 77 return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
73} 78}
74 79
75static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) 80static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
76{ 81{
77 const struct fdt_reserve_entry *rsv_table = 82 const struct fdt_reserve_entry *rsv_table =
78 fdt + fdt_off_mem_rsvmap(fdt); 83 (const struct fdt_reserve_entry *)
84 ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
79 85
80 return rsv_table + n; 86 return rsv_table + n;
81} 87}
82static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) 88static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
83{ 89{
84 return (void *)_fdt_mem_rsv(fdt, n); 90 return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
85} 91}
86 92
87#define SW_MAGIC (~FDT_MAGIC) 93#define FDT_SW_MAGIC (~FDT_MAGIC)
88 94
89#endif /* _LIBFDT_INTERNAL_H */ 95#endif /* _LIBFDT_INTERNAL_H */