aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2007-12-09 22:28:39 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-10 21:46:13 -0500
commit1cade99497c881a8c719df561d1bdc96831ff040 (patch)
treed90f0f9c667c5379f79244d117f4c95299180a05 /arch
parentb76e5e93982f28666aeef1055264f5eac76311b0 (diff)
[POWERPC] Merge libfdt upstream source
This incorporates a copy of dtc libfdt into the kernel source, in arch/powerpc/boot/libfdt. This only imports the upstream sources verbatim, later patches are needed to actually link it into the kernel Makefiles. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/boot/libfdt/Makefile.libfdt14
-rw-r--r--arch/powerpc/boot/libfdt/fdt.c156
-rw-r--r--arch/powerpc/boot/libfdt/fdt.h60
-rw-r--r--arch/powerpc/boot/libfdt/fdt_ro.c583
-rw-r--r--arch/powerpc/boot/libfdt/fdt_rw.c447
-rw-r--r--arch/powerpc/boot/libfdt/fdt_strerror.c96
-rw-r--r--arch/powerpc/boot/libfdt/fdt_sw.c258
-rw-r--r--arch/powerpc/boot/libfdt/fdt_wip.c144
-rw-r--r--arch/powerpc/boot/libfdt/libfdt.h721
-rw-r--r--arch/powerpc/boot/libfdt/libfdt_internal.h89
10 files changed, 2568 insertions, 0 deletions
diff --git a/arch/powerpc/boot/libfdt/Makefile.libfdt b/arch/powerpc/boot/libfdt/Makefile.libfdt
new file mode 100644
index 000000000000..82f9c6a8287b
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/Makefile.libfdt
@@ -0,0 +1,14 @@
1# Makefile.libfdt
2#
3# This is not a complete Makefile of itself. Instead, it is designed to
4# be easily embeddable into other systems of Makefiles.
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
8LIBFDT_EXTRA = libfdt_internal.h
9LIBFDT_LIB = libfdt/libfdt.a
10
11LIBFDT_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
new file mode 100644
index 000000000000..586a36136db2
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt.c
@@ -0,0 +1,156 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 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_check_header(const void *fdt)
59{
60 if (fdt_magic(fdt) == FDT_MAGIC) {
61 /* Complete tree */
62 if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
63 return -FDT_ERR_BADVERSION;
64 if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
65 return -FDT_ERR_BADVERSION;
66 } else if (fdt_magic(fdt) == SW_MAGIC) {
67 /* Unfinished sequential-write blob */
68 if (fdt_size_dt_struct(fdt) == 0)
69 return -FDT_ERR_BADSTATE;
70 } else {
71 return -FDT_ERR_BADMAGIC;
72 }
73
74 return 0;
75}
76
77const void *fdt_offset_ptr(const void *fdt, int offset, int len)
78{
79 const void *p;
80
81 if (fdt_version(fdt) >= 0x11)
82 if (((offset + len) < offset)
83 || ((offset + len) > fdt_size_dt_struct(fdt)))
84 return NULL;
85
86 p = _fdt_offset_ptr(fdt, offset);
87
88 if (p + len < p)
89 return NULL;
90 return p;
91}
92
93uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
94{
95 const uint32_t *tagp, *lenp;
96 uint32_t tag;
97 const char *p;
98
99 if (offset % FDT_TAGSIZE)
100 return -1;
101
102 tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
103 if (! tagp)
104 return FDT_END; /* premature end */
105 tag = fdt32_to_cpu(*tagp);
106 offset += FDT_TAGSIZE;
107
108 switch (tag) {
109 case FDT_BEGIN_NODE:
110 /* skip name */
111 do {
112 p = fdt_offset_ptr(fdt, offset++, 1);
113 } while (p && (*p != '\0'));
114 if (! p)
115 return FDT_END;
116 break;
117 case FDT_PROP:
118 lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
119 if (! lenp)
120 return FDT_END;
121 /* skip name offset, length and value */
122 offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
123 break;
124 }
125
126 if (nextoffset)
127 *nextoffset = ALIGN(offset, FDT_TAGSIZE);
128
129 return tag;
130}
131
132const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
133{
134 int len = strlen(s) + 1;
135 const char *last = strtab + tabsize - len;
136 const char *p;
137
138 for (p = strtab; p <= last; p++)
139 if (memeq(p, s, len))
140 return p;
141 return NULL;
142}
143
144int fdt_move(const void *fdt, void *buf, int bufsize)
145{
146 int err = fdt_check_header(fdt);
147
148 if (err)
149 return err;
150
151 if (fdt_totalsize(fdt) > bufsize)
152 return -FDT_ERR_NOSPACE;
153
154 memmove(buf, fdt, fdt_totalsize(fdt));
155 return 0;
156}
diff --git a/arch/powerpc/boot/libfdt/fdt.h b/arch/powerpc/boot/libfdt/fdt.h
new file mode 100644
index 000000000000..48ccfd910000
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt.h
@@ -0,0 +1,60 @@
1#ifndef _FDT_H
2#define _FDT_H
3
4#ifndef __ASSEMBLY__
5
6struct fdt_header {
7 uint32_t magic; /* magic word FDT_MAGIC */
8 uint32_t totalsize; /* total size of DT block */
9 uint32_t off_dt_struct; /* offset to structure */
10 uint32_t off_dt_strings; /* offset to strings */
11 uint32_t off_mem_rsvmap; /* offset to memory reserve map */
12 uint32_t version; /* format version */
13 uint32_t last_comp_version; /* last compatible version */
14
15 /* version 2 fields below */
16 uint32_t boot_cpuid_phys; /* Which physical CPU id we're
17 booting on */
18 /* version 3 fields below */
19 uint32_t size_dt_strings; /* size of the strings block */
20
21 /* version 17 fields below */
22 uint32_t size_dt_struct; /* size of the structure block */
23};
24
25struct fdt_reserve_entry {
26 uint64_t address;
27 uint64_t size;
28};
29
30struct fdt_node_header {
31 uint32_t tag;
32 char name[0];
33};
34
35struct fdt_property {
36 uint32_t tag;
37 uint32_t len;
38 uint32_t nameoff;
39 char data[0];
40};
41
42#endif /* !__ASSEMBLY */
43
44#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
45#define FDT_TAGSIZE sizeof(uint32_t)
46
47#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
48#define FDT_END_NODE 0x2 /* End node */
49#define FDT_PROP 0x3 /* Property: name off,
50 size, content */
51#define FDT_NOP 0x4 /* nop */
52#define FDT_END 0x9
53
54#define FDT_V1_SIZE (7*sizeof(uint32_t))
55#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t))
56#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t))
57#define FDT_V16_SIZE FDT_V3_SIZE
58#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t))
59
60#endif /* _FDT_H */
diff --git a/arch/powerpc/boot/libfdt/fdt_ro.c b/arch/powerpc/boot/libfdt/fdt_ro.c
new file mode 100644
index 000000000000..12a37d59f96e
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_ro.c
@@ -0,0 +1,583 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 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
58#define CHECK_HEADER(fdt) \
59 { \
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{
68 const char *p = fdt_offset_ptr(fdt, offset, len+1);
69
70 if (! p)
71 /* short match */
72 return 0;
73
74 if (memcmp(p, s, len) != 0)
75 return 0;
76
77 if (p[len] == '\0')
78 return 1;
79 else if (!memchr(s, '@', len) && (p[len] == '@'))
80 return 1;
81 else
82 return 0;
83}
84
85const char *fdt_string(const void *fdt, int stroffset)
86{
87 return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
88}
89
90int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
91{
92 CHECK_HEADER(fdt);
93 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
94 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
95 return 0;
96}
97
98int fdt_num_mem_rsv(const void *fdt)
99{
100 int i = 0;
101
102 while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
103 i++;
104 return i;
105}
106
107int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
108 const char *name, int namelen)
109{
110 int level = 0;
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
141 case FDT_PROP:
142 case FDT_NOP:
143 break;
144
145 default:
146 return -FDT_ERR_BADSTRUCTURE;
147 }
148 } while (level >= 0);
149
150 return -FDT_ERR_NOTFOUND;
151}
152
153int fdt_subnode_offset(const void *fdt, int parentoffset,
154 const char *name)
155{
156 return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
157}
158
159int fdt_path_offset(const void *fdt, const char *path)
160{
161 const char *end = path + strlen(path);
162 const char *p = path;
163 int offset = 0;
164
165 CHECK_HEADER(fdt);
166
167 if (*path != '/')
168 return -FDT_ERR_BADPATH;
169
170 while (*p) {
171 const char *q;
172
173 while (*p == '/')
174 p++;
175 if (! *p)
176 return offset;
177 q = strchr(p, '/');
178 if (! q)
179 q = end;
180
181 offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
182 if (offset < 0)
183 return offset;
184
185 p = q;
186 }
187
188 return offset;
189}
190
191const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
192{
193 const struct fdt_node_header *nh;
194 int err;
195
196 if ((err = fdt_check_header(fdt)) != 0)
197 goto fail;
198
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
204 if (len)
205 *len = strlen(nh->name);
206
207 return nh->name;
208
209 fail:
210 if (len)
211 *len = err;
212 return NULL;
213}
214
215const struct fdt_property *fdt_get_property(const void *fdt,
216 int nodeoffset,
217 const char *name, int *lenp)
218{
219 uint32_t tag;
220 const struct fdt_property *prop;
221 int namestroff;
222 int offset, nextoffset;
223 int err;
224
225 if ((err = fdt_check_header(fdt)) != 0)
226 goto fail;
227
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
236 do {
237 offset = nextoffset;
238
239 tag = fdt_next_tag(fdt, offset, &nextoffset);
240 switch (tag) {
241 case FDT_END:
242 err = -FDT_ERR_TRUNCATED;
243 goto fail;
244
245 case FDT_BEGIN_NODE:
246 case FDT_END_NODE:
247 case FDT_NOP:
248 break;
249
250 case FDT_PROP:
251 err = -FDT_ERR_BADSTRUCTURE;
252 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
253 if (! prop)
254 goto fail;
255 namestroff = fdt32_to_cpu(prop->nameoff);
256 if (streq(fdt_string(fdt, namestroff), name)) {
257 /* Found it! */
258 int len = fdt32_to_cpu(prop->len);
259 prop = fdt_offset_ptr(fdt, offset,
260 sizeof(*prop)+len);
261 if (! prop)
262 goto fail;
263
264 if (lenp)
265 *lenp = len;
266
267 return prop;
268 }
269 break;
270
271 default:
272 err = -FDT_ERR_BADSTRUCTURE;
273 goto fail;
274 }
275 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
276
277 err = -FDT_ERR_NOTFOUND;
278 fail:
279 if (lenp)
280 *lenp = err;
281 return NULL;
282}
283
284const void *fdt_getprop(const void *fdt, int nodeoffset,
285 const char *name, int *lenp)
286{
287 const struct fdt_property *prop;
288
289 prop = fdt_get_property(fdt, nodeoffset, name, lenp);
290 if (! prop)
291 return NULL;
292
293 return prop->data;
294}
295
296uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
297{
298 const uint32_t *php;
299 int len;
300
301 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
302 if (!php || (len != sizeof(*php)))
303 return 0;
304
305 return fdt32_to_cpu(*php);
306}
307
308int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
309{
310 uint32_t tag;
311 int p = 0, overflow = 0;
312 int offset, nextoffset, namelen;
313 const char *name;
314
315 CHECK_HEADER(fdt);
316
317 tag = fdt_next_tag(fdt, 0, &nextoffset);
318 if (tag != FDT_BEGIN_NODE)
319 return -FDT_ERR_BADSTRUCTURE;
320
321 if (buflen < 2)
322 return -FDT_ERR_NOSPACE;
323 buf[0] = '/';
324 p = 1;
325
326 while (nextoffset <= nodeoffset) {
327 offset = nextoffset;
328 tag = fdt_next_tag(fdt, offset, &nextoffset);
329 switch (tag) {
330 case FDT_END:
331 return -FDT_ERR_BADOFFSET;
332
333 case FDT_BEGIN_NODE:
334 name = fdt_get_name(fdt, offset, &namelen);
335 if (!name)
336 return namelen;
337 if (overflow || ((p + namelen + 1) > buflen)) {
338 overflow++;
339 break;
340 }
341 memcpy(buf + p, name, namelen);
342 p += namelen;
343 buf[p++] = '/';
344 break;
345
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
356 case FDT_PROP:
357 case FDT_NOP:
358 break;
359
360 default:
361 return -FDT_ERR_BADSTRUCTURE;
362 }
363 }
364
365 if (overflow)
366 return -FDT_ERR_NOSPACE;
367
368 if (p > 1) /* special case so that root path is "/", not "" */
369 p--;
370 buf[p] = '\0';
371 return p;
372}
373
374int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
375 int supernodedepth, int *nodedepth)
376{
377 int level = -1;
378 uint32_t tag;
379 int offset, nextoffset = 0;
380 int supernodeoffset = -FDT_ERR_INTERNAL;
381
382 CHECK_HEADER(fdt);
383
384 if (supernodedepth < 0)
385 return -FDT_ERR_NOTFOUND;
386
387 do {
388 offset = nextoffset;
389 tag = fdt_next_tag(fdt, offset, &nextoffset);
390 switch (tag) {
391 case FDT_END:
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
404 case FDT_PROP:
405 case FDT_NOP:
406 break;
407
408 default:
409 return -FDT_ERR_BADSTRUCTURE;
410 }
411 } while (offset < nodeoffset);
412
413 if (nodedepth)
414 *nodedepth = level;
415
416 if (supernodedepth > level)
417 return -FDT_ERR_NOTFOUND;
418 return supernodeoffset;
419}
420
421int fdt_node_depth(const void *fdt, int nodeoffset)
422{
423 int nodedepth;
424 int err;
425
426 err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
427 if (err)
428 return (err < 0) ? err : -FDT_ERR_INTERNAL;
429 return nodedepth;
430}
431
432int fdt_parent_offset(const void *fdt, int nodeoffset)
433{
434 int nodedepth = fdt_node_depth(fdt, nodeoffset);
435
436 if (nodedepth < 0)
437 return nodedepth;
438 return fdt_supernode_atdepth_offset(fdt, nodeoffset,
439 nodedepth - 1, NULL);
440}
441
442int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
443 const char *propname,
444 const void *propval, int proplen)
445{
446 uint32_t tag;
447 int offset, nextoffset;
448 const void *val;
449 int len;
450
451 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
461 /* FIXME: The algorithm here is pretty horrible: we scan each
462 * 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
464 * to the next node. Still it's the easiest to implement
465 * approach; performance can come later. */
466 do {
467 offset = nextoffset;
468 tag = fdt_next_tag(fdt, offset, &nextoffset);
469
470 switch (tag) {
471 case FDT_BEGIN_NODE:
472 val = fdt_getprop(fdt, offset, propname, &len);
473 if (val
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
490 return -FDT_ERR_NOTFOUND;
491}
492
493int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
494{
495 if ((phandle == 0) || (phandle == -1))
496 return -FDT_ERR_BADPHANDLE;
497 phandle = cpu_to_fdt32(phandle);
498 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
499 &phandle, sizeof(phandle));
500}
501
502int _stringlist_contains(const void *strlist, int listlen, const char *str)
503{
504 int len = strlen(str);
505 const void *p;
506
507 while (listlen >= len) {
508 if (memcmp(str, strlist, len+1) == 0)
509 return 1;
510 p = memchr(strlist, '\0', listlen);
511 if (!p)
512 return 0; /* malformed strlist.. */
513 listlen -= (p-strlist) + 1;
514 strlist = p + 1;
515 }
516 return 0;
517}
518
519int fdt_node_check_compatible(const void *fdt, int nodeoffset,
520 const char *compatible)
521{
522 const void *prop;
523 int len;
524
525 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
526 if (!prop)
527 return len;
528 if (_stringlist_contains(prop, len, compatible))
529 return 0;
530 else
531 return 1;
532}
533
534int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
535 const char *compatible)
536{
537 uint32_t tag;
538 int offset, nextoffset;
539 int err;
540
541 CHECK_HEADER(fdt);
542
543 if (startoffset >= 0) {
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
551 /* FIXME: The algorithm here is pretty horrible: we scan each
552 * property of a node in fdt_node_check_compatible(), then if
553 * 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
555 * implement approach; performance can come later. */
556 do {
557 offset = nextoffset;
558 tag = fdt_next_tag(fdt, offset, &nextoffset);
559
560 switch (tag) {
561 case FDT_BEGIN_NODE:
562 err = fdt_node_check_compatible(fdt, offset,
563 compatible);
564 if ((err < 0)
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
582 return -FDT_ERR_NOTFOUND;
583}
diff --git a/arch/powerpc/boot/libfdt/fdt_rw.c b/arch/powerpc/boot/libfdt/fdt_rw.c
new file mode 100644
index 000000000000..6673f8ec962a
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_rw.c
@@ -0,0 +1,447 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 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
58static int _blocks_misordered(const void *fdt,
59 int mem_rsv_size, int struct_size)
60{
61 return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8))
62 || (fdt_off_dt_struct(fdt) <
63 (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
64 || (fdt_off_dt_strings(fdt) <
65 (fdt_off_dt_struct(fdt) + struct_size))
66 || (fdt_totalsize(fdt) <
67 (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
68}
69
70static int rw_check_header(void *fdt)
71{
72 int err;
73
74 if ((err = fdt_check_header(fdt)))
75 return err;
76 if (fdt_version(fdt) < 17)
77 return -FDT_ERR_BADVERSION;
78 if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
79 fdt_size_dt_struct(fdt)))
80 return -FDT_ERR_BADLAYOUT;
81 if (fdt_version(fdt) > 17)
82 fdt_set_version(fdt, 17);
83
84 return 0;
85}
86
87#define RW_CHECK_HEADER(fdt) \
88 { \
89 int err; \
90 if ((err = rw_check_header(fdt)) != 0) \
91 return err; \
92 }
93
94static inline int _blob_data_size(void *fdt)
95{
96 return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
97}
98
99static int _blob_splice(void *fdt, void *p, int oldlen, int newlen)
100{
101 void *end = fdt + _blob_data_size(fdt);
102
103 if (((p + oldlen) < p) || ((p + oldlen) > end))
104 return -FDT_ERR_BADOFFSET;
105 if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt)))
106 return -FDT_ERR_NOSPACE;
107 memmove(p + newlen, p + oldlen, end - p - oldlen);
108 return 0;
109}
110
111static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
112 int oldn, int newn)
113{
114 int delta = (newn - oldn) * sizeof(*p);
115 int err;
116 err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
117 if (err)
118 return err;
119 fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
120 fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
121 return 0;
122}
123
124static int _blob_splice_struct(void *fdt, void *p,
125 int oldlen, int newlen)
126{
127 int delta = newlen - oldlen;
128 int err;
129
130 if ((err = _blob_splice(fdt, p, oldlen, newlen)))
131 return err;
132
133 fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
134 fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
135 return 0;
136}
137
138static int _blob_splice_string(void *fdt, int newlen)
139{
140 void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
141 int err;
142
143 if ((err = _blob_splice(fdt, p, 0, newlen)))
144 return err;
145
146 fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
147 return 0;
148}
149
150static int _find_add_string(void *fdt, const char *s)
151{
152 char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
153 const char *p;
154 char *new;
155 int len = strlen(s) + 1;
156 int err;
157
158 p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
159 if (p)
160 /* found it */
161 return (p - strtab);
162
163 new = strtab + fdt_size_dt_strings(fdt);
164 err = _blob_splice_string(fdt, len);
165 if (err)
166 return err;
167
168 memcpy(new, s, len);
169 return (new - strtab);
170}
171
172int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
173{
174 struct fdt_reserve_entry *re;
175 int err;
176
177 if ((err = rw_check_header(fdt)))
178 return err;
179
180 re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
181 err = _blob_splice_mem_rsv(fdt, re, 0, 1);
182 if (err)
183 return err;
184
185 re->address = cpu_to_fdt64(address);
186 re->size = cpu_to_fdt64(size);
187 return 0;
188}
189
190int fdt_del_mem_rsv(void *fdt, int n)
191{
192 struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
193 int err;
194
195 if ((err = rw_check_header(fdt)))
196 return err;
197 if (n >= fdt_num_mem_rsv(fdt))
198 return -FDT_ERR_NOTFOUND;
199
200 err = _blob_splice_mem_rsv(fdt, re, 1, 0);
201 if (err)
202 return err;
203 return 0;
204}
205
206static int _resize_property(void *fdt, int nodeoffset, const char *name, int len,
207 struct fdt_property **prop)
208{
209 int oldlen;
210 int err;
211
212 *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
213 if (! (*prop))
214 return oldlen;
215
216 if ((err = _blob_splice_struct(fdt, (*prop)->data,
217 ALIGN(oldlen, FDT_TAGSIZE),
218 ALIGN(len, FDT_TAGSIZE))))
219 return err;
220
221 (*prop)->len = cpu_to_fdt32(len);
222 return 0;
223}
224
225static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
226 struct fdt_property **prop)
227{
228 uint32_t tag;
229 int proplen;
230 int nextoffset;
231 int namestroff;
232 int err;
233
234 tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
235 if (tag != FDT_BEGIN_NODE)
236 return -FDT_ERR_BADOFFSET;
237
238 namestroff = _find_add_string(fdt, name);
239 if (namestroff < 0)
240 return namestroff;
241
242 *prop = _fdt_offset_ptr_w(fdt, nextoffset);
243 proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE);
244
245 err = _blob_splice_struct(fdt, *prop, 0, proplen);
246 if (err)
247 return err;
248
249 (*prop)->tag = cpu_to_fdt32(FDT_PROP);
250 (*prop)->nameoff = cpu_to_fdt32(namestroff);
251 (*prop)->len = cpu_to_fdt32(len);
252 return 0;
253}
254
255int fdt_setprop(void *fdt, int nodeoffset, const char *name,
256 const void *val, int len)
257{
258 struct fdt_property *prop;
259 int err;
260
261 if ((err = rw_check_header(fdt)))
262 return err;
263
264 err = _resize_property(fdt, nodeoffset, name, len, &prop);
265 if (err == -FDT_ERR_NOTFOUND)
266 err = _add_property(fdt, nodeoffset, name, len, &prop);
267 if (err)
268 return err;
269
270 memcpy(prop->data, val, len);
271 return 0;
272}
273
274int fdt_delprop(void *fdt, int nodeoffset, const char *name)
275{
276 struct fdt_property *prop;
277 int len, proplen;
278
279 RW_CHECK_HEADER(fdt);
280
281 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
282 if (! prop)
283 return len;
284
285 proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE);
286 return _blob_splice_struct(fdt, prop, proplen, 0);
287}
288
289int fdt_add_subnode_namelen(void *fdt, int parentoffset,
290 const char *name, int namelen)
291{
292 struct fdt_node_header *nh;
293 int offset, nextoffset;
294 int nodelen;
295 int err;
296 uint32_t tag;
297 uint32_t *endtag;
298
299 RW_CHECK_HEADER(fdt);
300
301 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
302 if (offset >= 0)
303 return -FDT_ERR_EXISTS;
304 else if (offset != -FDT_ERR_NOTFOUND)
305 return offset;
306
307 /* Try to place the new node after the parent's properties */
308 fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
309 do {
310 offset = nextoffset;
311 tag = fdt_next_tag(fdt, offset, &nextoffset);
312 } while (tag == FDT_PROP);
313
314 nh = _fdt_offset_ptr_w(fdt, offset);
315 nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
316
317 err = _blob_splice_struct(fdt, nh, 0, nodelen);
318 if (err)
319 return err;
320
321 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
322 memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE));
323 memcpy(nh->name, name, namelen);
324 endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE);
325 *endtag = cpu_to_fdt32(FDT_END_NODE);
326
327 return offset;
328}
329
330int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
331{
332 return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
333}
334
335int fdt_del_node(void *fdt, int nodeoffset)
336{
337 int endoffset;
338
339 RW_CHECK_HEADER(fdt);
340
341 endoffset = _fdt_node_end_offset(fdt, nodeoffset);
342 if (endoffset < 0)
343 return endoffset;
344
345 return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
346 endoffset - nodeoffset, 0);
347}
348
349static void _packblocks(const void *fdt, void *buf,
350 int mem_rsv_size, int struct_size)
351{
352 int mem_rsv_off, struct_off, strings_off;
353
354 mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8);
355 struct_off = mem_rsv_off + mem_rsv_size;
356 strings_off = struct_off + struct_size;
357
358 memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size);
359 fdt_set_off_mem_rsvmap(buf, mem_rsv_off);
360
361 memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size);
362 fdt_set_off_dt_struct(buf, struct_off);
363 fdt_set_size_dt_struct(buf, struct_size);
364
365 memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt),
366 fdt_size_dt_strings(fdt));
367 fdt_set_off_dt_strings(buf, strings_off);
368 fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt));
369}
370
371int fdt_open_into(const void *fdt, void *buf, int bufsize)
372{
373 int err;
374 int mem_rsv_size, struct_size;
375 int newsize;
376 void *tmp;
377
378 err = fdt_check_header(fdt);
379 if (err)
380 return err;
381
382 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
383 * sizeof(struct fdt_reserve_entry);
384
385 if (fdt_version(fdt) >= 17) {
386 struct_size = fdt_size_dt_struct(fdt);
387 } else {
388 struct_size = 0;
389 while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
390 ;
391 }
392
393 if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
394 /* no further work necessary */
395 err = fdt_move(fdt, buf, bufsize);
396 if (err)
397 return err;
398 fdt_set_version(buf, 17);
399 fdt_set_size_dt_struct(buf, struct_size);
400 fdt_set_totalsize(buf, bufsize);
401 return 0;
402 }
403
404 /* Need to reorder */
405 newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
406 + struct_size + fdt_size_dt_strings(fdt);
407
408 if (bufsize < newsize)
409 return -FDT_ERR_NOSPACE;
410
411 if (((buf + newsize) <= fdt)
412 || (buf >= (fdt + fdt_totalsize(fdt)))) {
413 tmp = buf;
414 } else {
415 tmp = (void *)fdt + fdt_totalsize(fdt);
416 if ((tmp + newsize) > (buf + bufsize))
417 return -FDT_ERR_NOSPACE;
418 }
419
420 _packblocks(fdt, tmp, mem_rsv_size, struct_size);
421 memmove(buf, tmp, newsize);
422
423 fdt_set_magic(buf, FDT_MAGIC);
424 fdt_set_totalsize(buf, bufsize);
425 fdt_set_version(buf, 17);
426 fdt_set_last_comp_version(buf, 16);
427 fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
428
429 return 0;
430}
431
432int fdt_pack(void *fdt)
433{
434 int mem_rsv_size;
435 int err;
436
437 err = rw_check_header(fdt);
438 if (err)
439 return err;
440
441 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
442 * sizeof(struct fdt_reserve_entry);
443 _packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
444 fdt_set_totalsize(fdt, _blob_data_size(fdt));
445
446 return 0;
447}
diff --git a/arch/powerpc/boot/libfdt/fdt_strerror.c b/arch/powerpc/boot/libfdt/fdt_strerror.c
new file mode 100644
index 000000000000..f9d32ef5360a
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_strerror.c
@@ -0,0 +1,96 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 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
58struct errtabent {
59 const char *str;
60};
61
62#define ERRTABENT(val) \
63 [(val)] = { .str = #val, }
64
65static struct errtabent errtable[] = {
66 ERRTABENT(FDT_ERR_NOTFOUND),
67 ERRTABENT(FDT_ERR_EXISTS),
68 ERRTABENT(FDT_ERR_NOSPACE),
69
70 ERRTABENT(FDT_ERR_BADOFFSET),
71 ERRTABENT(FDT_ERR_BADPATH),
72 ERRTABENT(FDT_ERR_BADSTATE),
73
74 ERRTABENT(FDT_ERR_TRUNCATED),
75 ERRTABENT(FDT_ERR_BADMAGIC),
76 ERRTABENT(FDT_ERR_BADVERSION),
77 ERRTABENT(FDT_ERR_BADSTRUCTURE),
78 ERRTABENT(FDT_ERR_BADLAYOUT),
79};
80#define ERRTABSIZE (sizeof(errtable) / sizeof(errtable[0]))
81
82const char *fdt_strerror(int errval)
83{
84 if (errval > 0)
85 return "<valid offset/length>";
86 else if (errval == 0)
87 return "<no error>";
88 else if (errval > -ERRTABSIZE) {
89 const char *s = errtable[-errval].str;
90
91 if (s)
92 return s;
93 }
94
95 return "<unknown error>";
96}
diff --git a/arch/powerpc/boot/libfdt/fdt_sw.c b/arch/powerpc/boot/libfdt/fdt_sw.c
new file mode 100644
index 000000000000..dda2de34b2e0
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_sw.c
@@ -0,0 +1,258 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 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
58static int check_header_sw(void *fdt)
59{
60 if (fdt_magic(fdt) != SW_MAGIC)
61 return -FDT_ERR_BADMAGIC;
62 return 0;
63}
64
65static void *grab_space(void *fdt, int len)
66{
67 int offset = fdt_size_dt_struct(fdt);
68 int spaceleft;
69
70 spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
71 - fdt_size_dt_strings(fdt);
72
73 if ((offset + len < offset) || (offset + len > spaceleft))
74 return NULL;
75
76 fdt_set_size_dt_struct(fdt, offset + len);
77 return fdt_offset_ptr_w(fdt, offset, len);
78}
79
80int fdt_create(void *buf, int bufsize)
81{
82 void *fdt = buf;
83
84 if (bufsize < sizeof(struct fdt_header))
85 return -FDT_ERR_NOSPACE;
86
87 memset(buf, 0, bufsize);
88
89 fdt_set_magic(fdt, SW_MAGIC);
90 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
91 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
92 fdt_set_totalsize(fdt, bufsize);
93
94 fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header),
95 sizeof(struct fdt_reserve_entry)));
96 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
97 fdt_set_off_dt_strings(fdt, bufsize);
98
99 return 0;
100}
101
102int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
103{
104 struct fdt_reserve_entry *re;
105 int err = check_header_sw(fdt);
106 int offset;
107
108 if (err)
109 return err;
110 if (fdt_size_dt_struct(fdt))
111 return -FDT_ERR_BADSTATE;
112
113 offset = fdt_off_dt_struct(fdt);
114 if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
115 return -FDT_ERR_NOSPACE;
116
117 re = (struct fdt_reserve_entry *)(fdt + offset);
118 re->address = cpu_to_fdt64(addr);
119 re->size = cpu_to_fdt64(size);
120
121 fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
122
123 return 0;
124}
125
126int fdt_finish_reservemap(void *fdt)
127{
128 return fdt_add_reservemap_entry(fdt, 0, 0);
129}
130
131int fdt_begin_node(void *fdt, const char *name)
132{
133 struct fdt_node_header *nh;
134 int err = check_header_sw(fdt);
135 int namelen = strlen(name) + 1;
136
137 if (err)
138 return err;
139
140 nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
141 if (! nh)
142 return -FDT_ERR_NOSPACE;
143
144 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
145 memcpy(nh->name, name, namelen);
146 return 0;
147}
148
149int fdt_end_node(void *fdt)
150{
151 uint32_t *en;
152 int err = check_header_sw(fdt);
153
154 if (err)
155 return err;
156
157 en = grab_space(fdt, FDT_TAGSIZE);
158 if (! en)
159 return -FDT_ERR_NOSPACE;
160
161 *en = cpu_to_fdt32(FDT_END_NODE);
162 return 0;
163}
164
165static int find_add_string(void *fdt, const char *s)
166{
167 char *strtab = (char *)fdt + fdt_totalsize(fdt);
168 const char *p;
169 int strtabsize = fdt_size_dt_strings(fdt);
170 int len = strlen(s) + 1;
171 int struct_top, offset;
172
173 p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
174 if (p)
175 return p - strtab;
176
177 /* Add it */
178 offset = -strtabsize - len;
179 struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
180 if (fdt_totalsize(fdt) + offset < struct_top)
181 return 0; /* no more room :( */
182
183 memcpy(strtab + offset, s, len);
184 fdt_set_size_dt_strings(fdt, strtabsize + len);
185 return offset;
186}
187
188int fdt_property(void *fdt, const char *name, const void *val, int len)
189{
190 struct fdt_property *prop;
191 int err = check_header_sw(fdt);
192 int nameoff;
193
194 if (err)
195 return err;
196
197 nameoff = find_add_string(fdt, name);
198 if (nameoff == 0)
199 return -FDT_ERR_NOSPACE;
200
201 prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
202 if (! prop)
203 return -FDT_ERR_NOSPACE;
204
205 prop->tag = cpu_to_fdt32(FDT_PROP);
206 prop->nameoff = cpu_to_fdt32(nameoff);
207 prop->len = cpu_to_fdt32(len);
208 memcpy(prop->data, val, len);
209 return 0;
210}
211
212int fdt_finish(void *fdt)
213{
214 int err = check_header_sw(fdt);
215 char *p = (char *)fdt;
216 uint32_t *end;
217 int oldstroffset, newstroffset;
218 uint32_t tag;
219 int offset, nextoffset;
220
221 if (err)
222 return err;
223
224 /* Add terminator */
225 end = grab_space(fdt, sizeof(*end));
226 if (! end)
227 return -FDT_ERR_NOSPACE;
228 *end = cpu_to_fdt32(FDT_END);
229
230 /* Relocate the string table */
231 oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
232 newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
233 memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
234 fdt_set_off_dt_strings(fdt, newstroffset);
235
236 /* Walk the structure, correcting string offsets */
237 offset = 0;
238 while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
239 if (tag == FDT_PROP) {
240 struct fdt_property *prop =
241 fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
242 int nameoff;
243
244 if (! prop)
245 return -FDT_ERR_BADSTRUCTURE;
246
247 nameoff = fdt32_to_cpu(prop->nameoff);
248 nameoff += fdt_size_dt_strings(fdt);
249 prop->nameoff = cpu_to_fdt32(nameoff);
250 }
251 offset = nextoffset;
252 }
253
254 /* Finally, adjust the header */
255 fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
256 fdt_set_magic(fdt, FDT_MAGIC);
257 return 0;
258}
diff --git a/arch/powerpc/boot/libfdt/fdt_wip.c b/arch/powerpc/boot/libfdt/fdt_wip.c
new file mode 100644
index 000000000000..88e24b8318f4
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_wip.c
@@ -0,0 +1,144 @@
1/*
2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 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_setprop_inplace(void *fdt, int nodeoffset, const char *name,
59 const void *val, int len)
60{
61 void *propval;
62 int proplen;
63
64 propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
65 if (! propval)
66 return proplen;
67
68 if (proplen != len)
69 return -FDT_ERR_NOSPACE;
70
71 memcpy(propval, val, len);
72 return 0;
73}
74
75static void nop_region(void *start, int len)
76{
77 uint32_t *p;
78
79 for (p = start; (void *)p < (start + len); p++)
80 *p = cpu_to_fdt32(FDT_NOP);
81}
82
83int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
84{
85 struct fdt_property *prop;
86 int len;
87
88 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
89 if (! prop)
90 return len;
91
92 nop_region(prop, len + sizeof(*prop));
93
94 return 0;
95}
96
97int _fdt_node_end_offset(void *fdt, int nodeoffset)
98{
99 int level = 0;
100 uint32_t tag;
101 int offset, nextoffset;
102
103 tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
104 if (tag != FDT_BEGIN_NODE)
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}
133
134int fdt_nop_node(void *fdt, int nodeoffset)
135{
136 int endoffset;
137
138 endoffset = _fdt_node_end_offset(fdt, nodeoffset);
139 if (endoffset < 0)
140 return endoffset;
141
142 nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset);
143 return 0;
144}
diff --git a/arch/powerpc/boot/libfdt/libfdt.h b/arch/powerpc/boot/libfdt/libfdt.h
new file mode 100644
index 000000000000..6b2fb92ea357
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/libfdt.h
@@ -0,0 +1,721 @@
1#ifndef _LIBFDT_H
2#define _LIBFDT_H
3/*
4 * libfdt - Flat Device Tree manipulation
5 * Copyright (C) 2006 David Gibson, IBM Corporation.
6 *
7 * libfdt is dual licensed: you can use it either under the terms of
8 * the GPL, or the BSD license, at your option.
9 *
10 * a) This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
23 * MA 02110-1301 USA
24 *
25 * Alternatively,
26 *
27 * b) Redistribution and use in source and binary forms, with or
28 * without modification, are permitted provided that the following
29 * conditions are met:
30 *
31 * 1. Redistributions of source code must retain the above
32 * copyright notice, this list of conditions and the following
33 * disclaimer.
34 * 2. Redistributions in binary form must reproduce the above
35 * copyright notice, this list of conditions and the following
36 * disclaimer in the documentation and/or other materials
37 * provided with the distribution.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
40 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
50 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53
54#include <libfdt_env.h>
55#include <fdt.h>
56
57#define FDT_FIRST_SUPPORTED_VERSION 0x10
58#define FDT_LAST_SUPPORTED_VERSION 0x11
59
60/* Error codes: informative error codes */
61#define FDT_ERR_NOTFOUND 1
62 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
63#define FDT_ERR_EXISTS 2
64 /* FDT_ERR_EXISTS: Attemped to create a node or property which
65 * already exists */
66#define FDT_ERR_NOSPACE 3
67 /* FDT_ERR_NOSPACE: Operation needed to expand the device
68 * tree, but its buffer did not have sufficient space to
69 * contain the expanded tree. Use fdt_open_into() to move the
70 * device tree to a buffer with more space. */
71
72/* Error codes: codes for bad parameters */
73#define FDT_ERR_BADOFFSET 4
74 /* FDT_ERR_BADOFFSET: Function was passed a structure block
75 * offset which is out-of-bounds, or which points to an
76 * unsuitable part of the structure for the operation. */
77#define FDT_ERR_BADPATH 5
78 /* FDT_ERR_BADPATH: Function was passed a badly formatted path
79 * (e.g. missing a leading / for a function which requires an
80 * absolute path) */
81#define FDT_ERR_BADPHANDLE 6
82 /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
83 * value. phandle values of 0 and -1 are not permitted. */
84#define FDT_ERR_BADSTATE 7
85 /* FDT_ERR_BADSTATE: Function was passed an incomplete device
86 * tree created by the sequential-write functions, which is
87 * not sufficiently complete for the requested operation. */
88
89/* Error codes: codes for bad device tree blobs */
90#define FDT_ERR_TRUNCATED 8
91 /* FDT_ERR_TRUNCATED: Structure block of the given device tree
92 * ends without an FDT_END tag. */
93#define FDT_ERR_BADMAGIC 9
94 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
95 * device tree at all - it is missing the flattened device
96 * tree magic number. */
97#define FDT_ERR_BADVERSION 10
98 /* FDT_ERR_BADVERSION: Given device tree has a version which
99 * can't be handled by the requested operation. For
100 * read-write functions, this may mean that fdt_open_into() is
101 * required to convert the tree to the expected version. */
102#define FDT_ERR_BADSTRUCTURE 11
103 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
104 * structure block or other serious error (e.g. misnested
105 * nodes, or subnodes preceding properties). */
106#define FDT_ERR_BADLAYOUT 12
107 /* FDT_ERR_BADLAYOUT: For read-write functions, the given
108 * device tree has it's sub-blocks in an order that the
109 * function can't handle (memory reserve map, then structure,
110 * then strings). Use fdt_open_into() to reorganize the tree
111 * into a form suitable for the read-write operations. */
112
113/* "Can't happen" error indicating a bug in libfdt */
114#define FDT_ERR_INTERNAL 13
115 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
116 * Should never be returned, if it is, it indicates a bug in
117 * libfdt itself. */
118
119#define FDT_ERR_MAX 13
120
121/**********************************************************************/
122/* Low-level functions (you probably don't need these) */
123/**********************************************************************/
124
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)
127{
128 return (void *)fdt_offset_ptr(fdt, offset, checklen);
129}
130
131uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
132
133/**********************************************************************/
134/* General functions */
135/**********************************************************************/
136
137#define fdt_get_header(fdt, field) \
138 (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
139#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
140#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
141#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
142#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
143#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
144#define fdt_version(fdt) (fdt_get_header(fdt, version))
145#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
146#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
147#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
148#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
149
150#define __fdt_set_hdr(name) \
151 static inline void fdt_set_##name(void *fdt, uint32_t val) \
152 { \
153 struct fdt_header *fdth = fdt; \
154 fdth->name = cpu_to_fdt32(val); \
155 }
156__fdt_set_hdr(magic);
157__fdt_set_hdr(totalsize);
158__fdt_set_hdr(off_dt_struct);
159__fdt_set_hdr(off_dt_strings);
160__fdt_set_hdr(off_mem_rsvmap);
161__fdt_set_hdr(version);
162__fdt_set_hdr(last_comp_version);
163__fdt_set_hdr(boot_cpuid_phys);
164__fdt_set_hdr(size_dt_strings);
165__fdt_set_hdr(size_dt_struct);
166#undef __fdt_set_hdr
167
168/**
169 * fdt_check_header - sanity check a device tree or possible device tree
170 * @fdt: pointer to data which might be a flattened device tree
171 *
172 * fdt_check_header() checks that the given buffer contains what
173 * appears to be a flattened device tree with sane information in its
174 * header.
175 *
176 * returns:
177 * 0, if the buffer appears to contain a valid device tree
178 * -FDT_ERR_BADMAGIC,
179 * -FDT_ERR_BADVERSION,
180 * -FDT_ERR_BADSTATE, standard meanings, as above
181 */
182int fdt_check_header(const void *fdt);
183
184/**
185 * fdt_move - move a device tree around in memory
186 * @fdt: pointer to the device tree to move
187 * @buf: pointer to memory where the device is to be moved
188 * @bufsize: size of the memory space at buf
189 *
190 * fdt_move() relocates, if possible, the device tree blob located at
191 * fdt to the buffer at buf of size bufsize. The buffer may overlap
192 * with the existing device tree blob at fdt. Therefore,
193 * fdt_move(fdt, fdt, fdt_totalsize(fdt))
194 * should always succeed.
195 *
196 * returns:
197 * 0, on success
198 * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
199 * -FDT_ERR_BADMAGIC,
200 * -FDT_ERR_BADVERSION,
201 * -FDT_ERR_BADSTATE, standard meanings
202 */
203int fdt_move(const void *fdt, void *buf, int bufsize);
204
205/**********************************************************************/
206/* Read-only functions */
207/**********************************************************************/
208
209/**
210 * fdt_string - retreive a string from the strings block of a device tree
211 * @fdt: pointer to the device tree blob
212 * @stroffset: offset of the string within the strings block (native endian)
213 *
214 * fdt_string() retrieves a pointer to a single string from the
215 * strings block of the device tree blob at fdt.
216 *
217 * returns:
218 * a pointer to the string, on success
219 * NULL, if stroffset is out of bounds
220 */
221const char *fdt_string(const void *fdt, int stroffset);
222
223/**
224 * fdt_num_mem_rsv - retreive the number of memory reserve map entries
225 * @fdt: pointer to the device tree blob
226 *
227 * Returns the number of entries in the device tree blob's memory
228 * reservation map. This does not include the terminating 0,0 entry
229 * or any other (0,0) entries reserved for expansion.
230 *
231 * returns:
232 * the number of entries
233 */
234int fdt_num_mem_rsv(const void *fdt);
235
236/**
237 * fdt_get_mem_rsv - retreive one memory reserve map entry
238 * @fdt: pointer to the device tree blob
239 * @address, @size: pointers to 64-bit variables
240 *
241 * On success, *address and *size will contain the address and size of
242 * the n-th reserve map entry from the device tree blob, in
243 * native-endian format.
244 *
245 * returns:
246 * 0, on success
247 * -FDT_ERR_BADMAGIC,
248 * -FDT_ERR_BADVERSION,
249 * -FDT_ERR_BADSTATE, standard meanings
250 */
251int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
252
253/**
254 * fdt_subnode_offset_namelen - find a subnode based on substring
255 * @fdt: pointer to the device tree blob
256 * @parentoffset: structure block offset of a node
257 * @name: name of the subnode to locate
258 * @namelen: number of characters of name to consider
259 *
260 * Identical to fdt_subnode_offset(), but only examine the first
261 * namelen characters of name for matching the subnode name. This is
262 * useful for finding subnodes based on a portion of a larger string,
263 * such as a full path.
264 */
265int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
266 const char *name, int namelen);
267/**
268 * fdt_subnode_offset - find a subnode of a given node
269 * @fdt: pointer to the device tree blob
270 * @parentoffset: structure block offset of a node
271 * @name: name of the subnode to locate
272 *
273 * fdt_subnode_offset() finds a subnode of the node at structure block
274 * offset parentoffset with the given name. name may include a unit
275 * address, in which case fdt_subnode_offset() will find the subnode
276 * with that unit address, or the unit address may be omitted, in
277 * which case fdt_subnode_offset() will find an arbitrary subnode
278 * whose name excluding unit address matches the given name.
279 *
280 * returns:
281 * structure block offset of the requested subnode (>=0), on success
282 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
283 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
284 * -FDT_ERR_BADMAGIC,
285 * -FDT_ERR_BADVERSION,
286 * -FDT_ERR_BADSTATE,
287 * -FDT_ERR_BADSTRUCTURE,
288 * -FDT_ERR_TRUNCATED, standard meanings.
289 */
290int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
291
292/**
293 * fdt_path_offset - find a tree node by its full path
294 * @fdt: pointer to the device tree blob
295 * @path: full path of the node to locate
296 *
297 * fdt_path_offset() finds a node of a given path in the device tree.
298 * Each path component may omit the unit address portion, but the
299 * results of this are undefined if any such path component is
300 * ambiguous (that is if there are multiple nodes at the relevant
301 * level matching the given component, differentiated only by unit
302 * address).
303 *
304 * returns:
305 * structure block offset of the node with the requested path (>=0), on success
306 * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
307 * -FDT_ERR_NOTFOUND, if the requested node does not exist
308 * -FDT_ERR_BADMAGIC,
309 * -FDT_ERR_BADVERSION,
310 * -FDT_ERR_BADSTATE,
311 * -FDT_ERR_BADSTRUCTURE,
312 * -FDT_ERR_TRUNCATED, standard meanings.
313 */
314int fdt_path_offset(const void *fdt, const char *path);
315
316/**
317 * fdt_get_name - retreive the name of a given node
318 * @fdt: pointer to the device tree blob
319 * @nodeoffset: structure block offset of the starting node
320 * @lenp: pointer to an integer variable (will be overwritten) or NULL
321 *
322 * fdt_get_name() retrieves the name (including unit address) of the
323 * device tree node at structure block offset nodeoffset. If lenp is
324 * non-NULL, the length of this name is also returned, in the integer
325 * pointed to by lenp.
326 *
327 * returns:
328 * pointer to the node's name, on success
329 * If lenp is non-NULL, *lenp contains the length of that name (>=0)
330 * NULL, on error
331 * if lenp is non-NULL *lenp contains an error code (<0):
332 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
333 * -FDT_ERR_BADMAGIC,
334 * -FDT_ERR_BADVERSION,
335 * -FDT_ERR_BADSTATE, standard meanings
336 */
337const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
338
339/**
340 * fdt_get_property - find a given property in a given node
341 * @fdt: pointer to the device tree blob
342 * @nodeoffset: offset of the node whose property to find
343 * @name: name of the property to find
344 * @lenp: pointer to an integer variable (will be overwritten) or NULL
345 *
346 * fdt_get_property() retrieves a pointer to the fdt_property
347 * structure within the device tree blob corresponding to the property
348 * named 'name' of the node at offset nodeoffset. If lenp is
349 * non-NULL, the length of the property value also returned, in the
350 * integer pointed to by lenp.
351 *
352 * returns:
353 * pointer to the structure representing the property
354 * if lenp is non-NULL, *lenp contains the length of the property
355 * value (>=0)
356 * NULL, on error
357 * if lenp is non-NULL, *lenp contains an error code (<0):
358 * -FDT_ERR_NOTFOUND, node does not have named property
359 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
360 * -FDT_ERR_BADMAGIC,
361 * -FDT_ERR_BADVERSION,
362 * -FDT_ERR_BADSTATE,
363 * -FDT_ERR_BADSTRUCTURE,
364 * -FDT_ERR_TRUNCATED, standard meanings
365 */
366const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
367 const char *name, int *lenp);
368static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
369 const char *name,
370 int *lenp)
371{
372 return (struct fdt_property *)fdt_get_property(fdt, nodeoffset,
373 name, lenp);
374}
375
376/**
377 * fdt_getprop - retrieve the value of a given property
378 * @fdt: pointer to the device tree blob
379 * @nodeoffset: offset of the node whose property to find
380 * @name: name of the property to find
381 * @lenp: pointer to an integer variable (will be overwritten) or NULL
382 *
383 * fdt_getprop() retrieves a pointer to the value of the property
384 * 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).
386 * If lenp is non-NULL, the length of the property value also
387 * returned, in the integer pointed to by lenp.
388 *
389 * returns:
390 * pointer to the property's value
391 * if lenp is non-NULL, *lenp contains the length of the property
392 * value (>=0)
393 * NULL, on error
394 * if lenp is non-NULL, *lenp contains an error code (<0):
395 * -FDT_ERR_NOTFOUND, node does not have named property
396 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
397 * -FDT_ERR_BADMAGIC,
398 * -FDT_ERR_BADVERSION,
399 * -FDT_ERR_BADSTATE,
400 * -FDT_ERR_BADSTRUCTURE,
401 * -FDT_ERR_TRUNCATED, standard meanings
402 */
403const void *fdt_getprop(const void *fdt, int nodeoffset,
404 const char *name, int *lenp);
405static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
406 const char *name, int *lenp)
407{
408 return (void *)fdt_getprop(fdt, nodeoffset, name, lenp);
409}
410
411/**
412 * fdt_get_phandle - retreive the phandle of a given node
413 * @fdt: pointer to the device tree blob
414 * @nodeoffset: structure block offset of the node
415 *
416 * fdt_get_phandle() retrieves the phandle of the device tree node at
417 * structure block offset nodeoffset.
418 *
419 * returns:
420 * the phandle of the node at nodeoffset, on succes (!= 0, != -1)
421 * 0, if the node has no phandle, or another error occurs
422 */
423uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
424
425/**
426 * fdt_get_path - determine the full path of a node
427 * @fdt: pointer to the device tree blob
428 * @nodeoffset: offset of the node whose path to find
429 * @buf: character buffer to contain the returned path (will be overwritten)
430 * @buflen: size of the character buffer at buf
431 *
432 * fdt_get_path() computes the full path of the node at offset
433 * nodeoffset, and records that path in the buffer at buf.
434 *
435 * NOTE: This function is expensive, as it must scan the device tree
436 * structure from the start to nodeoffset.
437 *
438 * returns:
439 * 0, on success
440 * buf contains the absolute path of the node at
441 * nodeoffset, as a NUL-terminated string.
442 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
443 * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
444 * characters and will not fit in the given buffer.
445 * -FDT_ERR_BADMAGIC,
446 * -FDT_ERR_BADVERSION,
447 * -FDT_ERR_BADSTATE,
448 * -FDT_ERR_BADSTRUCTURE, standard meanings
449 */
450int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
451
452/**
453 * fdt_supernode_atdepth_offset - find a specific ancestor of a node
454 * @fdt: pointer to the device tree blob
455 * @nodeoffset: offset of the node whose parent to find
456 * @supernodedepth: depth of the ancestor to find
457 * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
458 *
459 * fdt_supernode_atdepth_offset() finds an ancestor of the given node
460 * at a specific depth from the root (where the root itself has depth
461 * 0, its immediate subnodes depth 1 and so forth). So
462 * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
463 * will always return 0, the offset of the root node. If the node at
464 * nodeoffset has depth D, then:
465 * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
466 * will return nodeoffset itself.
467 *
468 * NOTE: This function is expensive, as it must scan the device tree
469 * structure from the start to nodeoffset.
470 *
471 * returns:
472
473 * structure block offset of the node at node offset's ancestor
474 * of depth supernodedepth (>=0), on success
475 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
476* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
477 * -FDT_ERR_BADMAGIC,
478 * -FDT_ERR_BADVERSION,
479 * -FDT_ERR_BADSTATE,
480 * -FDT_ERR_BADSTRUCTURE, standard meanings
481 */
482int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
483 int supernodedepth, int *nodedepth);
484
485/**
486 * fdt_node_depth - find the depth of a given node
487 * @fdt: pointer to the device tree blob
488 * @nodeoffset: offset of the node whose parent to find
489 *
490 * fdt_node_depth() finds the depth of a given node. The root node
491 * has depth 0, its immediate subnodes depth 1 and so forth.
492 *
493 * NOTE: This function is expensive, as it must scan the device tree
494 * structure from the start to nodeoffset.
495 *
496 * returns:
497 * depth of the node at nodeoffset (>=0), on success
498 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
499 * -FDT_ERR_BADMAGIC,
500 * -FDT_ERR_BADVERSION,
501 * -FDT_ERR_BADSTATE,
502 * -FDT_ERR_BADSTRUCTURE, standard meanings
503 */
504int fdt_node_depth(const void *fdt, int nodeoffset);
505
506/**
507 * fdt_parent_offset - find the parent of a given node
508 * @fdt: pointer to the device tree blob
509 * @nodeoffset: offset of the node whose parent to find
510 *
511 * fdt_parent_offset() locates the parent node of a given node (that
512 * is, it finds the offset of the node which contains the node at
513 * nodeoffset as a subnode).
514 *
515 * NOTE: This function is expensive, as it must scan the device tree
516 * structure from the start to nodeoffset, *twice*.
517 *
518 * returns:
519 * stucture block offset of the parent of the node at nodeoffset
520 * (>=0), on success
521 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
522 * -FDT_ERR_BADMAGIC,
523 * -FDT_ERR_BADVERSION,
524 * -FDT_ERR_BADSTATE,
525 * -FDT_ERR_BADSTRUCTURE, standard meanings
526 */
527int fdt_parent_offset(const void *fdt, int nodeoffset);
528
529/**
530 * fdt_node_offset_by_prop_value - find nodes with a given property value
531 * @fdt: pointer to the device tree blob
532 * @startoffset: only find nodes after this offset
533 * @propname: property name to check
534 * @propval: property value to search for
535 * @proplen: length of the value in propval
536 *
537 * fdt_node_offset_by_prop_value() returns the offset of the first
538 * node after startoffset, which has a property named propname whose
539 * value is of length proplen and has value equal to propval; or if
540 * startoffset is -1, the very first such node in the tree.
541 *
542 * To iterate through all nodes matching the criterion, the following
543 * idiom can be used:
544 * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
545 * propval, proplen);
546 * while (offset != -FDT_ERR_NOTFOUND) {
547 * // other code here
548 * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
549 * propval, proplen);
550 * }
551 *
552 * Note the -1 in the first call to the function, if 0 is used here
553 * instead, the function will never locate the root node, even if it
554 * matches the criterion.
555 *
556 * returns:
557 * structure block offset of the located node (>= 0, >startoffset),
558 * on success
559 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
560 * tree after startoffset
561 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
562 * -FDT_ERR_BADMAGIC,
563 * -FDT_ERR_BADVERSION,
564 * -FDT_ERR_BADSTATE,
565 * -FDT_ERR_BADSTRUCTURE, standard meanings
566 */
567int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
568 const char *propname,
569 const void *propval, int proplen);
570
571/**
572 * fdt_node_offset_by_phandle - find the node with a given phandle
573 * @fdt: pointer to the device tree blob
574 * @phandle: phandle value
575 *
576 * fdt_node_offset_by_prop_value() returns the offset of the node
577 * 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
579 * undefined.
580 *
581 * returns:
582 * structure block offset of the located node (>= 0), on success
583 * -FDT_ERR_NOTFOUND, no node with that phandle exists
584 * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
585 * -FDT_ERR_BADMAGIC,
586 * -FDT_ERR_BADVERSION,
587 * -FDT_ERR_BADSTATE,
588 * -FDT_ERR_BADSTRUCTURE, standard meanings
589 */
590int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
591
592/**
593 * fdt_node_check_compatible: check a node's compatible property
594 * @fdt: pointer to the device tree blob
595 * @nodeoffset: offset of a tree node
596 * @compatible: string to match against
597 *
598 *
599 * fdt_node_check_compatible() returns 0 if the given node contains a
600 * 'compatible' property with the given string as one of its elements,
601 * it returns non-zero otherwise, or on error.
602 *
603 * returns:
604 * 0, if the node has a 'compatible' property listing the given string
605 * 1, if the node has a 'compatible' property, but it does not list
606 * the given string
607 * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
608 * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
609 * -FDT_ERR_BADMAGIC,
610 * -FDT_ERR_BADVERSION,
611 * -FDT_ERR_BADSTATE,
612 * -FDT_ERR_BADSTRUCTURE, standard meanings
613 */
614int fdt_node_check_compatible(const void *fdt, int nodeoffset,
615 const char *compatible);
616
617/**
618 * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
619 * @fdt: pointer to the device tree blob
620 * @startoffset: only find nodes after this offset
621 * @compatible: 'compatible' string to match against
622 *
623 * fdt_node_offset_by_compatible() returns the offset of the first
624 * node after startoffset, which has a 'compatible' property which
625 * lists the given compatible string; or if startoffset is -1, the
626 * very first such node in the tree.
627 *
628 * To iterate through all nodes matching the criterion, the following
629 * idiom can be used:
630 * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
631 * while (offset != -FDT_ERR_NOTFOUND) {
632 * // other code here
633 * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
634 * }
635 *
636 * Note the -1 in the first call to the function, if 0 is used here
637 * instead, the function will never locate the root node, even if it
638 * matches the criterion.
639 *
640 * returns:
641 * structure block offset of the located node (>= 0, >startoffset),
642 * on success
643 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
644 * tree after startoffset
645 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
646 * -FDT_ERR_BADMAGIC,
647 * -FDT_ERR_BADVERSION,
648 * -FDT_ERR_BADSTATE,
649 * -FDT_ERR_BADSTRUCTURE, standard meanings
650 */
651int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
652 const char *compatible);
653
654/**********************************************************************/
655/* Write-in-place functions */
656/**********************************************************************/
657
658int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
659 const void *val, int len);
660static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
661 const char *name, uint32_t val)
662{
663 val = cpu_to_fdt32(val);
664 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
665}
666
667int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
668int fdt_nop_node(void *fdt, int nodeoffset);
669
670/**********************************************************************/
671/* Sequential write functions */
672/**********************************************************************/
673
674int fdt_create(void *buf, int bufsize);
675int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
676int fdt_finish_reservemap(void *fdt);
677int fdt_begin_node(void *fdt, const char *name);
678int fdt_property(void *fdt, const char *name, const void *val, int len);
679static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
680{
681 val = cpu_to_fdt32(val);
682 return fdt_property(fdt, name, &val, sizeof(val));
683}
684#define fdt_property_string(fdt, name, str) \
685 fdt_property(fdt, name, str, strlen(str)+1)
686int fdt_end_node(void *fdt);
687int fdt_finish(void *fdt);
688
689/**********************************************************************/
690/* Read-write functions */
691/**********************************************************************/
692
693int fdt_open_into(const void *fdt, void *buf, int bufsize);
694int fdt_pack(void *fdt);
695
696int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
697int fdt_del_mem_rsv(void *fdt, int n);
698
699int fdt_setprop(void *fdt, int nodeoffset, const char *name,
700 const void *val, int len);
701static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
702 uint32_t val)
703{
704 val = cpu_to_fdt32(val);
705 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
706}
707#define fdt_setprop_string(fdt, nodeoffset, name, str) \
708 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
709int fdt_delprop(void *fdt, int nodeoffset, const char *name);
710int fdt_add_subnode_namelen(void *fdt, int parentoffset,
711 const char *name, int namelen);
712int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
713int fdt_del_node(void *fdt, int nodeoffset);
714
715/**********************************************************************/
716/* Debugging / informational functions */
717/**********************************************************************/
718
719const char *fdt_strerror(int errval);
720
721#endif /* _LIBFDT_H */
diff --git a/arch/powerpc/boot/libfdt/libfdt_internal.h b/arch/powerpc/boot/libfdt/libfdt_internal.h
new file mode 100644
index 000000000000..1e60936beb5b
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/libfdt_internal.h
@@ -0,0 +1,89 @@
1#ifndef _LIBFDT_INTERNAL_H
2#define _LIBFDT_INTERNAL_H
3/*
4 * libfdt - Flat Device Tree manipulation
5 * Copyright (C) 2006 David Gibson, IBM Corporation.
6 *
7 * libfdt is dual licensed: you can use it either under the terms of
8 * the GPL, or the BSD license, at your option.
9 *
10 * a) This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
23 * MA 02110-1301 USA
24 *
25 * Alternatively,
26 *
27 * b) Redistribution and use in source and binary forms, with or
28 * without modification, are permitted provided that the following
29 * conditions are met:
30 *
31 * 1. Redistributions of source code must retain the above
32 * copyright notice, this list of conditions and the following
33 * disclaimer.
34 * 2. Redistributions in binary form must reproduce the above
35 * copyright notice, this list of conditions and the following
36 * disclaimer in the documentation and/or other materials
37 * provided with the distribution.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
40 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
50 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53#include <fdt.h>
54
55#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
56#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a)))
57
58#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0)
59#define streq(p, q) (strcmp((p), (q)) == 0)
60
61uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
62const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
63int _fdt_node_end_offset(void *fdt, int nodeoffset);
64
65static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
66{
67 return fdt + fdt_off_dt_struct(fdt) + offset;
68}
69
70static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
71{
72 return (void *)_fdt_offset_ptr(fdt, offset);
73}
74
75static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
76{
77 const struct fdt_reserve_entry *rsv_table =
78 fdt + fdt_off_mem_rsvmap(fdt);
79
80 return rsv_table + n;
81}
82static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
83{
84 return (void *)_fdt_mem_rsv(fdt, n);
85}
86
87#define SW_MAGIC (~FDT_MAGIC)
88
89#endif /* _LIBFDT_INTERNAL_H */