aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/libfdt/fdt.c
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/fdt.c
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/fdt.c')
-rw-r--r--scripts/dtc/libfdt/fdt.c201
1 files changed, 201 insertions, 0 deletions
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}