aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/libfdt
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2009-04-30 01:25:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-05-02 19:52:26 -0400
commit9fffb55f66127b52c937ede5196ebfa0c0d50bce (patch)
tree11664fb82734ba8dcde9556b8d47e780451a740a /scripts/dtc/libfdt
parentafc1e702e8e8355faa712d4e90d9afe26a4995a5 (diff)
Move dtc and libfdt sources from arch/powerpc/boot to scripts/dtc
The powerpc kernel always requires an Open Firmware like device tree to supply device information. On systems without OF, this comes from a flattened device tree blob. This blob is usually generated by dtc, a tool which compiles a text description of the device tree into the flattened format used by the kernel. Sometimes, the bootwrapper makes small changes to the pre-compiled device tree blob (e.g. filling in the size of RAM). To do this it uses the libfdt library. Because these are only used on powerpc, the code for both these tools is included under arch/powerpc/boot (these were imported and are periodically updated from the upstream dtc tree). However, the microblaze architecture, currently being prepared for merging to mainline also uses dtc to produce device tree blobs. A few other archs have also mentioned some interest in using dtc. Therefore, this patch moves dtc and libfdt from arch/powerpc into scripts, where it can be used by any architecture. The vast bulk of this patch is a literal move, the rest is adjusting the various Makefiles to use dtc and libfdt correctly from their new locations. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts/dtc/libfdt')
-rw-r--r--scripts/dtc/libfdt/Makefile.libfdt8
-rw-r--r--scripts/dtc/libfdt/fdt.c201
-rw-r--r--scripts/dtc/libfdt/fdt.h60
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c469
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c463
-rw-r--r--scripts/dtc/libfdt/fdt_strerror.c96
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c257
-rw-r--r--scripts/dtc/libfdt/fdt_wip.c145
-rw-r--r--scripts/dtc/libfdt/libfdt.h1076
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h23
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h95
11 files changed, 2893 insertions, 0 deletions
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
new file mode 100644
index 000000000000..6c42acfa21ec
--- /dev/null
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -0,0 +1,8 @@
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_INCLUDES = fdt.h libfdt.h
7LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
8LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
new file mode 100644
index 000000000000..2acaec5923ae
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt.c
@@ -0,0 +1,201 @@
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) == 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 char *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 = FDT_TAGALIGN(offset);
128
129 return tag;
130}
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
180const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
181{
182 int len = strlen(s) + 1;
183 const char *last = strtab + tabsize - len;
184 const char *p;
185
186 for (p = strtab; p <= last; p++)
187 if (memcmp(p, s, len) == 0)
188 return p;
189 return NULL;
190}
191
192int fdt_move(const void *fdt, void *buf, int bufsize)
193{
194 FDT_CHECK_HEADER(fdt);
195
196 if (fdt_totalsize(fdt) > bufsize)
197 return -FDT_ERR_NOSPACE;
198
199 memmove(buf, fdt, fdt_totalsize(fdt));
200 return 0;
201}
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
new file mode 100644
index 000000000000..48ccfd910000
--- /dev/null
+++ b/scripts/dtc/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/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
new file mode 100644
index 000000000000..fbbba44fcd0d
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -0,0 +1,469 @@
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 _fdt_nodename_eq(const void *fdt, int offset,
59 const char *s, int len)
60{
61 const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
62
63 if (! p)
64 /* short match */
65 return 0;
66
67 if (memcmp(p, s, len) != 0)
68 return 0;
69
70 if (p[len] == '\0')
71 return 1;
72 else if (!memchr(s, '@', len) && (p[len] == '@'))
73 return 1;
74 else
75 return 0;
76}
77
78const char *fdt_string(const void *fdt, int stroffset)
79{
80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
81}
82
83int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
84{
85 FDT_CHECK_HEADER(fdt);
86 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
87 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
88 return 0;
89}
90
91int fdt_num_mem_rsv(const void *fdt)
92{
93 int i = 0;
94
95 while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
96 i++;
97 return i;
98}
99
100int fdt_subnode_offset_namelen(const void *fdt, int offset,
101 const char *name, int namelen)
102{
103 int depth;
104
105 FDT_CHECK_HEADER(fdt);
106
107 for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
108 (offset >= 0) && (depth > 0);
109 offset = fdt_next_node(fdt, offset, &depth)) {
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 }
116
117 if (offset < 0)
118 return offset; /* error */
119 else
120 return -FDT_ERR_NOTFOUND;
121}
122
123int fdt_subnode_offset(const void *fdt, int parentoffset,
124 const char *name)
125{
126 return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
127}
128
129int fdt_path_offset(const void *fdt, const char *path)
130{
131 const char *end = path + strlen(path);
132 const char *p = path;
133 int offset = 0;
134
135 FDT_CHECK_HEADER(fdt);
136
137 if (*path != '/')
138 return -FDT_ERR_BADPATH;
139
140 while (*p) {
141 const char *q;
142
143 while (*p == '/')
144 p++;
145 if (! *p)
146 return offset;
147 q = strchr(p, '/');
148 if (! q)
149 q = end;
150
151 offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
152 if (offset < 0)
153 return offset;
154
155 p = q;
156 }
157
158 return offset;
159}
160
161const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
162{
163 const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
164 int err;
165
166 if (((err = fdt_check_header(fdt)) != 0)
167 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
168 goto fail;
169
170 if (len)
171 *len = strlen(nh->name);
172
173 return nh->name;
174
175 fail:
176 if (len)
177 *len = err;
178 return NULL;
179}
180
181const struct fdt_property *fdt_get_property(const void *fdt,
182 int nodeoffset,
183 const char *name, int *lenp)
184{
185 uint32_t tag;
186 const struct fdt_property *prop;
187 int namestroff;
188 int offset, nextoffset;
189 int err;
190
191 if (((err = fdt_check_header(fdt)) != 0)
192 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
193 goto fail;
194
195 nextoffset = err;
196 do {
197 offset = nextoffset;
198
199 tag = fdt_next_tag(fdt, offset, &nextoffset);
200 switch (tag) {
201 case FDT_END:
202 err = -FDT_ERR_TRUNCATED;
203 goto fail;
204
205 case FDT_BEGIN_NODE:
206 case FDT_END_NODE:
207 case FDT_NOP:
208 break;
209
210 case FDT_PROP:
211 err = -FDT_ERR_BADSTRUCTURE;
212 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
213 if (! prop)
214 goto fail;
215 namestroff = fdt32_to_cpu(prop->nameoff);
216 if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
217 /* Found it! */
218 int len = fdt32_to_cpu(prop->len);
219 prop = fdt_offset_ptr(fdt, offset,
220 sizeof(*prop)+len);
221 if (! prop)
222 goto fail;
223
224 if (lenp)
225 *lenp = len;
226
227 return prop;
228 }
229 break;
230
231 default:
232 err = -FDT_ERR_BADSTRUCTURE;
233 goto fail;
234 }
235 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
236
237 err = -FDT_ERR_NOTFOUND;
238 fail:
239 if (lenp)
240 *lenp = err;
241 return NULL;
242}
243
244const void *fdt_getprop(const void *fdt, int nodeoffset,
245 const char *name, int *lenp)
246{
247 const struct fdt_property *prop;
248
249 prop = fdt_get_property(fdt, nodeoffset, name, lenp);
250 if (! prop)
251 return NULL;
252
253 return prop->data;
254}
255
256uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
257{
258 const uint32_t *php;
259 int len;
260
261 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
262 if (!php || (len != sizeof(*php)))
263 return 0;
264
265 return fdt32_to_cpu(*php);
266}
267
268int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
269{
270 int pdepth = 0, p = 0;
271 int offset, depth, namelen;
272 const char *name;
273
274 FDT_CHECK_HEADER(fdt);
275
276 if (buflen < 2)
277 return -FDT_ERR_NOSPACE;
278
279 for (offset = 0, depth = 0;
280 (offset >= 0) && (offset <= nodeoffset);
281 offset = fdt_next_node(fdt, offset, &depth)) {
282 if (pdepth < depth)
283 continue; /* overflowed buffer */
284
285 while (pdepth > depth) {
286 do {
287 p--;
288 } while (buf[p-1] != '/');
289 pdepth--;
290 }
291
292 name = fdt_get_name(fdt, offset, &namelen);
293 if (!name)
294 return namelen;
295 if ((p + namelen + 1) <= buflen) {
296 memcpy(buf + p, name, namelen);
297 p += namelen;
298 buf[p++] = '/';
299 pdepth++;
300 }
301
302 if (offset == nodeoffset) {
303 if (pdepth < (depth + 1))
304 return -FDT_ERR_NOSPACE;
305
306 if (p > 1) /* special case so that root path is "/", not "" */
307 p--;
308 buf[p] = '\0';
309 return p;
310 }
311 }
312
313 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
314 return -FDT_ERR_BADOFFSET;
315 else if (offset == -FDT_ERR_BADOFFSET)
316 return -FDT_ERR_BADSTRUCTURE;
317
318 return offset; /* error from fdt_next_node() */
319}
320
321int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
322 int supernodedepth, int *nodedepth)
323{
324 int offset, depth;
325 int supernodeoffset = -FDT_ERR_INTERNAL;
326
327 FDT_CHECK_HEADER(fdt);
328
329 if (supernodedepth < 0)
330 return -FDT_ERR_NOTFOUND;
331
332 for (offset = 0, depth = 0;
333 (offset >= 0) && (offset <= nodeoffset);
334 offset = fdt_next_node(fdt, offset, &depth)) {
335 if (depth == supernodedepth)
336 supernodeoffset = offset;
337
338 if (offset == nodeoffset) {
339 if (nodedepth)
340 *nodedepth = depth;
341
342 if (supernodedepth > depth)
343 return -FDT_ERR_NOTFOUND;
344 else
345 return supernodeoffset;
346 }
347 }
348
349 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
350 return -FDT_ERR_BADOFFSET;
351 else if (offset == -FDT_ERR_BADOFFSET)
352 return -FDT_ERR_BADSTRUCTURE;
353
354 return offset; /* error from fdt_next_node() */
355}
356
357int fdt_node_depth(const void *fdt, int nodeoffset)
358{
359 int nodedepth;
360 int err;
361
362 err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
363 if (err)
364 return (err < 0) ? err : -FDT_ERR_INTERNAL;
365 return nodedepth;
366}
367
368int fdt_parent_offset(const void *fdt, int nodeoffset)
369{
370 int nodedepth = fdt_node_depth(fdt, nodeoffset);
371
372 if (nodedepth < 0)
373 return nodedepth;
374 return fdt_supernode_atdepth_offset(fdt, nodeoffset,
375 nodedepth - 1, NULL);
376}
377
378int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
379 const char *propname,
380 const void *propval, int proplen)
381{
382 int offset;
383 const void *val;
384 int len;
385
386 FDT_CHECK_HEADER(fdt);
387
388 /* FIXME: The algorithm here is pretty horrible: we scan each
389 * property of a node in fdt_getprop(), then if that didn't
390 * find what we want, we scan over them again making our way
391 * to the next node. Still it's the easiest to implement
392 * approach; performance can come later. */
393 for (offset = fdt_next_node(fdt, startoffset, NULL);
394 offset >= 0;
395 offset = fdt_next_node(fdt, offset, NULL)) {
396 val = fdt_getprop(fdt, offset, propname, &len);
397 if (val && (len == proplen)
398 && (memcmp(val, propval, len) == 0))
399 return offset;
400 }
401
402 return offset; /* error from fdt_next_node() */
403}
404
405int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
406{
407 if ((phandle == 0) || (phandle == -1))
408 return -FDT_ERR_BADPHANDLE;
409 phandle = cpu_to_fdt32(phandle);
410 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
411 &phandle, sizeof(phandle));
412}
413
414int _stringlist_contains(const char *strlist, int listlen, const char *str)
415{
416 int len = strlen(str);
417 const char *p;
418
419 while (listlen >= len) {
420 if (memcmp(str, strlist, len+1) == 0)
421 return 1;
422 p = memchr(strlist, '\0', listlen);
423 if (!p)
424 return 0; /* malformed strlist.. */
425 listlen -= (p-strlist) + 1;
426 strlist = p + 1;
427 }
428 return 0;
429}
430
431int fdt_node_check_compatible(const void *fdt, int nodeoffset,
432 const char *compatible)
433{
434 const void *prop;
435 int len;
436
437 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
438 if (!prop)
439 return len;
440 if (_stringlist_contains(prop, len, compatible))
441 return 0;
442 else
443 return 1;
444}
445
446int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
447 const char *compatible)
448{
449 int offset, err;
450
451 FDT_CHECK_HEADER(fdt);
452
453 /* FIXME: The algorithm here is pretty horrible: we scan each
454 * property of a node in fdt_node_check_compatible(), then if
455 * that didn't find what we want, we scan over them again
456 * making our way to the next node. Still it's the easiest to
457 * implement approach; performance can come later. */
458 for (offset = fdt_next_node(fdt, startoffset, NULL);
459 offset >= 0;
460 offset = fdt_next_node(fdt, offset, NULL)) {
461 err = fdt_node_check_compatible(fdt, offset, compatible);
462 if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
463 return err;
464 else if (err == 0)
465 return offset;
466 }
467
468 return offset; /* error from fdt_next_node() */
469}
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
new file mode 100644
index 000000000000..8e7ec4cb7bcd
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -0,0 +1,463 @@
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 _fdt_blocks_misordered(const void *fdt,
59 int mem_rsv_size, int struct_size)
60{
61 return (fdt_off_mem_rsvmap(fdt) < 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 _fdt_rw_check_header(void *fdt)
71{
72 FDT_CHECK_HEADER(fdt);
73
74 if (fdt_version(fdt) < 17)
75 return -FDT_ERR_BADVERSION;
76 if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
77 fdt_size_dt_struct(fdt)))
78 return -FDT_ERR_BADLAYOUT;
79 if (fdt_version(fdt) > 17)
80 fdt_set_version(fdt, 17);
81
82 return 0;
83}
84
85#define FDT_RW_CHECK_HEADER(fdt) \
86 { \
87 int err; \
88 if ((err = _fdt_rw_check_header(fdt)) != 0) \
89 return err; \
90 }
91
92static inline int _fdt_data_size(void *fdt)
93{
94 return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
95}
96
97static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
98{
99 char *p = splicepoint;
100 char *end = (char *)fdt + _fdt_data_size(fdt);
101
102 if (((p + oldlen) < p) || ((p + oldlen) > end))
103 return -FDT_ERR_BADOFFSET;
104 if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
105 return -FDT_ERR_NOSPACE;
106 memmove(p + newlen, p + oldlen, end - p - oldlen);
107 return 0;
108}
109
110static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
111 int oldn, int newn)
112{
113 int delta = (newn - oldn) * sizeof(*p);
114 int err;
115 err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
116 if (err)
117 return err;
118 fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
119 fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
120 return 0;
121}
122
123static int _fdt_splice_struct(void *fdt, void *p,
124 int oldlen, int newlen)
125{
126 int delta = newlen - oldlen;
127 int err;
128
129 if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
130 return err;
131
132 fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
133 fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
134 return 0;
135}
136
137static int _fdt_splice_string(void *fdt, int newlen)
138{
139 void *p = (char *)fdt
140 + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
141 int err;
142
143 if ((err = _fdt_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 _fdt_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 = _fdt_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 FDT_RW_CHECK_HEADER(fdt);
178
179 re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
180 err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
181 if (err)
182 return err;
183
184 re->address = cpu_to_fdt64(address);
185 re->size = cpu_to_fdt64(size);
186 return 0;
187}
188
189int fdt_del_mem_rsv(void *fdt, int n)
190{
191 struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
192 int err;
193
194 FDT_RW_CHECK_HEADER(fdt);
195
196 if (n >= fdt_num_mem_rsv(fdt))
197 return -FDT_ERR_NOTFOUND;
198
199 err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
200 if (err)
201 return err;
202 return 0;
203}
204
205static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
206 int len, struct fdt_property **prop)
207{
208 int oldlen;
209 int err;
210
211 *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
212 if (! (*prop))
213 return oldlen;
214
215 if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
216 FDT_TAGALIGN(len))))
217 return err;
218
219 (*prop)->len = cpu_to_fdt32(len);
220 return 0;
221}
222
223static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
224 int len, struct fdt_property **prop)
225{
226 int proplen;
227 int nextoffset;
228 int namestroff;
229 int err;
230
231 if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
232 return nextoffset;
233
234 namestroff = _fdt_find_add_string(fdt, name);
235 if (namestroff < 0)
236 return namestroff;
237
238 *prop = _fdt_offset_ptr_w(fdt, nextoffset);
239 proplen = sizeof(**prop) + FDT_TAGALIGN(len);
240
241 err = _fdt_splice_struct(fdt, *prop, 0, proplen);
242 if (err)
243 return err;
244
245 (*prop)->tag = cpu_to_fdt32(FDT_PROP);
246 (*prop)->nameoff = cpu_to_fdt32(namestroff);
247 (*prop)->len = cpu_to_fdt32(len);
248 return 0;
249}
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
274int fdt_setprop(void *fdt, int nodeoffset, const char *name,
275 const void *val, int len)
276{
277 struct fdt_property *prop;
278 int err;
279
280 FDT_RW_CHECK_HEADER(fdt);
281
282 err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
283 if (err == -FDT_ERR_NOTFOUND)
284 err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
285 if (err)
286 return err;
287
288 memcpy(prop->data, val, len);
289 return 0;
290}
291
292int fdt_delprop(void *fdt, int nodeoffset, const char *name)
293{
294 struct fdt_property *prop;
295 int len, proplen;
296
297 FDT_RW_CHECK_HEADER(fdt);
298
299 prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
300 if (! prop)
301 return len;
302
303 proplen = sizeof(*prop) + FDT_TAGALIGN(len);
304 return _fdt_splice_struct(fdt, prop, proplen, 0);
305}
306
307int fdt_add_subnode_namelen(void *fdt, int parentoffset,
308 const char *name, int namelen)
309{
310 struct fdt_node_header *nh;
311 int offset, nextoffset;
312 int nodelen;
313 int err;
314 uint32_t tag;
315 uint32_t *endtag;
316
317 FDT_RW_CHECK_HEADER(fdt);
318
319 offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
320 if (offset >= 0)
321 return -FDT_ERR_EXISTS;
322 else if (offset != -FDT_ERR_NOTFOUND)
323 return offset;
324
325 /* Try to place the new node after the parent's properties */
326 fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
327 do {
328 offset = nextoffset;
329 tag = fdt_next_tag(fdt, offset, &nextoffset);
330 } while ((tag == FDT_PROP) || (tag == FDT_NOP));
331
332 nh = _fdt_offset_ptr_w(fdt, offset);
333 nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
334
335 err = _fdt_splice_struct(fdt, nh, 0, nodelen);
336 if (err)
337 return err;
338
339 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
340 memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
341 memcpy(nh->name, name, namelen);
342 endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
343 *endtag = cpu_to_fdt32(FDT_END_NODE);
344
345 return offset;
346}
347
348int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
349{
350 return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
351}
352
353int fdt_del_node(void *fdt, int nodeoffset)
354{
355 int endoffset;
356
357 FDT_RW_CHECK_HEADER(fdt);
358
359 endoffset = _fdt_node_end_offset(fdt, nodeoffset);
360 if (endoffset < 0)
361 return endoffset;
362
363 return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
364 endoffset - nodeoffset, 0);
365}
366
367static void _fdt_packblocks(const char *old, char *new,
368 int mem_rsv_size, int struct_size)
369{
370 int mem_rsv_off, struct_off, strings_off;
371
372 mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
373 struct_off = mem_rsv_off + mem_rsv_size;
374 strings_off = struct_off + struct_size;
375
376 memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
377 fdt_set_off_mem_rsvmap(new, mem_rsv_off);
378
379 memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
380 fdt_set_off_dt_struct(new, struct_off);
381 fdt_set_size_dt_struct(new, struct_size);
382
383 memmove(new + strings_off, old + fdt_off_dt_strings(old),
384 fdt_size_dt_strings(old));
385 fdt_set_off_dt_strings(new, strings_off);
386 fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
387}
388
389int fdt_open_into(const void *fdt, void *buf, int bufsize)
390{
391 int err;
392 int mem_rsv_size, struct_size;
393 int newsize;
394 const char *fdtstart = fdt;
395 const char *fdtend = fdtstart + fdt_totalsize(fdt);
396 char *tmp;
397
398 FDT_CHECK_HEADER(fdt);
399
400 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
401 * sizeof(struct fdt_reserve_entry);
402
403 if (fdt_version(fdt) >= 17) {
404 struct_size = fdt_size_dt_struct(fdt);
405 } else {
406 struct_size = 0;
407 while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
408 ;
409 }
410
411 if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
412 /* no further work necessary */
413 err = fdt_move(fdt, buf, bufsize);
414 if (err)
415 return err;
416 fdt_set_version(buf, 17);
417 fdt_set_size_dt_struct(buf, struct_size);
418 fdt_set_totalsize(buf, bufsize);
419 return 0;
420 }
421
422 /* Need to reorder */
423 newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
424 + struct_size + fdt_size_dt_strings(fdt);
425
426 if (bufsize < newsize)
427 return -FDT_ERR_NOSPACE;
428
429 /* First attempt to build converted tree at beginning of buffer */
430 tmp = buf;
431 /* But if that overlaps with the old tree... */
432 if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
433 /* Try right after the old tree instead */
434 tmp = (char *)(uintptr_t)fdtend;
435 if ((tmp + newsize) > ((char *)buf + bufsize))
436 return -FDT_ERR_NOSPACE;
437 }
438
439 _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
440 memmove(buf, tmp, newsize);
441
442 fdt_set_magic(buf, FDT_MAGIC);
443 fdt_set_totalsize(buf, bufsize);
444 fdt_set_version(buf, 17);
445 fdt_set_last_comp_version(buf, 16);
446 fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
447
448 return 0;
449}
450
451int fdt_pack(void *fdt)
452{
453 int mem_rsv_size;
454
455 FDT_RW_CHECK_HEADER(fdt);
456
457 mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
458 * sizeof(struct fdt_reserve_entry);
459 _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
460 fdt_set_totalsize(fdt, _fdt_data_size(fdt));
461
462 return 0;
463}
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
new file mode 100644
index 000000000000..e6c3ceee8c58
--- /dev/null
+++ b/scripts/dtc/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 fdt_errtabent {
59 const char *str;
60};
61
62#define FDT_ERRTABENT(val) \
63 [(val)] = { .str = #val, }
64
65static struct fdt_errtabent fdt_errtable[] = {
66 FDT_ERRTABENT(FDT_ERR_NOTFOUND),
67 FDT_ERRTABENT(FDT_ERR_EXISTS),
68 FDT_ERRTABENT(FDT_ERR_NOSPACE),
69
70 FDT_ERRTABENT(FDT_ERR_BADOFFSET),
71 FDT_ERRTABENT(FDT_ERR_BADPATH),
72 FDT_ERRTABENT(FDT_ERR_BADSTATE),
73
74 FDT_ERRTABENT(FDT_ERR_TRUNCATED),
75 FDT_ERRTABENT(FDT_ERR_BADMAGIC),
76 FDT_ERRTABENT(FDT_ERR_BADVERSION),
77 FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
78 FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
79};
80#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_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 > -FDT_ERRTABSIZE) {
89 const char *s = fdt_errtable[-errval].str;
90
91 if (s)
92 return s;
93 }
94
95 return "<unknown error>";
96}
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
new file mode 100644
index 000000000000..698329e0ccaf
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -0,0 +1,257 @@
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 _fdt_sw_check_header(void *fdt)
59{
60 if (fdt_magic(fdt) != FDT_SW_MAGIC)
61 return -FDT_ERR_BADMAGIC;
62 /* FIXME: should check more details about the header state */
63 return 0;
64}
65
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)
74{
75 int offset = fdt_size_dt_struct(fdt);
76 int spaceleft;
77
78 spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
79 - fdt_size_dt_strings(fdt);
80
81 if ((offset + len < offset) || (offset + len > spaceleft))
82 return NULL;
83
84 fdt_set_size_dt_struct(fdt, offset + len);
85 return fdt_offset_ptr_w(fdt, offset, len);
86}
87
88int fdt_create(void *buf, int bufsize)
89{
90 void *fdt = buf;
91
92 if (bufsize < sizeof(struct fdt_header))
93 return -FDT_ERR_NOSPACE;
94
95 memset(buf, 0, bufsize);
96
97 fdt_set_magic(fdt, FDT_SW_MAGIC);
98 fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
99 fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
100 fdt_set_totalsize(fdt, bufsize);
101
102 fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
103 sizeof(struct fdt_reserve_entry)));
104 fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
105 fdt_set_off_dt_strings(fdt, bufsize);
106
107 return 0;
108}
109
110int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
111{
112 struct fdt_reserve_entry *re;
113 int offset;
114
115 FDT_SW_CHECK_HEADER(fdt);
116
117 if (fdt_size_dt_struct(fdt))
118 return -FDT_ERR_BADSTATE;
119
120 offset = fdt_off_dt_struct(fdt);
121 if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
122 return -FDT_ERR_NOSPACE;
123
124 re = (struct fdt_reserve_entry *)((char *)fdt + offset);
125 re->address = cpu_to_fdt64(addr);
126 re->size = cpu_to_fdt64(size);
127
128 fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
129
130 return 0;
131}
132
133int fdt_finish_reservemap(void *fdt)
134{
135 return fdt_add_reservemap_entry(fdt, 0, 0);
136}
137
138int fdt_begin_node(void *fdt, const char *name)
139{
140 struct fdt_node_header *nh;
141 int namelen = strlen(name) + 1;
142
143 FDT_SW_CHECK_HEADER(fdt);
144
145 nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
146 if (! nh)
147 return -FDT_ERR_NOSPACE;
148
149 nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
150 memcpy(nh->name, name, namelen);
151 return 0;
152}
153
154int fdt_end_node(void *fdt)
155{
156 uint32_t *en;
157
158 FDT_SW_CHECK_HEADER(fdt);
159
160 en = _fdt_grab_space(fdt, FDT_TAGSIZE);
161 if (! en)
162 return -FDT_ERR_NOSPACE;
163
164 *en = cpu_to_fdt32(FDT_END_NODE);
165 return 0;
166}
167
168static int _fdt_find_add_string(void *fdt, const char *s)
169{
170 char *strtab = (char *)fdt + fdt_totalsize(fdt);
171 const char *p;
172 int strtabsize = fdt_size_dt_strings(fdt);
173 int len = strlen(s) + 1;
174 int struct_top, offset;
175
176 p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
177 if (p)
178 return p - strtab;
179
180 /* Add it */
181 offset = -strtabsize - len;
182 struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
183 if (fdt_totalsize(fdt) + offset < struct_top)
184 return 0; /* no more room :( */
185
186 memcpy(strtab + offset, s, len);
187 fdt_set_size_dt_strings(fdt, strtabsize + len);
188 return offset;
189}
190
191int fdt_property(void *fdt, const char *name, const void *val, int len)
192{
193 struct fdt_property *prop;
194 int nameoff;
195
196 FDT_SW_CHECK_HEADER(fdt);
197
198 nameoff = _fdt_find_add_string(fdt, name);
199 if (nameoff == 0)
200 return -FDT_ERR_NOSPACE;
201
202 prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
203 if (! prop)
204 return -FDT_ERR_NOSPACE;
205
206 prop->tag = cpu_to_fdt32(FDT_PROP);
207 prop->nameoff = cpu_to_fdt32(nameoff);
208 prop->len = cpu_to_fdt32(len);
209 memcpy(prop->data, val, len);
210 return 0;
211}
212
213int fdt_finish(void *fdt)
214{
215 char *p = (char *)fdt;
216 uint32_t *end;
217 int oldstroffset, newstroffset;
218 uint32_t tag;
219 int offset, nextoffset;
220
221 FDT_SW_CHECK_HEADER(fdt);
222
223 /* Add terminator */
224 end = _fdt_grab_space(fdt, sizeof(*end));
225 if (! end)
226 return -FDT_ERR_NOSPACE;
227 *end = cpu_to_fdt32(FDT_END);
228
229 /* Relocate the string table */
230 oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
231 newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
232 memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
233 fdt_set_off_dt_strings(fdt, newstroffset);
234
235 /* Walk the structure, correcting string offsets */
236 offset = 0;
237 while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
238 if (tag == FDT_PROP) {
239 struct fdt_property *prop =
240 fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
241 int nameoff;
242
243 if (! prop)
244 return -FDT_ERR_BADSTRUCTURE;
245
246 nameoff = fdt32_to_cpu(prop->nameoff);
247 nameoff += fdt_size_dt_strings(fdt);
248 prop->nameoff = cpu_to_fdt32(nameoff);
249 }
250 offset = nextoffset;
251 }
252
253 /* Finally, adjust the header */
254 fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
255 fdt_set_magic(fdt, FDT_MAGIC);
256 return 0;
257}
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
new file mode 100644
index 000000000000..a4652c6e787e
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -0,0 +1,145 @@
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 _fdt_nop_region(void *start, int len)
76{
77 uint32_t *p;
78
79 for (p = start; (char *)p < ((char *)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 _fdt_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 _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
143 endoffset - nodeoffset);
144 return 0;
145}
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
new file mode 100644
index 000000000000..ce80e4fb41b2
--- /dev/null
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -0,0 +1,1076 @@
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 *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
129}
130
131uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
132
133/**********************************************************************/
134/* Traversal functions */
135/**********************************************************************/
136
137int fdt_next_node(const void *fdt, int offset, int *depth);
138
139/**********************************************************************/
140/* General functions */
141/**********************************************************************/
142
143#define fdt_get_header(fdt, field) \
144 (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
145#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
146#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
147#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
148#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
149#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
150#define fdt_version(fdt) (fdt_get_header(fdt, version))
151#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
152#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
153#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
154#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
155
156#define __fdt_set_hdr(name) \
157 static inline void fdt_set_##name(void *fdt, uint32_t val) \
158 { \
159 struct fdt_header *fdth = fdt; \
160 fdth->name = cpu_to_fdt32(val); \
161 }
162__fdt_set_hdr(magic);
163__fdt_set_hdr(totalsize);
164__fdt_set_hdr(off_dt_struct);
165__fdt_set_hdr(off_dt_strings);
166__fdt_set_hdr(off_mem_rsvmap);
167__fdt_set_hdr(version);
168__fdt_set_hdr(last_comp_version);
169__fdt_set_hdr(boot_cpuid_phys);
170__fdt_set_hdr(size_dt_strings);
171__fdt_set_hdr(size_dt_struct);
172#undef __fdt_set_hdr
173
174/**
175 * fdt_check_header - sanity check a device tree or possible device tree
176 * @fdt: pointer to data which might be a flattened device tree
177 *
178 * fdt_check_header() checks that the given buffer contains what
179 * appears to be a flattened device tree with sane information in its
180 * header.
181 *
182 * returns:
183 * 0, if the buffer appears to contain a valid device tree
184 * -FDT_ERR_BADMAGIC,
185 * -FDT_ERR_BADVERSION,
186 * -FDT_ERR_BADSTATE, standard meanings, as above
187 */
188int fdt_check_header(const void *fdt);
189
190/**
191 * fdt_move - move a device tree around in memory
192 * @fdt: pointer to the device tree to move
193 * @buf: pointer to memory where the device is to be moved
194 * @bufsize: size of the memory space at buf
195 *
196 * fdt_move() relocates, if possible, the device tree blob located at
197 * fdt to the buffer at buf of size bufsize. The buffer may overlap
198 * with the existing device tree blob at fdt. Therefore,
199 * fdt_move(fdt, fdt, fdt_totalsize(fdt))
200 * should always succeed.
201 *
202 * returns:
203 * 0, on success
204 * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
205 * -FDT_ERR_BADMAGIC,
206 * -FDT_ERR_BADVERSION,
207 * -FDT_ERR_BADSTATE, standard meanings
208 */
209int fdt_move(const void *fdt, void *buf, int bufsize);
210
211/**********************************************************************/
212/* Read-only functions */
213/**********************************************************************/
214
215/**
216 * fdt_string - retrieve a string from the strings block of a device tree
217 * @fdt: pointer to the device tree blob
218 * @stroffset: offset of the string within the strings block (native endian)
219 *
220 * fdt_string() retrieves a pointer to a single string from the
221 * strings block of the device tree blob at fdt.
222 *
223 * returns:
224 * a pointer to the string, on success
225 * NULL, if stroffset is out of bounds
226 */
227const char *fdt_string(const void *fdt, int stroffset);
228
229/**
230 * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
231 * @fdt: pointer to the device tree blob
232 *
233 * Returns the number of entries in the device tree blob's memory
234 * reservation map. This does not include the terminating 0,0 entry
235 * or any other (0,0) entries reserved for expansion.
236 *
237 * returns:
238 * the number of entries
239 */
240int fdt_num_mem_rsv(const void *fdt);
241
242/**
243 * fdt_get_mem_rsv - retrieve one memory reserve map entry
244 * @fdt: pointer to the device tree blob
245 * @address, @size: pointers to 64-bit variables
246 *
247 * On success, *address and *size will contain the address and size of
248 * the n-th reserve map entry from the device tree blob, in
249 * native-endian format.
250 *
251 * returns:
252 * 0, on success
253 * -FDT_ERR_BADMAGIC,
254 * -FDT_ERR_BADVERSION,
255 * -FDT_ERR_BADSTATE, standard meanings
256 */
257int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
258
259/**
260 * fdt_subnode_offset_namelen - find a subnode based on substring
261 * @fdt: pointer to the device tree blob
262 * @parentoffset: structure block offset of a node
263 * @name: name of the subnode to locate
264 * @namelen: number of characters of name to consider
265 *
266 * Identical to fdt_subnode_offset(), but only examine the first
267 * namelen characters of name for matching the subnode name. This is
268 * useful for finding subnodes based on a portion of a larger string,
269 * such as a full path.
270 */
271int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
272 const char *name, int namelen);
273/**
274 * fdt_subnode_offset - find a subnode of a given node
275 * @fdt: pointer to the device tree blob
276 * @parentoffset: structure block offset of a node
277 * @name: name of the subnode to locate
278 *
279 * fdt_subnode_offset() finds a subnode of the node at structure block
280 * offset parentoffset with the given name. name may include a unit
281 * address, in which case fdt_subnode_offset() will find the subnode
282 * with that unit address, or the unit address may be omitted, in
283 * which case fdt_subnode_offset() will find an arbitrary subnode
284 * whose name excluding unit address matches the given name.
285 *
286 * returns:
287 * structure block offset of the requested subnode (>=0), on success
288 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
289 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
290 * -FDT_ERR_BADMAGIC,
291 * -FDT_ERR_BADVERSION,
292 * -FDT_ERR_BADSTATE,
293 * -FDT_ERR_BADSTRUCTURE,
294 * -FDT_ERR_TRUNCATED, standard meanings.
295 */
296int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
297
298/**
299 * fdt_path_offset - find a tree node by its full path
300 * @fdt: pointer to the device tree blob
301 * @path: full path of the node to locate
302 *
303 * fdt_path_offset() finds a node of a given path in the device tree.
304 * Each path component may omit the unit address portion, but the
305 * results of this are undefined if any such path component is
306 * ambiguous (that is if there are multiple nodes at the relevant
307 * level matching the given component, differentiated only by unit
308 * address).
309 *
310 * returns:
311 * structure block offset of the node with the requested path (>=0), on success
312 * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
313 * -FDT_ERR_NOTFOUND, if the requested node does not exist
314 * -FDT_ERR_BADMAGIC,
315 * -FDT_ERR_BADVERSION,
316 * -FDT_ERR_BADSTATE,
317 * -FDT_ERR_BADSTRUCTURE,
318 * -FDT_ERR_TRUNCATED, standard meanings.
319 */
320int fdt_path_offset(const void *fdt, const char *path);
321
322/**
323 * fdt_get_name - retrieve the name of a given node
324 * @fdt: pointer to the device tree blob
325 * @nodeoffset: structure block offset of the starting node
326 * @lenp: pointer to an integer variable (will be overwritten) or NULL
327 *
328 * fdt_get_name() retrieves the name (including unit address) of the
329 * device tree node at structure block offset nodeoffset. If lenp is
330 * non-NULL, the length of this name is also returned, in the integer
331 * pointed to by lenp.
332 *
333 * returns:
334 * pointer to the node's name, on success
335 * If lenp is non-NULL, *lenp contains the length of that name (>=0)
336 * NULL, on error
337 * if lenp is non-NULL *lenp contains an error code (<0):
338 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
339 * -FDT_ERR_BADMAGIC,
340 * -FDT_ERR_BADVERSION,
341 * -FDT_ERR_BADSTATE, standard meanings
342 */
343const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
344
345/**
346 * fdt_get_property - find a given property in a given node
347 * @fdt: pointer to the device tree blob
348 * @nodeoffset: offset of the node whose property to find
349 * @name: name of the property to find
350 * @lenp: pointer to an integer variable (will be overwritten) or NULL
351 *
352 * fdt_get_property() retrieves a pointer to the fdt_property
353 * structure within the device tree blob corresponding to the property
354 * named 'name' of the node at offset nodeoffset. If lenp is
355 * non-NULL, the length of the property value is also returned, in the
356 * integer pointed to by lenp.
357 *
358 * returns:
359 * pointer to the structure representing the property
360 * if lenp is non-NULL, *lenp contains the length of the property
361 * value (>=0)
362 * NULL, on error
363 * if lenp is non-NULL, *lenp contains an error code (<0):
364 * -FDT_ERR_NOTFOUND, node does not have named property
365 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
366 * -FDT_ERR_BADMAGIC,
367 * -FDT_ERR_BADVERSION,
368 * -FDT_ERR_BADSTATE,
369 * -FDT_ERR_BADSTRUCTURE,
370 * -FDT_ERR_TRUNCATED, standard meanings
371 */
372const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
373 const char *name, int *lenp);
374static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
375 const char *name,
376 int *lenp)
377{
378 return (struct fdt_property *)(uintptr_t)
379 fdt_get_property(fdt, nodeoffset, name, lenp);
380}
381
382/**
383 * fdt_getprop - retrieve the value of a given property
384 * @fdt: pointer to the device tree blob
385 * @nodeoffset: offset of the node whose property to find
386 * @name: name of the property to find
387 * @lenp: pointer to an integer variable (will be overwritten) or NULL
388 *
389 * fdt_getprop() retrieves a pointer to the value of the property
390 * named 'name' of the node at offset nodeoffset (this will be a
391 * pointer to within the device blob itself, not a copy of the value).
392 * If lenp is non-NULL, the length of the property value is also
393 * returned, in the integer pointed to by lenp.
394 *
395 * returns:
396 * pointer to the property's value
397 * if lenp is non-NULL, *lenp contains the length of the property
398 * value (>=0)
399 * NULL, on error
400 * if lenp is non-NULL, *lenp contains an error code (<0):
401 * -FDT_ERR_NOTFOUND, node does not have named property
402 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
403 * -FDT_ERR_BADMAGIC,
404 * -FDT_ERR_BADVERSION,
405 * -FDT_ERR_BADSTATE,
406 * -FDT_ERR_BADSTRUCTURE,
407 * -FDT_ERR_TRUNCATED, standard meanings
408 */
409const void *fdt_getprop(const void *fdt, int nodeoffset,
410 const char *name, int *lenp);
411static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
412 const char *name, int *lenp)
413{
414 return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
415}
416
417/**
418 * fdt_get_phandle - retrieve the phandle of a given node
419 * @fdt: pointer to the device tree blob
420 * @nodeoffset: structure block offset of the node
421 *
422 * fdt_get_phandle() retrieves the phandle of the device tree node at
423 * structure block offset nodeoffset.
424 *
425 * returns:
426 * the phandle of the node at nodeoffset, on success (!= 0, != -1)
427 * 0, if the node has no phandle, or another error occurs
428 */
429uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
430
431/**
432 * fdt_get_path - determine the full path of a node
433 * @fdt: pointer to the device tree blob
434 * @nodeoffset: offset of the node whose path to find
435 * @buf: character buffer to contain the returned path (will be overwritten)
436 * @buflen: size of the character buffer at buf
437 *
438 * fdt_get_path() computes the full path of the node at offset
439 * nodeoffset, and records that path in the buffer at buf.
440 *
441 * NOTE: This function is expensive, as it must scan the device tree
442 * structure from the start to nodeoffset.
443 *
444 * returns:
445 * 0, on success
446 * buf contains the absolute path of the node at
447 * nodeoffset, as a NUL-terminated string.
448 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
449 * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
450 * characters and will not fit in the given buffer.
451 * -FDT_ERR_BADMAGIC,
452 * -FDT_ERR_BADVERSION,
453 * -FDT_ERR_BADSTATE,
454 * -FDT_ERR_BADSTRUCTURE, standard meanings
455 */
456int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
457
458/**
459 * fdt_supernode_atdepth_offset - find a specific ancestor of a node
460 * @fdt: pointer to the device tree blob
461 * @nodeoffset: offset of the node whose parent to find
462 * @supernodedepth: depth of the ancestor to find
463 * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
464 *
465 * fdt_supernode_atdepth_offset() finds an ancestor of the given node
466 * at a specific depth from the root (where the root itself has depth
467 * 0, its immediate subnodes depth 1 and so forth). So
468 * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
469 * will always return 0, the offset of the root node. If the node at
470 * nodeoffset has depth D, then:
471 * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
472 * will return nodeoffset itself.
473 *
474 * NOTE: This function is expensive, as it must scan the device tree
475 * structure from the start to nodeoffset.
476 *
477 * returns:
478
479 * structure block offset of the node at node offset's ancestor
480 * of depth supernodedepth (>=0), on success
481 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
482* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
483 * -FDT_ERR_BADMAGIC,
484 * -FDT_ERR_BADVERSION,
485 * -FDT_ERR_BADSTATE,
486 * -FDT_ERR_BADSTRUCTURE, standard meanings
487 */
488int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
489 int supernodedepth, int *nodedepth);
490
491/**
492 * fdt_node_depth - find the depth of a given node
493 * @fdt: pointer to the device tree blob
494 * @nodeoffset: offset of the node whose parent to find
495 *
496 * fdt_node_depth() finds the depth of a given node. The root node
497 * has depth 0, its immediate subnodes depth 1 and so forth.
498 *
499 * NOTE: This function is expensive, as it must scan the device tree
500 * structure from the start to nodeoffset.
501 *
502 * returns:
503 * depth of the node at nodeoffset (>=0), on success
504 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
505 * -FDT_ERR_BADMAGIC,
506 * -FDT_ERR_BADVERSION,
507 * -FDT_ERR_BADSTATE,
508 * -FDT_ERR_BADSTRUCTURE, standard meanings
509 */
510int fdt_node_depth(const void *fdt, int nodeoffset);
511
512/**
513 * fdt_parent_offset - find the parent of a given node
514 * @fdt: pointer to the device tree blob
515 * @nodeoffset: offset of the node whose parent to find
516 *
517 * fdt_parent_offset() locates the parent node of a given node (that
518 * is, it finds the offset of the node which contains the node at
519 * nodeoffset as a subnode).
520 *
521 * NOTE: This function is expensive, as it must scan the device tree
522 * structure from the start to nodeoffset, *twice*.
523 *
524 * returns:
525 * structure block offset of the parent of the node at nodeoffset
526 * (>=0), on success
527 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
528 * -FDT_ERR_BADMAGIC,
529 * -FDT_ERR_BADVERSION,
530 * -FDT_ERR_BADSTATE,
531 * -FDT_ERR_BADSTRUCTURE, standard meanings
532 */
533int fdt_parent_offset(const void *fdt, int nodeoffset);
534
535/**
536 * fdt_node_offset_by_prop_value - find nodes with a given property value
537 * @fdt: pointer to the device tree blob
538 * @startoffset: only find nodes after this offset
539 * @propname: property name to check
540 * @propval: property value to search for
541 * @proplen: length of the value in propval
542 *
543 * fdt_node_offset_by_prop_value() returns the offset of the first
544 * node after startoffset, which has a property named propname whose
545 * value is of length proplen and has value equal to propval; or if
546 * startoffset is -1, the very first such node in the tree.
547 *
548 * To iterate through all nodes matching the criterion, the following
549 * idiom can be used:
550 * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
551 * propval, proplen);
552 * while (offset != -FDT_ERR_NOTFOUND) {
553 * // other code here
554 * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
555 * propval, proplen);
556 * }
557 *
558 * Note the -1 in the first call to the function, if 0 is used here
559 * instead, the function will never locate the root node, even if it
560 * matches the criterion.
561 *
562 * returns:
563 * structure block offset of the located node (>= 0, >startoffset),
564 * on success
565 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
566 * tree after startoffset
567 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
568 * -FDT_ERR_BADMAGIC,
569 * -FDT_ERR_BADVERSION,
570 * -FDT_ERR_BADSTATE,
571 * -FDT_ERR_BADSTRUCTURE, standard meanings
572 */
573int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
574 const char *propname,
575 const void *propval, int proplen);
576
577/**
578 * fdt_node_offset_by_phandle - find the node with a given phandle
579 * @fdt: pointer to the device tree blob
580 * @phandle: phandle value
581 *
582 * fdt_node_offset_by_phandle() returns the offset of the node
583 * which has the given phandle value. If there is more than one node
584 * in the tree with the given phandle (an invalid tree), results are
585 * undefined.
586 *
587 * returns:
588 * structure block offset of the located node (>= 0), on success
589 * -FDT_ERR_NOTFOUND, no node with that phandle exists
590 * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
591 * -FDT_ERR_BADMAGIC,
592 * -FDT_ERR_BADVERSION,
593 * -FDT_ERR_BADSTATE,
594 * -FDT_ERR_BADSTRUCTURE, standard meanings
595 */
596int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
597
598/**
599 * fdt_node_check_compatible: check a node's compatible property
600 * @fdt: pointer to the device tree blob
601 * @nodeoffset: offset of a tree node
602 * @compatible: string to match against
603 *
604 *
605 * fdt_node_check_compatible() returns 0 if the given node contains a
606 * 'compatible' property with the given string as one of its elements,
607 * it returns non-zero otherwise, or on error.
608 *
609 * returns:
610 * 0, if the node has a 'compatible' property listing the given string
611 * 1, if the node has a 'compatible' property, but it does not list
612 * the given string
613 * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
614 * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
615 * -FDT_ERR_BADMAGIC,
616 * -FDT_ERR_BADVERSION,
617 * -FDT_ERR_BADSTATE,
618 * -FDT_ERR_BADSTRUCTURE, standard meanings
619 */
620int fdt_node_check_compatible(const void *fdt, int nodeoffset,
621 const char *compatible);
622
623/**
624 * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
625 * @fdt: pointer to the device tree blob
626 * @startoffset: only find nodes after this offset
627 * @compatible: 'compatible' string to match against
628 *
629 * fdt_node_offset_by_compatible() returns the offset of the first
630 * node after startoffset, which has a 'compatible' property which
631 * lists the given compatible string; or if startoffset is -1, the
632 * very first such node in the tree.
633 *
634 * To iterate through all nodes matching the criterion, the following
635 * idiom can be used:
636 * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
637 * while (offset != -FDT_ERR_NOTFOUND) {
638 * // other code here
639 * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
640 * }
641 *
642 * Note the -1 in the first call to the function, if 0 is used here
643 * instead, the function will never locate the root node, even if it
644 * matches the criterion.
645 *
646 * returns:
647 * structure block offset of the located node (>= 0, >startoffset),
648 * on success
649 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
650 * tree after startoffset
651 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
652 * -FDT_ERR_BADMAGIC,
653 * -FDT_ERR_BADVERSION,
654 * -FDT_ERR_BADSTATE,
655 * -FDT_ERR_BADSTRUCTURE, standard meanings
656 */
657int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
658 const char *compatible);
659
660/**********************************************************************/
661/* Write-in-place functions */
662/**********************************************************************/
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 */
692int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
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 */
723static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
724 const char *name, uint32_t val)
725{
726 val = cpu_to_fdt32(val);
727 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
728}
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 */
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 */
778int fdt_nop_node(void *fdt, int nodeoffset);
779
780/**********************************************************************/
781/* Sequential write functions */
782/**********************************************************************/
783
784int fdt_create(void *buf, int bufsize);
785int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
786int fdt_finish_reservemap(void *fdt);
787int fdt_begin_node(void *fdt, const char *name);
788int fdt_property(void *fdt, const char *name, const void *val, int len);
789static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
790{
791 val = cpu_to_fdt32(val);
792 return fdt_property(fdt, name, &val, sizeof(val));
793}
794#define fdt_property_string(fdt, name, str) \
795 fdt_property(fdt, name, str, strlen(str)+1)
796int fdt_end_node(void *fdt);
797int fdt_finish(void *fdt);
798
799/**********************************************************************/
800/* Read-write functions */
801/**********************************************************************/
802
803int fdt_open_into(const void *fdt, void *buf, int bufsize);
804int fdt_pack(void *fdt);
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 */
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 */
852int fdt_del_mem_rsv(void *fdt, int n);
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 */
908int fdt_setprop(void *fdt, int nodeoffset, const char *name,
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 */
939static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
940 uint32_t val)
941{
942 val = cpu_to_fdt32(val);
943 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
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 */
974#define fdt_setprop_string(fdt, nodeoffset, name, str) \
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 */
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 */
1013int fdt_add_subnode_namelen(void *fdt, int parentoffset,
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 */
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 */
1068int fdt_del_node(void *fdt, int nodeoffset);
1069
1070/**********************************************************************/
1071/* Debugging / informational functions */
1072/**********************************************************************/
1073
1074const char *fdt_strerror(int errval);
1075
1076#endif /* _LIBFDT_H */
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
new file mode 100644
index 000000000000..449bf602daf1
--- /dev/null
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -0,0 +1,23 @@
1#ifndef _LIBFDT_ENV_H
2#define _LIBFDT_ENV_H
3
4#include <stddef.h>
5#include <stdint.h>
6#include <string.h>
7
8#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
9static inline uint32_t fdt32_to_cpu(uint32_t x)
10{
11 return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
12}
13#define cpu_to_fdt32(x) fdt32_to_cpu(x)
14
15static inline uint64_t fdt64_to_cpu(uint64_t x)
16{
17 return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
18 | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
19}
20#define cpu_to_fdt64(x) fdt64_to_cpu(x)
21#undef _B
22
23#endif /* _LIBFDT_ENV_H */
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
new file mode 100644
index 000000000000..46eb93e4af5c
--- /dev/null
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -0,0 +1,95 @@
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 FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
56#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
57
58#define FDT_CHECK_HEADER(fdt) \
59 { \
60 int err; \
61 if ((err = fdt_check_header(fdt)) != 0) \
62 return err; \
63 }
64
65uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
66int _fdt_check_node_offset(const void *fdt, int offset);
67const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
68int _fdt_node_end_offset(void *fdt, int nodeoffset);
69
70static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
71{
72 return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
73}
74
75static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
76{
77 return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
78}
79
80static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
81{
82 const struct fdt_reserve_entry *rsv_table =
83 (const struct fdt_reserve_entry *)
84 ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
85
86 return rsv_table + n;
87}
88static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
89{
90 return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
91}
92
93#define FDT_SW_MAGIC (~FDT_MAGIC)
94
95#endif /* _LIBFDT_INTERNAL_H */