Commit 0de71d507157c4bd4fddcd3a419140d2b986eed2
Committed by
Wolfgang Denk
1 parent
78acc472d9
Exists in
master
and in
54 other branches
Move libfdt/ into lib/
Move the libfdt directory into the common lib/ directory to clean up the top-level directory. Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
Showing 21 changed files with 1844 additions and 1844 deletions Side-by-side Diff
- Makefile
- lib/libfdt/Makefile
- lib/libfdt/README
- lib/libfdt/fdt.c
- lib/libfdt/fdt_ro.c
- lib/libfdt/fdt_rw.c
- lib/libfdt/fdt_strerror.c
- lib/libfdt/fdt_sw.c
- lib/libfdt/fdt_wip.c
- lib/libfdt/libfdt_internal.h
- libfdt/Makefile
- libfdt/README
- libfdt/fdt.c
- libfdt/fdt_ro.c
- libfdt/fdt_rw.c
- libfdt/fdt_strerror.c
- libfdt/fdt_sw.c
- libfdt/fdt_wip.c
- libfdt/libfdt_internal.h
- tools/Makefile
- tools/imls/Makefile
Makefile
lib/libfdt/Makefile
1 | +# | |
2 | +# (C) Copyright 2000-2007 | |
3 | +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | +# | |
5 | +# See file CREDITS for list of people who contributed to this | |
6 | +# project. | |
7 | +# | |
8 | +# This program 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 | |
11 | +# the License, or (at your option) any later version. | |
12 | +# | |
13 | +# This program 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 License | |
19 | +# along with this program; if not, write to the Free Software | |
20 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | +# MA 02111-1307 USA | |
22 | +# | |
23 | + | |
24 | +include $(TOPDIR)/config.mk | |
25 | + | |
26 | +LIB = $(obj)libfdt.a | |
27 | + | |
28 | +SOBJS = | |
29 | + | |
30 | +COBJS-libfdt += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o | |
31 | + | |
32 | +COBJS-$(CONFIG_OF_LIBFDT) += $(COBJS-libfdt) | |
33 | +COBJS-$(CONFIG_FIT) += $(COBJS-libfdt) | |
34 | + | |
35 | + | |
36 | +COBJS := $(sort $(COBJS-y)) | |
37 | +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) | |
38 | +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) | |
39 | + | |
40 | +$(LIB): $(obj).depend $(OBJS) | |
41 | + $(AR) $(ARFLAGS) $@ $(OBJS) | |
42 | + | |
43 | +######################################################################### | |
44 | + | |
45 | +# defines $(obj).depend target | |
46 | +include $(SRCTREE)/rules.mk | |
47 | + | |
48 | +sinclude $(obj).depend | |
49 | + | |
50 | +######################################################################### |
lib/libfdt/README
1 | +The libfdt functionality was written by David Gibson. The original | |
2 | +source came from the git repository: | |
3 | + | |
4 | +URL: git://ozlabs.org/home/dgibson/git/libfdt.git | |
5 | + | |
6 | +author David Gibson <dgibson@sneetch.(none)> | |
7 | + Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100) | |
8 | +committer David Gibson <dgibson@sneetch.(none)> | |
9 | + Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100) | |
10 | +commit 857f54e79f74429af20c2b5ecc00ee98af6a3b8b | |
11 | +tree 2f648f0f88225a51ded452968d28b4402df8ade0 | |
12 | +parent 07a12a08005f3b5cd9337900a6551e450c07b515 | |
13 | + | |
14 | +To adapt for u-boot usage, only the applicable files were copied and | |
15 | +imported into the u-boot git repository. | |
16 | +Omitted: | |
17 | +* GPL - u-boot comes with a copy of the GPL license | |
18 | +* test subdirectory - not directly useful for u-boot | |
19 | + | |
20 | +After importing, other customizations were performed. See the git log | |
21 | +for details. | |
22 | + | |
23 | +Jerry Van Baren |
lib/libfdt/fdt.c
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 | +#ifndef USE_HOSTCC | |
54 | +#include <fdt.h> | |
55 | +#include <libfdt.h> | |
56 | +#else | |
57 | +#include "fdt_host.h" | |
58 | +#endif | |
59 | + | |
60 | +#include "libfdt_internal.h" | |
61 | + | |
62 | +int fdt_check_header(const void *fdt) | |
63 | +{ | |
64 | + if (fdt_magic(fdt) == FDT_MAGIC) { | |
65 | + /* Complete tree */ | |
66 | + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |
67 | + return -FDT_ERR_BADVERSION; | |
68 | + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | |
69 | + return -FDT_ERR_BADVERSION; | |
70 | + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | |
71 | + /* Unfinished sequential-write blob */ | |
72 | + if (fdt_size_dt_struct(fdt) == 0) | |
73 | + return -FDT_ERR_BADSTATE; | |
74 | + } else { | |
75 | + return -FDT_ERR_BADMAGIC; | |
76 | + } | |
77 | + | |
78 | + return 0; | |
79 | +} | |
80 | + | |
81 | +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) | |
82 | +{ | |
83 | + const char *p; | |
84 | + | |
85 | + if (fdt_version(fdt) >= 0x11) | |
86 | + if (((offset + len) < offset) | |
87 | + || ((offset + len) > fdt_size_dt_struct(fdt))) | |
88 | + return NULL; | |
89 | + | |
90 | + p = _fdt_offset_ptr(fdt, offset); | |
91 | + | |
92 | + if (p + len < p) | |
93 | + return NULL; | |
94 | + return p; | |
95 | +} | |
96 | + | |
97 | +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) | |
98 | +{ | |
99 | + const uint32_t *tagp, *lenp; | |
100 | + uint32_t tag; | |
101 | + int offset = startoffset; | |
102 | + const char *p; | |
103 | + | |
104 | + *nextoffset = -FDT_ERR_TRUNCATED; | |
105 | + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); | |
106 | + if (!tagp) | |
107 | + return FDT_END; /* premature end */ | |
108 | + tag = fdt32_to_cpu(*tagp); | |
109 | + offset += FDT_TAGSIZE; | |
110 | + | |
111 | + *nextoffset = -FDT_ERR_BADSTRUCTURE; | |
112 | + switch (tag) { | |
113 | + case FDT_BEGIN_NODE: | |
114 | + /* skip name */ | |
115 | + do { | |
116 | + p = fdt_offset_ptr(fdt, offset++, 1); | |
117 | + } while (p && (*p != '\0')); | |
118 | + if (!p) | |
119 | + return FDT_END; /* premature end */ | |
120 | + break; | |
121 | + | |
122 | + case FDT_PROP: | |
123 | + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); | |
124 | + if (!lenp) | |
125 | + return FDT_END; /* premature end */ | |
126 | + /* skip-name offset, length and value */ | |
127 | + offset += sizeof(struct fdt_property) - FDT_TAGSIZE | |
128 | + + fdt32_to_cpu(*lenp); | |
129 | + break; | |
130 | + | |
131 | + case FDT_END: | |
132 | + case FDT_END_NODE: | |
133 | + case FDT_NOP: | |
134 | + break; | |
135 | + | |
136 | + default: | |
137 | + return FDT_END; | |
138 | + } | |
139 | + | |
140 | + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) | |
141 | + return FDT_END; /* premature end */ | |
142 | + | |
143 | + *nextoffset = FDT_TAGALIGN(offset); | |
144 | + return tag; | |
145 | +} | |
146 | + | |
147 | +int _fdt_check_node_offset(const void *fdt, int offset) | |
148 | +{ | |
149 | + if ((offset < 0) || (offset % FDT_TAGSIZE) | |
150 | + || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) | |
151 | + return -FDT_ERR_BADOFFSET; | |
152 | + | |
153 | + return offset; | |
154 | +} | |
155 | + | |
156 | +int fdt_next_node(const void *fdt, int offset, int *depth) | |
157 | +{ | |
158 | + int nextoffset = 0; | |
159 | + uint32_t tag; | |
160 | + | |
161 | + if (offset >= 0) | |
162 | + if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) | |
163 | + return nextoffset; | |
164 | + | |
165 | + do { | |
166 | + offset = nextoffset; | |
167 | + tag = fdt_next_tag(fdt, offset, &nextoffset); | |
168 | + | |
169 | + switch (tag) { | |
170 | + case FDT_PROP: | |
171 | + case FDT_NOP: | |
172 | + break; | |
173 | + | |
174 | + case FDT_BEGIN_NODE: | |
175 | + if (depth) | |
176 | + (*depth)++; | |
177 | + break; | |
178 | + | |
179 | + case FDT_END_NODE: | |
180 | + if (depth && ((--(*depth)) < 0)) | |
181 | + return nextoffset; | |
182 | + break; | |
183 | + | |
184 | + case FDT_END: | |
185 | + if ((nextoffset >= 0) | |
186 | + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) | |
187 | + return -FDT_ERR_NOTFOUND; | |
188 | + else | |
189 | + return nextoffset; | |
190 | + } | |
191 | + } while (tag != FDT_BEGIN_NODE); | |
192 | + | |
193 | + return offset; | |
194 | +} | |
195 | + | |
196 | +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) | |
197 | +{ | |
198 | + int len = strlen(s) + 1; | |
199 | + const char *last = strtab + tabsize - len; | |
200 | + const char *p; | |
201 | + | |
202 | + for (p = strtab; p <= last; p++) | |
203 | + if (memcmp(p, s, len) == 0) | |
204 | + return p; | |
205 | + return NULL; | |
206 | +} | |
207 | + | |
208 | +int fdt_move(const void *fdt, void *buf, int bufsize) | |
209 | +{ | |
210 | + FDT_CHECK_HEADER(fdt); | |
211 | + | |
212 | + if (fdt_totalsize(fdt) > bufsize) | |
213 | + return -FDT_ERR_NOSPACE; | |
214 | + | |
215 | + memmove(buf, fdt, fdt_totalsize(fdt)); | |
216 | + return 0; | |
217 | +} |
lib/libfdt/fdt_ro.c
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 | +#ifndef USE_HOSTCC | |
54 | +#include <fdt.h> | |
55 | +#include <libfdt.h> | |
56 | +#else | |
57 | +#include "fdt_host.h" | |
58 | +#endif | |
59 | + | |
60 | +#include "libfdt_internal.h" | |
61 | + | |
62 | +static int _fdt_nodename_eq(const void *fdt, int offset, | |
63 | + const char *s, int len) | |
64 | +{ | |
65 | + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); | |
66 | + | |
67 | + if (! p) | |
68 | + /* short match */ | |
69 | + return 0; | |
70 | + | |
71 | + if (memcmp(p, s, len) != 0) | |
72 | + return 0; | |
73 | + | |
74 | + if (p[len] == '\0') | |
75 | + return 1; | |
76 | + else if (!memchr(s, '@', len) && (p[len] == '@')) | |
77 | + return 1; | |
78 | + else | |
79 | + return 0; | |
80 | +} | |
81 | + | |
82 | +const char *fdt_string(const void *fdt, int stroffset) | |
83 | +{ | |
84 | + return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | |
85 | +} | |
86 | + | |
87 | +static int _fdt_string_eq(const void *fdt, int stroffset, | |
88 | + const char *s, int len) | |
89 | +{ | |
90 | + const char *p = fdt_string(fdt, stroffset); | |
91 | + | |
92 | + return (strlen(p) == len) && (memcmp(p, s, len) == 0); | |
93 | +} | |
94 | + | |
95 | +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) | |
96 | +{ | |
97 | + FDT_CHECK_HEADER(fdt); | |
98 | + *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); | |
99 | + *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); | |
100 | + return 0; | |
101 | +} | |
102 | + | |
103 | +int fdt_num_mem_rsv(const void *fdt) | |
104 | +{ | |
105 | + int i = 0; | |
106 | + | |
107 | + while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) | |
108 | + i++; | |
109 | + return i; | |
110 | +} | |
111 | + | |
112 | +int fdt_subnode_offset_namelen(const void *fdt, int offset, | |
113 | + const char *name, int namelen) | |
114 | +{ | |
115 | + int depth; | |
116 | + | |
117 | + FDT_CHECK_HEADER(fdt); | |
118 | + | |
119 | + for (depth = 0; | |
120 | + (offset >= 0) && (depth >= 0); | |
121 | + offset = fdt_next_node(fdt, offset, &depth)) | |
122 | + if ((depth == 1) | |
123 | + && _fdt_nodename_eq(fdt, offset, name, namelen)) | |
124 | + return offset; | |
125 | + | |
126 | + if (depth < 0) | |
127 | + return -FDT_ERR_NOTFOUND; | |
128 | + return offset; /* error */ | |
129 | +} | |
130 | + | |
131 | +int fdt_subnode_offset(const void *fdt, int parentoffset, | |
132 | + const char *name) | |
133 | +{ | |
134 | + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); | |
135 | +} | |
136 | + | |
137 | +int fdt_path_offset(const void *fdt, const char *path) | |
138 | +{ | |
139 | + const char *end = path + strlen(path); | |
140 | + const char *p = path; | |
141 | + int offset = 0; | |
142 | + | |
143 | + FDT_CHECK_HEADER(fdt); | |
144 | + | |
145 | + /* see if we have an alias */ | |
146 | + if (*path != '/') { | |
147 | + const char *q = strchr(path, '/'); | |
148 | + | |
149 | + if (!q) | |
150 | + q = end; | |
151 | + | |
152 | + p = fdt_get_alias_namelen(fdt, p, q - p); | |
153 | + if (!p) | |
154 | + return -FDT_ERR_BADPATH; | |
155 | + offset = fdt_path_offset(fdt, p); | |
156 | + | |
157 | + p = q; | |
158 | + } | |
159 | + | |
160 | + while (*p) { | |
161 | + const char *q; | |
162 | + | |
163 | + while (*p == '/') | |
164 | + p++; | |
165 | + if (! *p) | |
166 | + return offset; | |
167 | + q = strchr(p, '/'); | |
168 | + if (! q) | |
169 | + q = end; | |
170 | + | |
171 | + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); | |
172 | + if (offset < 0) | |
173 | + return offset; | |
174 | + | |
175 | + p = q; | |
176 | + } | |
177 | + | |
178 | + return offset; | |
179 | +} | |
180 | + | |
181 | +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) | |
182 | +{ | |
183 | + const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); | |
184 | + int err; | |
185 | + | |
186 | + if (((err = fdt_check_header(fdt)) != 0) | |
187 | + || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) | |
188 | + goto fail; | |
189 | + | |
190 | + if (len) | |
191 | + *len = strlen(nh->name); | |
192 | + | |
193 | + return nh->name; | |
194 | + | |
195 | + fail: | |
196 | + if (len) | |
197 | + *len = err; | |
198 | + return NULL; | |
199 | +} | |
200 | + | |
201 | +const struct fdt_property *fdt_get_property_namelen(const void *fdt, | |
202 | + int nodeoffset, | |
203 | + const char *name, | |
204 | + int namelen, int *lenp) | |
205 | +{ | |
206 | + uint32_t tag; | |
207 | + const struct fdt_property *prop; | |
208 | + int offset, nextoffset; | |
209 | + int err; | |
210 | + | |
211 | + if (((err = fdt_check_header(fdt)) != 0) | |
212 | + || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) | |
213 | + goto fail; | |
214 | + | |
215 | + nextoffset = err; | |
216 | + do { | |
217 | + offset = nextoffset; | |
218 | + | |
219 | + tag = fdt_next_tag(fdt, offset, &nextoffset); | |
220 | + switch (tag) { | |
221 | + case FDT_END: | |
222 | + if (nextoffset < 0) | |
223 | + err = nextoffset; | |
224 | + else | |
225 | + /* FDT_END tag with unclosed nodes */ | |
226 | + err = -FDT_ERR_BADSTRUCTURE; | |
227 | + goto fail; | |
228 | + | |
229 | + case FDT_PROP: | |
230 | + prop = _fdt_offset_ptr(fdt, offset); | |
231 | + if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), | |
232 | + name, namelen)) { | |
233 | + /* Found it! */ | |
234 | + if (lenp) | |
235 | + *lenp = fdt32_to_cpu(prop->len); | |
236 | + | |
237 | + return prop; | |
238 | + } | |
239 | + break; | |
240 | + } | |
241 | + } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); | |
242 | + | |
243 | + err = -FDT_ERR_NOTFOUND; | |
244 | + fail: | |
245 | + if (lenp) | |
246 | + *lenp = err; | |
247 | + return NULL; | |
248 | +} | |
249 | + | |
250 | +const struct fdt_property *fdt_get_property(const void *fdt, | |
251 | + int nodeoffset, | |
252 | + const char *name, int *lenp) | |
253 | +{ | |
254 | + return fdt_get_property_namelen(fdt, nodeoffset, name, | |
255 | + strlen(name), lenp); | |
256 | +} | |
257 | + | |
258 | +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | |
259 | + const char *name, int namelen, int *lenp) | |
260 | +{ | |
261 | + const struct fdt_property *prop; | |
262 | + | |
263 | + prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); | |
264 | + if (! prop) | |
265 | + return NULL; | |
266 | + | |
267 | + return prop->data; | |
268 | +} | |
269 | + | |
270 | +const void *fdt_getprop(const void *fdt, int nodeoffset, | |
271 | + const char *name, int *lenp) | |
272 | +{ | |
273 | + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); | |
274 | +} | |
275 | + | |
276 | +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) | |
277 | +{ | |
278 | + const uint32_t *php; | |
279 | + int len; | |
280 | + | |
281 | + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); | |
282 | + if (!php || (len != sizeof(*php))) | |
283 | + return 0; | |
284 | + | |
285 | + return fdt32_to_cpu(*php); | |
286 | +} | |
287 | + | |
288 | +const char *fdt_get_alias_namelen(const void *fdt, | |
289 | + const char *name, int namelen) | |
290 | +{ | |
291 | + int aliasoffset; | |
292 | + | |
293 | + aliasoffset = fdt_path_offset(fdt, "/aliases"); | |
294 | + if (aliasoffset < 0) | |
295 | + return NULL; | |
296 | + | |
297 | + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); | |
298 | +} | |
299 | + | |
300 | +const char *fdt_get_alias(const void *fdt, const char *name) | |
301 | +{ | |
302 | + return fdt_get_alias_namelen(fdt, name, strlen(name)); | |
303 | +} | |
304 | + | |
305 | +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |
306 | +{ | |
307 | + int pdepth = 0, p = 0; | |
308 | + int offset, depth, namelen; | |
309 | + const char *name; | |
310 | + | |
311 | + FDT_CHECK_HEADER(fdt); | |
312 | + | |
313 | + if (buflen < 2) | |
314 | + return -FDT_ERR_NOSPACE; | |
315 | + | |
316 | + for (offset = 0, depth = 0; | |
317 | + (offset >= 0) && (offset <= nodeoffset); | |
318 | + offset = fdt_next_node(fdt, offset, &depth)) { | |
319 | + while (pdepth > depth) { | |
320 | + do { | |
321 | + p--; | |
322 | + } while (buf[p-1] != '/'); | |
323 | + pdepth--; | |
324 | + } | |
325 | + | |
326 | + if (pdepth >= depth) { | |
327 | + name = fdt_get_name(fdt, offset, &namelen); | |
328 | + if (!name) | |
329 | + return namelen; | |
330 | + if ((p + namelen + 1) <= buflen) { | |
331 | + memcpy(buf + p, name, namelen); | |
332 | + p += namelen; | |
333 | + buf[p++] = '/'; | |
334 | + pdepth++; | |
335 | + } | |
336 | + } | |
337 | + | |
338 | + if (offset == nodeoffset) { | |
339 | + if (pdepth < (depth + 1)) | |
340 | + return -FDT_ERR_NOSPACE; | |
341 | + | |
342 | + if (p > 1) /* special case so that root path is "/", not "" */ | |
343 | + p--; | |
344 | + buf[p] = '\0'; | |
345 | + return 0; | |
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 | + | |
357 | +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | |
358 | + int supernodedepth, int *nodedepth) | |
359 | +{ | |
360 | + int offset, depth; | |
361 | + int supernodeoffset = -FDT_ERR_INTERNAL; | |
362 | + | |
363 | + FDT_CHECK_HEADER(fdt); | |
364 | + | |
365 | + if (supernodedepth < 0) | |
366 | + return -FDT_ERR_NOTFOUND; | |
367 | + | |
368 | + for (offset = 0, depth = 0; | |
369 | + (offset >= 0) && (offset <= nodeoffset); | |
370 | + offset = fdt_next_node(fdt, offset, &depth)) { | |
371 | + if (depth == supernodedepth) | |
372 | + supernodeoffset = offset; | |
373 | + | |
374 | + if (offset == nodeoffset) { | |
375 | + if (nodedepth) | |
376 | + *nodedepth = depth; | |
377 | + | |
378 | + if (supernodedepth > depth) | |
379 | + return -FDT_ERR_NOTFOUND; | |
380 | + else | |
381 | + return supernodeoffset; | |
382 | + } | |
383 | + } | |
384 | + | |
385 | + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | |
386 | + return -FDT_ERR_BADOFFSET; | |
387 | + else if (offset == -FDT_ERR_BADOFFSET) | |
388 | + return -FDT_ERR_BADSTRUCTURE; | |
389 | + | |
390 | + return offset; /* error from fdt_next_node() */ | |
391 | +} | |
392 | + | |
393 | +int fdt_node_depth(const void *fdt, int nodeoffset) | |
394 | +{ | |
395 | + int nodedepth; | |
396 | + int err; | |
397 | + | |
398 | + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); | |
399 | + if (err) | |
400 | + return (err < 0) ? err : -FDT_ERR_INTERNAL; | |
401 | + return nodedepth; | |
402 | +} | |
403 | + | |
404 | +int fdt_parent_offset(const void *fdt, int nodeoffset) | |
405 | +{ | |
406 | + int nodedepth = fdt_node_depth(fdt, nodeoffset); | |
407 | + | |
408 | + if (nodedepth < 0) | |
409 | + return nodedepth; | |
410 | + return fdt_supernode_atdepth_offset(fdt, nodeoffset, | |
411 | + nodedepth - 1, NULL); | |
412 | +} | |
413 | + | |
414 | +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, | |
415 | + const char *propname, | |
416 | + const void *propval, int proplen) | |
417 | +{ | |
418 | + int offset; | |
419 | + const void *val; | |
420 | + int len; | |
421 | + | |
422 | + FDT_CHECK_HEADER(fdt); | |
423 | + | |
424 | + /* FIXME: The algorithm here is pretty horrible: we scan each | |
425 | + * property of a node in fdt_getprop(), then if that didn't | |
426 | + * find what we want, we scan over them again making our way | |
427 | + * to the next node. Still it's the easiest to implement | |
428 | + * approach; performance can come later. */ | |
429 | + for (offset = fdt_next_node(fdt, startoffset, NULL); | |
430 | + offset >= 0; | |
431 | + offset = fdt_next_node(fdt, offset, NULL)) { | |
432 | + val = fdt_getprop(fdt, offset, propname, &len); | |
433 | + if (val && (len == proplen) | |
434 | + && (memcmp(val, propval, len) == 0)) | |
435 | + return offset; | |
436 | + } | |
437 | + | |
438 | + return offset; /* error from fdt_next_node() */ | |
439 | +} | |
440 | + | |
441 | +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) | |
442 | +{ | |
443 | + if ((phandle == 0) || (phandle == -1)) | |
444 | + return -FDT_ERR_BADPHANDLE; | |
445 | + phandle = cpu_to_fdt32(phandle); | |
446 | + return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", | |
447 | + &phandle, sizeof(phandle)); | |
448 | +} | |
449 | + | |
450 | +static int _fdt_stringlist_contains(const char *strlist, int listlen, | |
451 | + const char *str) | |
452 | +{ | |
453 | + int len = strlen(str); | |
454 | + const char *p; | |
455 | + | |
456 | + while (listlen >= len) { | |
457 | + if (memcmp(str, strlist, len+1) == 0) | |
458 | + return 1; | |
459 | + p = memchr(strlist, '\0', listlen); | |
460 | + if (!p) | |
461 | + return 0; /* malformed strlist.. */ | |
462 | + listlen -= (p-strlist) + 1; | |
463 | + strlist = p + 1; | |
464 | + } | |
465 | + return 0; | |
466 | +} | |
467 | + | |
468 | +int fdt_node_check_compatible(const void *fdt, int nodeoffset, | |
469 | + const char *compatible) | |
470 | +{ | |
471 | + const void *prop; | |
472 | + int len; | |
473 | + | |
474 | + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); | |
475 | + if (!prop) | |
476 | + return len; | |
477 | + if (_fdt_stringlist_contains(prop, len, compatible)) | |
478 | + return 0; | |
479 | + else | |
480 | + return 1; | |
481 | +} | |
482 | + | |
483 | +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | |
484 | + const char *compatible) | |
485 | +{ | |
486 | + int offset, err; | |
487 | + | |
488 | + FDT_CHECK_HEADER(fdt); | |
489 | + | |
490 | + /* FIXME: The algorithm here is pretty horrible: we scan each | |
491 | + * property of a node in fdt_node_check_compatible(), then if | |
492 | + * that didn't find what we want, we scan over them again | |
493 | + * making our way to the next node. Still it's the easiest to | |
494 | + * implement approach; performance can come later. */ | |
495 | + for (offset = fdt_next_node(fdt, startoffset, NULL); | |
496 | + offset >= 0; | |
497 | + offset = fdt_next_node(fdt, offset, NULL)) { | |
498 | + err = fdt_node_check_compatible(fdt, offset, compatible); | |
499 | + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) | |
500 | + return err; | |
501 | + else if (err == 0) | |
502 | + return offset; | |
503 | + } | |
504 | + | |
505 | + return offset; /* error from fdt_next_node() */ | |
506 | +} |
lib/libfdt/fdt_rw.c
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 | +#ifndef USE_HOSTCC | |
54 | +#include <fdt.h> | |
55 | +#include <libfdt.h> | |
56 | +#else | |
57 | +#include "fdt_host.h" | |
58 | +#endif | |
59 | + | |
60 | +#include "libfdt_internal.h" | |
61 | + | |
62 | +static int _fdt_blocks_misordered(const void *fdt, | |
63 | + int mem_rsv_size, int struct_size) | |
64 | +{ | |
65 | + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) | |
66 | + || (fdt_off_dt_struct(fdt) < | |
67 | + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) | |
68 | + || (fdt_off_dt_strings(fdt) < | |
69 | + (fdt_off_dt_struct(fdt) + struct_size)) | |
70 | + || (fdt_totalsize(fdt) < | |
71 | + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); | |
72 | +} | |
73 | + | |
74 | +static int _fdt_rw_check_header(void *fdt) | |
75 | +{ | |
76 | + FDT_CHECK_HEADER(fdt); | |
77 | + | |
78 | + if (fdt_version(fdt) < 17) | |
79 | + return -FDT_ERR_BADVERSION; | |
80 | + if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), | |
81 | + fdt_size_dt_struct(fdt))) | |
82 | + return -FDT_ERR_BADLAYOUT; | |
83 | + if (fdt_version(fdt) > 17) | |
84 | + fdt_set_version(fdt, 17); | |
85 | + | |
86 | + return 0; | |
87 | +} | |
88 | + | |
89 | +#define FDT_RW_CHECK_HEADER(fdt) \ | |
90 | + { \ | |
91 | + int err; \ | |
92 | + if ((err = _fdt_rw_check_header(fdt)) != 0) \ | |
93 | + return err; \ | |
94 | + } | |
95 | + | |
96 | +static inline int _fdt_data_size(void *fdt) | |
97 | +{ | |
98 | + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | |
99 | +} | |
100 | + | |
101 | +static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) | |
102 | +{ | |
103 | + char *p = splicepoint; | |
104 | + char *end = (char *)fdt + _fdt_data_size(fdt); | |
105 | + | |
106 | + if (((p + oldlen) < p) || ((p + oldlen) > end)) | |
107 | + return -FDT_ERR_BADOFFSET; | |
108 | + if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) | |
109 | + return -FDT_ERR_NOSPACE; | |
110 | + memmove(p + newlen, p + oldlen, end - p - oldlen); | |
111 | + return 0; | |
112 | +} | |
113 | + | |
114 | +static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, | |
115 | + int oldn, int newn) | |
116 | +{ | |
117 | + int delta = (newn - oldn) * sizeof(*p); | |
118 | + int err; | |
119 | + err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); | |
120 | + if (err) | |
121 | + return err; | |
122 | + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); | |
123 | + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); | |
124 | + return 0; | |
125 | +} | |
126 | + | |
127 | +static int _fdt_splice_struct(void *fdt, void *p, | |
128 | + int oldlen, int newlen) | |
129 | +{ | |
130 | + int delta = newlen - oldlen; | |
131 | + int err; | |
132 | + | |
133 | + if ((err = _fdt_splice(fdt, p, oldlen, newlen))) | |
134 | + return err; | |
135 | + | |
136 | + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); | |
137 | + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); | |
138 | + return 0; | |
139 | +} | |
140 | + | |
141 | +static int _fdt_splice_string(void *fdt, int newlen) | |
142 | +{ | |
143 | + void *p = (char *)fdt | |
144 | + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | |
145 | + int err; | |
146 | + | |
147 | + if ((err = _fdt_splice(fdt, p, 0, newlen))) | |
148 | + return err; | |
149 | + | |
150 | + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); | |
151 | + return 0; | |
152 | +} | |
153 | + | |
154 | +static int _fdt_find_add_string(void *fdt, const char *s) | |
155 | +{ | |
156 | + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); | |
157 | + const char *p; | |
158 | + char *new; | |
159 | + int len = strlen(s) + 1; | |
160 | + int err; | |
161 | + | |
162 | + p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); | |
163 | + if (p) | |
164 | + /* found it */ | |
165 | + return (p - strtab); | |
166 | + | |
167 | + new = strtab + fdt_size_dt_strings(fdt); | |
168 | + err = _fdt_splice_string(fdt, len); | |
169 | + if (err) | |
170 | + return err; | |
171 | + | |
172 | + memcpy(new, s, len); | |
173 | + return (new - strtab); | |
174 | +} | |
175 | + | |
176 | +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) | |
177 | +{ | |
178 | + struct fdt_reserve_entry *re; | |
179 | + int err; | |
180 | + | |
181 | + FDT_RW_CHECK_HEADER(fdt); | |
182 | + | |
183 | + re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); | |
184 | + err = _fdt_splice_mem_rsv(fdt, re, 0, 1); | |
185 | + if (err) | |
186 | + return err; | |
187 | + | |
188 | + re->address = cpu_to_fdt64(address); | |
189 | + re->size = cpu_to_fdt64(size); | |
190 | + return 0; | |
191 | +} | |
192 | + | |
193 | +int fdt_del_mem_rsv(void *fdt, int n) | |
194 | +{ | |
195 | + struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); | |
196 | + int err; | |
197 | + | |
198 | + FDT_RW_CHECK_HEADER(fdt); | |
199 | + | |
200 | + if (n >= fdt_num_mem_rsv(fdt)) | |
201 | + return -FDT_ERR_NOTFOUND; | |
202 | + | |
203 | + err = _fdt_splice_mem_rsv(fdt, re, 1, 0); | |
204 | + if (err) | |
205 | + return err; | |
206 | + return 0; | |
207 | +} | |
208 | + | |
209 | +static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, | |
210 | + int len, struct fdt_property **prop) | |
211 | +{ | |
212 | + int oldlen; | |
213 | + int err; | |
214 | + | |
215 | + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); | |
216 | + if (! (*prop)) | |
217 | + return oldlen; | |
218 | + | |
219 | + if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), | |
220 | + FDT_TAGALIGN(len)))) | |
221 | + return err; | |
222 | + | |
223 | + (*prop)->len = cpu_to_fdt32(len); | |
224 | + return 0; | |
225 | +} | |
226 | + | |
227 | +static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, | |
228 | + int len, struct fdt_property **prop) | |
229 | +{ | |
230 | + int proplen; | |
231 | + int nextoffset; | |
232 | + int namestroff; | |
233 | + int err; | |
234 | + | |
235 | + if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) | |
236 | + return nextoffset; | |
237 | + | |
238 | + namestroff = _fdt_find_add_string(fdt, name); | |
239 | + if (namestroff < 0) | |
240 | + return namestroff; | |
241 | + | |
242 | + *prop = _fdt_offset_ptr_w(fdt, nextoffset); | |
243 | + proplen = sizeof(**prop) + FDT_TAGALIGN(len); | |
244 | + | |
245 | + err = _fdt_splice_struct(fdt, *prop, 0, proplen); | |
246 | + if (err) | |
247 | + return err; | |
248 | + | |
249 | + (*prop)->tag = cpu_to_fdt32(FDT_PROP); | |
250 | + (*prop)->nameoff = cpu_to_fdt32(namestroff); | |
251 | + (*prop)->len = cpu_to_fdt32(len); | |
252 | + return 0; | |
253 | +} | |
254 | + | |
255 | +int fdt_set_name(void *fdt, int nodeoffset, const char *name) | |
256 | +{ | |
257 | + char *namep; | |
258 | + int oldlen, newlen; | |
259 | + int err; | |
260 | + | |
261 | + FDT_RW_CHECK_HEADER(fdt); | |
262 | + | |
263 | + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); | |
264 | + if (!namep) | |
265 | + return oldlen; | |
266 | + | |
267 | + newlen = strlen(name); | |
268 | + | |
269 | + err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), | |
270 | + FDT_TAGALIGN(newlen+1)); | |
271 | + if (err) | |
272 | + return err; | |
273 | + | |
274 | + memcpy(namep, name, newlen+1); | |
275 | + return 0; | |
276 | +} | |
277 | + | |
278 | +int fdt_setprop(void *fdt, int nodeoffset, const char *name, | |
279 | + const void *val, int len) | |
280 | +{ | |
281 | + struct fdt_property *prop; | |
282 | + int err; | |
283 | + | |
284 | + FDT_RW_CHECK_HEADER(fdt); | |
285 | + | |
286 | + err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); | |
287 | + if (err == -FDT_ERR_NOTFOUND) | |
288 | + err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); | |
289 | + if (err) | |
290 | + return err; | |
291 | + | |
292 | + memcpy(prop->data, val, len); | |
293 | + return 0; | |
294 | +} | |
295 | + | |
296 | +int fdt_delprop(void *fdt, int nodeoffset, const char *name) | |
297 | +{ | |
298 | + struct fdt_property *prop; | |
299 | + int len, proplen; | |
300 | + | |
301 | + FDT_RW_CHECK_HEADER(fdt); | |
302 | + | |
303 | + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | |
304 | + if (! prop) | |
305 | + return len; | |
306 | + | |
307 | + proplen = sizeof(*prop) + FDT_TAGALIGN(len); | |
308 | + return _fdt_splice_struct(fdt, prop, proplen, 0); | |
309 | +} | |
310 | + | |
311 | +int fdt_add_subnode_namelen(void *fdt, int parentoffset, | |
312 | + const char *name, int namelen) | |
313 | +{ | |
314 | + struct fdt_node_header *nh; | |
315 | + int offset, nextoffset; | |
316 | + int nodelen; | |
317 | + int err; | |
318 | + uint32_t tag; | |
319 | + uint32_t *endtag; | |
320 | + | |
321 | + FDT_RW_CHECK_HEADER(fdt); | |
322 | + | |
323 | + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); | |
324 | + if (offset >= 0) | |
325 | + return -FDT_ERR_EXISTS; | |
326 | + else if (offset != -FDT_ERR_NOTFOUND) | |
327 | + return offset; | |
328 | + | |
329 | + /* Try to place the new node after the parent's properties */ | |
330 | + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ | |
331 | + do { | |
332 | + offset = nextoffset; | |
333 | + tag = fdt_next_tag(fdt, offset, &nextoffset); | |
334 | + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); | |
335 | + | |
336 | + nh = _fdt_offset_ptr_w(fdt, offset); | |
337 | + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; | |
338 | + | |
339 | + err = _fdt_splice_struct(fdt, nh, 0, nodelen); | |
340 | + if (err) | |
341 | + return err; | |
342 | + | |
343 | + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); | |
344 | + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); | |
345 | + memcpy(nh->name, name, namelen); | |
346 | + endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); | |
347 | + *endtag = cpu_to_fdt32(FDT_END_NODE); | |
348 | + | |
349 | + return offset; | |
350 | +} | |
351 | + | |
352 | +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) | |
353 | +{ | |
354 | + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); | |
355 | +} | |
356 | + | |
357 | +int fdt_del_node(void *fdt, int nodeoffset) | |
358 | +{ | |
359 | + int endoffset; | |
360 | + | |
361 | + FDT_RW_CHECK_HEADER(fdt); | |
362 | + | |
363 | + endoffset = _fdt_node_end_offset(fdt, nodeoffset); | |
364 | + if (endoffset < 0) | |
365 | + return endoffset; | |
366 | + | |
367 | + return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), | |
368 | + endoffset - nodeoffset, 0); | |
369 | +} | |
370 | + | |
371 | +static void _fdt_packblocks(const char *old, char *new, | |
372 | + int mem_rsv_size, int struct_size) | |
373 | +{ | |
374 | + int mem_rsv_off, struct_off, strings_off; | |
375 | + | |
376 | + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); | |
377 | + struct_off = mem_rsv_off + mem_rsv_size; | |
378 | + strings_off = struct_off + struct_size; | |
379 | + | |
380 | + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); | |
381 | + fdt_set_off_mem_rsvmap(new, mem_rsv_off); | |
382 | + | |
383 | + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); | |
384 | + fdt_set_off_dt_struct(new, struct_off); | |
385 | + fdt_set_size_dt_struct(new, struct_size); | |
386 | + | |
387 | + memmove(new + strings_off, old + fdt_off_dt_strings(old), | |
388 | + fdt_size_dt_strings(old)); | |
389 | + fdt_set_off_dt_strings(new, strings_off); | |
390 | + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); | |
391 | +} | |
392 | + | |
393 | +int fdt_open_into(const void *fdt, void *buf, int bufsize) | |
394 | +{ | |
395 | + int err; | |
396 | + int mem_rsv_size, struct_size; | |
397 | + int newsize; | |
398 | + const char *fdtstart = fdt; | |
399 | + const char *fdtend = fdtstart + fdt_totalsize(fdt); | |
400 | + char *tmp; | |
401 | + | |
402 | + FDT_CHECK_HEADER(fdt); | |
403 | + | |
404 | + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | |
405 | + * sizeof(struct fdt_reserve_entry); | |
406 | + | |
407 | + if (fdt_version(fdt) >= 17) { | |
408 | + struct_size = fdt_size_dt_struct(fdt); | |
409 | + } else { | |
410 | + struct_size = 0; | |
411 | + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) | |
412 | + ; | |
413 | + if (struct_size < 0) | |
414 | + return struct_size; | |
415 | + } | |
416 | + | |
417 | + if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { | |
418 | + /* no further work necessary */ | |
419 | + err = fdt_move(fdt, buf, bufsize); | |
420 | + if (err) | |
421 | + return err; | |
422 | + fdt_set_version(buf, 17); | |
423 | + fdt_set_size_dt_struct(buf, struct_size); | |
424 | + fdt_set_totalsize(buf, bufsize); | |
425 | + return 0; | |
426 | + } | |
427 | + | |
428 | + /* Need to reorder */ | |
429 | + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size | |
430 | + + struct_size + fdt_size_dt_strings(fdt); | |
431 | + | |
432 | + if (bufsize < newsize) | |
433 | + return -FDT_ERR_NOSPACE; | |
434 | + | |
435 | + /* First attempt to build converted tree at beginning of buffer */ | |
436 | + tmp = buf; | |
437 | + /* But if that overlaps with the old tree... */ | |
438 | + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { | |
439 | + /* Try right after the old tree instead */ | |
440 | + tmp = (char *)(uintptr_t)fdtend; | |
441 | + if ((tmp + newsize) > ((char *)buf + bufsize)) | |
442 | + return -FDT_ERR_NOSPACE; | |
443 | + } | |
444 | + | |
445 | + _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); | |
446 | + memmove(buf, tmp, newsize); | |
447 | + | |
448 | + fdt_set_magic(buf, FDT_MAGIC); | |
449 | + fdt_set_totalsize(buf, bufsize); | |
450 | + fdt_set_version(buf, 17); | |
451 | + fdt_set_last_comp_version(buf, 16); | |
452 | + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); | |
453 | + | |
454 | + return 0; | |
455 | +} | |
456 | + | |
457 | +int fdt_pack(void *fdt) | |
458 | +{ | |
459 | + int mem_rsv_size; | |
460 | + | |
461 | + FDT_RW_CHECK_HEADER(fdt); | |
462 | + | |
463 | + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | |
464 | + * sizeof(struct fdt_reserve_entry); | |
465 | + _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); | |
466 | + fdt_set_totalsize(fdt, _fdt_data_size(fdt)); | |
467 | + | |
468 | + return 0; | |
469 | +} |
lib/libfdt/fdt_strerror.c
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 | +#ifndef USE_HOSTCC | |
54 | +#include <fdt.h> | |
55 | +#include <libfdt.h> | |
56 | +#else | |
57 | +#include "fdt_host.h" | |
58 | +#endif | |
59 | + | |
60 | +#include "libfdt_internal.h" | |
61 | + | |
62 | +struct fdt_errtabent { | |
63 | + const char *str; | |
64 | +}; | |
65 | + | |
66 | +#define FDT_ERRTABENT(val) \ | |
67 | + [(val)] = { .str = #val, } | |
68 | + | |
69 | +static struct fdt_errtabent fdt_errtable[] = { | |
70 | + FDT_ERRTABENT(FDT_ERR_NOTFOUND), | |
71 | + FDT_ERRTABENT(FDT_ERR_EXISTS), | |
72 | + FDT_ERRTABENT(FDT_ERR_NOSPACE), | |
73 | + | |
74 | + FDT_ERRTABENT(FDT_ERR_BADOFFSET), | |
75 | + FDT_ERRTABENT(FDT_ERR_BADPATH), | |
76 | + FDT_ERRTABENT(FDT_ERR_BADSTATE), | |
77 | + | |
78 | + FDT_ERRTABENT(FDT_ERR_TRUNCATED), | |
79 | + FDT_ERRTABENT(FDT_ERR_BADMAGIC), | |
80 | + FDT_ERRTABENT(FDT_ERR_BADVERSION), | |
81 | + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), | |
82 | + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), | |
83 | +}; | |
84 | +#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) | |
85 | + | |
86 | +const char *fdt_strerror(int errval) | |
87 | +{ | |
88 | + if (errval > 0) | |
89 | + return "<valid offset/length>"; | |
90 | + else if (errval == 0) | |
91 | + return "<no error>"; | |
92 | + else if (errval > -FDT_ERRTABSIZE) { | |
93 | + const char *s = fdt_errtable[-errval].str; | |
94 | + | |
95 | + if (s) | |
96 | + return s; | |
97 | + } | |
98 | + | |
99 | + return "<unknown error>"; | |
100 | +} |
lib/libfdt/fdt_sw.c
1 | +/* | |
2 | + * libfdt - Flat Device Tree manipulation | |
3 | + * Copyright (C) 2006 David Gibson, IBM Corporation. | |
4 | + * | |
5 | + * libfdt is dual licensed: you can use it either under the terms of | |
6 | + * the GPL, or the BSD license, at your option. | |
7 | + * | |
8 | + * a) This library is free software; you can redistribute it and/or | |
9 | + * modify it under the terms of the GNU General Public License as | |
10 | + * published by the Free Software Foundation; either version 2 of the | |
11 | + * License, or (at your option) any later version. | |
12 | + * | |
13 | + * This library is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public | |
19 | + * License along with this library; if not, write to the Free | |
20 | + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
21 | + * MA 02110-1301 USA | |
22 | + * | |
23 | + * Alternatively, | |
24 | + * | |
25 | + * b) Redistribution and use in source and binary forms, with or | |
26 | + * without modification, are permitted provided that the following | |
27 | + * conditions are met: | |
28 | + * | |
29 | + * 1. Redistributions of source code must retain the above | |
30 | + * copyright notice, this list of conditions and the following | |
31 | + * disclaimer. | |
32 | + * 2. Redistributions in binary form must reproduce the above | |
33 | + * copyright notice, this list of conditions and the following | |
34 | + * disclaimer in the documentation and/or other materials | |
35 | + * provided with the distribution. | |
36 | + * | |
37 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |
38 | + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
39 | + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
40 | + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
41 | + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
42 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
43 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
44 | + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
45 | + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
46 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
47 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
48 | + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
49 | + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
50 | + */ | |
51 | +#include "libfdt_env.h" | |
52 | + | |
53 | +#include <fdt.h> | |
54 | +#include <libfdt.h> | |
55 | + | |
56 | +#include "libfdt_internal.h" | |
57 | + | |
58 | +static 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 | + | |
73 | +static void *_fdt_grab_space(void *fdt, size_t 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); | |
86 | +} | |
87 | + | |
88 | +int 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 | + | |
110 | +int 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 | + | |
133 | +int fdt_finish_reservemap(void *fdt) | |
134 | +{ | |
135 | + return fdt_add_reservemap_entry(fdt, 0, 0); | |
136 | +} | |
137 | + | |
138 | +int 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 | + | |
154 | +int 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 | + | |
168 | +static 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 | + | |
191 | +int 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 | + | |
213 | +int 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); | |
241 | + int nameoff; | |
242 | + | |
243 | + nameoff = fdt32_to_cpu(prop->nameoff); | |
244 | + nameoff += fdt_size_dt_strings(fdt); | |
245 | + prop->nameoff = cpu_to_fdt32(nameoff); | |
246 | + } | |
247 | + offset = nextoffset; | |
248 | + } | |
249 | + if (nextoffset < 0) | |
250 | + return nextoffset; | |
251 | + | |
252 | + /* Finally, adjust the header */ | |
253 | + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); | |
254 | + fdt_set_magic(fdt, FDT_MAGIC); | |
255 | + return 0; | |
256 | +} |
lib/libfdt/fdt_wip.c
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 | +#ifndef USE_HOSTCC | |
54 | +#include <fdt.h> | |
55 | +#include <libfdt.h> | |
56 | +#else | |
57 | +#include "fdt_host.h" | |
58 | +#endif | |
59 | + | |
60 | +#include "libfdt_internal.h" | |
61 | + | |
62 | +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, | |
63 | + const void *val, int len) | |
64 | +{ | |
65 | + void *propval; | |
66 | + int proplen; | |
67 | + | |
68 | + propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); | |
69 | + if (! propval) | |
70 | + return proplen; | |
71 | + | |
72 | + if (proplen != len) | |
73 | + return -FDT_ERR_NOSPACE; | |
74 | + | |
75 | + memcpy(propval, val, len); | |
76 | + return 0; | |
77 | +} | |
78 | + | |
79 | +static void _fdt_nop_region(void *start, int len) | |
80 | +{ | |
81 | + uint32_t *p; | |
82 | + | |
83 | + for (p = start; (char *)p < ((char *)start + len); p++) | |
84 | + *p = cpu_to_fdt32(FDT_NOP); | |
85 | +} | |
86 | + | |
87 | +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) | |
88 | +{ | |
89 | + struct fdt_property *prop; | |
90 | + int len; | |
91 | + | |
92 | + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | |
93 | + if (! prop) | |
94 | + return len; | |
95 | + | |
96 | + _fdt_nop_region(prop, len + sizeof(*prop)); | |
97 | + | |
98 | + return 0; | |
99 | +} | |
100 | + | |
101 | +int _fdt_node_end_offset(void *fdt, int offset) | |
102 | +{ | |
103 | + int depth = 0; | |
104 | + | |
105 | + while ((offset >= 0) && (depth >= 0)) | |
106 | + offset = fdt_next_node(fdt, offset, &depth); | |
107 | + | |
108 | + return offset; | |
109 | +} | |
110 | + | |
111 | +int fdt_nop_node(void *fdt, int nodeoffset) | |
112 | +{ | |
113 | + int endoffset; | |
114 | + | |
115 | + endoffset = _fdt_node_end_offset(fdt, nodeoffset); | |
116 | + if (endoffset < 0) | |
117 | + return endoffset; | |
118 | + | |
119 | + _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), | |
120 | + endoffset - nodeoffset); | |
121 | + return 0; | |
122 | +} |
lib/libfdt/libfdt_internal.h
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 | + | |
65 | +int _fdt_check_node_offset(const void *fdt, int offset); | |
66 | +const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); | |
67 | +int _fdt_node_end_offset(void *fdt, int nodeoffset); | |
68 | + | |
69 | +static inline const void *_fdt_offset_ptr(const void *fdt, int offset) | |
70 | +{ | |
71 | + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; | |
72 | +} | |
73 | + | |
74 | +static inline void *_fdt_offset_ptr_w(void *fdt, int offset) | |
75 | +{ | |
76 | + return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); | |
77 | +} | |
78 | + | |
79 | +static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) | |
80 | +{ | |
81 | + const struct fdt_reserve_entry *rsv_table = | |
82 | + (const struct fdt_reserve_entry *) | |
83 | + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); | |
84 | + | |
85 | + return rsv_table + n; | |
86 | +} | |
87 | +static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) | |
88 | +{ | |
89 | + return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); | |
90 | +} | |
91 | + | |
92 | +#define FDT_SW_MAGIC (~FDT_MAGIC) | |
93 | + | |
94 | +#endif /* _LIBFDT_INTERNAL_H */ |
libfdt/Makefile
1 | -# | |
2 | -# (C) Copyright 2000-2007 | |
3 | -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | -# | |
5 | -# See file CREDITS for list of people who contributed to this | |
6 | -# project. | |
7 | -# | |
8 | -# This program 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 | |
11 | -# the License, or (at your option) any later version. | |
12 | -# | |
13 | -# This program 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 License | |
19 | -# along with this program; if not, write to the Free Software | |
20 | -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | -# MA 02111-1307 USA | |
22 | -# | |
23 | - | |
24 | -include $(TOPDIR)/config.mk | |
25 | - | |
26 | -LIB = $(obj)libfdt.a | |
27 | - | |
28 | -SOBJS = | |
29 | - | |
30 | -COBJS-libfdt += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o | |
31 | - | |
32 | -COBJS-$(CONFIG_OF_LIBFDT) += $(COBJS-libfdt) | |
33 | -COBJS-$(CONFIG_FIT) += $(COBJS-libfdt) | |
34 | - | |
35 | - | |
36 | -COBJS := $(sort $(COBJS-y)) | |
37 | -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) | |
38 | -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) | |
39 | - | |
40 | -$(LIB): $(obj).depend $(OBJS) | |
41 | - $(AR) $(ARFLAGS) $@ $(OBJS) | |
42 | - | |
43 | -######################################################################### | |
44 | - | |
45 | -# defines $(obj).depend target | |
46 | -include $(SRCTREE)/rules.mk | |
47 | - | |
48 | -sinclude $(obj).depend | |
49 | - | |
50 | -######################################################################### |
libfdt/README
1 | -The libfdt functionality was written by David Gibson. The original | |
2 | -source came from the git repository: | |
3 | - | |
4 | -URL: git://ozlabs.org/home/dgibson/git/libfdt.git | |
5 | - | |
6 | -author David Gibson <dgibson@sneetch.(none)> | |
7 | - Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100) | |
8 | -committer David Gibson <dgibson@sneetch.(none)> | |
9 | - Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100) | |
10 | -commit 857f54e79f74429af20c2b5ecc00ee98af6a3b8b | |
11 | -tree 2f648f0f88225a51ded452968d28b4402df8ade0 | |
12 | -parent 07a12a08005f3b5cd9337900a6551e450c07b515 | |
13 | - | |
14 | -To adapt for u-boot usage, only the applicable files were copied and | |
15 | -imported into the u-boot git repository. | |
16 | -Omitted: | |
17 | -* GPL - u-boot comes with a copy of the GPL license | |
18 | -* test subdirectory - not directly useful for u-boot | |
19 | - | |
20 | -After importing, other customizations were performed. See the git log | |
21 | -for details. | |
22 | - | |
23 | -Jerry Van Baren |
libfdt/fdt.c
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 | -#ifndef USE_HOSTCC | |
54 | -#include <fdt.h> | |
55 | -#include <libfdt.h> | |
56 | -#else | |
57 | -#include "fdt_host.h" | |
58 | -#endif | |
59 | - | |
60 | -#include "libfdt_internal.h" | |
61 | - | |
62 | -int fdt_check_header(const void *fdt) | |
63 | -{ | |
64 | - if (fdt_magic(fdt) == FDT_MAGIC) { | |
65 | - /* Complete tree */ | |
66 | - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | |
67 | - return -FDT_ERR_BADVERSION; | |
68 | - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | |
69 | - return -FDT_ERR_BADVERSION; | |
70 | - } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | |
71 | - /* Unfinished sequential-write blob */ | |
72 | - if (fdt_size_dt_struct(fdt) == 0) | |
73 | - return -FDT_ERR_BADSTATE; | |
74 | - } else { | |
75 | - return -FDT_ERR_BADMAGIC; | |
76 | - } | |
77 | - | |
78 | - return 0; | |
79 | -} | |
80 | - | |
81 | -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) | |
82 | -{ | |
83 | - const char *p; | |
84 | - | |
85 | - if (fdt_version(fdt) >= 0x11) | |
86 | - if (((offset + len) < offset) | |
87 | - || ((offset + len) > fdt_size_dt_struct(fdt))) | |
88 | - return NULL; | |
89 | - | |
90 | - p = _fdt_offset_ptr(fdt, offset); | |
91 | - | |
92 | - if (p + len < p) | |
93 | - return NULL; | |
94 | - return p; | |
95 | -} | |
96 | - | |
97 | -uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) | |
98 | -{ | |
99 | - const uint32_t *tagp, *lenp; | |
100 | - uint32_t tag; | |
101 | - int offset = startoffset; | |
102 | - const char *p; | |
103 | - | |
104 | - *nextoffset = -FDT_ERR_TRUNCATED; | |
105 | - tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); | |
106 | - if (!tagp) | |
107 | - return FDT_END; /* premature end */ | |
108 | - tag = fdt32_to_cpu(*tagp); | |
109 | - offset += FDT_TAGSIZE; | |
110 | - | |
111 | - *nextoffset = -FDT_ERR_BADSTRUCTURE; | |
112 | - switch (tag) { | |
113 | - case FDT_BEGIN_NODE: | |
114 | - /* skip name */ | |
115 | - do { | |
116 | - p = fdt_offset_ptr(fdt, offset++, 1); | |
117 | - } while (p && (*p != '\0')); | |
118 | - if (!p) | |
119 | - return FDT_END; /* premature end */ | |
120 | - break; | |
121 | - | |
122 | - case FDT_PROP: | |
123 | - lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); | |
124 | - if (!lenp) | |
125 | - return FDT_END; /* premature end */ | |
126 | - /* skip-name offset, length and value */ | |
127 | - offset += sizeof(struct fdt_property) - FDT_TAGSIZE | |
128 | - + fdt32_to_cpu(*lenp); | |
129 | - break; | |
130 | - | |
131 | - case FDT_END: | |
132 | - case FDT_END_NODE: | |
133 | - case FDT_NOP: | |
134 | - break; | |
135 | - | |
136 | - default: | |
137 | - return FDT_END; | |
138 | - } | |
139 | - | |
140 | - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) | |
141 | - return FDT_END; /* premature end */ | |
142 | - | |
143 | - *nextoffset = FDT_TAGALIGN(offset); | |
144 | - return tag; | |
145 | -} | |
146 | - | |
147 | -int _fdt_check_node_offset(const void *fdt, int offset) | |
148 | -{ | |
149 | - if ((offset < 0) || (offset % FDT_TAGSIZE) | |
150 | - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) | |
151 | - return -FDT_ERR_BADOFFSET; | |
152 | - | |
153 | - return offset; | |
154 | -} | |
155 | - | |
156 | -int fdt_next_node(const void *fdt, int offset, int *depth) | |
157 | -{ | |
158 | - int nextoffset = 0; | |
159 | - uint32_t tag; | |
160 | - | |
161 | - if (offset >= 0) | |
162 | - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) | |
163 | - return nextoffset; | |
164 | - | |
165 | - do { | |
166 | - offset = nextoffset; | |
167 | - tag = fdt_next_tag(fdt, offset, &nextoffset); | |
168 | - | |
169 | - switch (tag) { | |
170 | - case FDT_PROP: | |
171 | - case FDT_NOP: | |
172 | - break; | |
173 | - | |
174 | - case FDT_BEGIN_NODE: | |
175 | - if (depth) | |
176 | - (*depth)++; | |
177 | - break; | |
178 | - | |
179 | - case FDT_END_NODE: | |
180 | - if (depth && ((--(*depth)) < 0)) | |
181 | - return nextoffset; | |
182 | - break; | |
183 | - | |
184 | - case FDT_END: | |
185 | - if ((nextoffset >= 0) | |
186 | - || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) | |
187 | - return -FDT_ERR_NOTFOUND; | |
188 | - else | |
189 | - return nextoffset; | |
190 | - } | |
191 | - } while (tag != FDT_BEGIN_NODE); | |
192 | - | |
193 | - return offset; | |
194 | -} | |
195 | - | |
196 | -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) | |
197 | -{ | |
198 | - int len = strlen(s) + 1; | |
199 | - const char *last = strtab + tabsize - len; | |
200 | - const char *p; | |
201 | - | |
202 | - for (p = strtab; p <= last; p++) | |
203 | - if (memcmp(p, s, len) == 0) | |
204 | - return p; | |
205 | - return NULL; | |
206 | -} | |
207 | - | |
208 | -int fdt_move(const void *fdt, void *buf, int bufsize) | |
209 | -{ | |
210 | - FDT_CHECK_HEADER(fdt); | |
211 | - | |
212 | - if (fdt_totalsize(fdt) > bufsize) | |
213 | - return -FDT_ERR_NOSPACE; | |
214 | - | |
215 | - memmove(buf, fdt, fdt_totalsize(fdt)); | |
216 | - return 0; | |
217 | -} |
libfdt/fdt_ro.c
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 | -#ifndef USE_HOSTCC | |
54 | -#include <fdt.h> | |
55 | -#include <libfdt.h> | |
56 | -#else | |
57 | -#include "fdt_host.h" | |
58 | -#endif | |
59 | - | |
60 | -#include "libfdt_internal.h" | |
61 | - | |
62 | -static int _fdt_nodename_eq(const void *fdt, int offset, | |
63 | - const char *s, int len) | |
64 | -{ | |
65 | - const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); | |
66 | - | |
67 | - if (! p) | |
68 | - /* short match */ | |
69 | - return 0; | |
70 | - | |
71 | - if (memcmp(p, s, len) != 0) | |
72 | - return 0; | |
73 | - | |
74 | - if (p[len] == '\0') | |
75 | - return 1; | |
76 | - else if (!memchr(s, '@', len) && (p[len] == '@')) | |
77 | - return 1; | |
78 | - else | |
79 | - return 0; | |
80 | -} | |
81 | - | |
82 | -const char *fdt_string(const void *fdt, int stroffset) | |
83 | -{ | |
84 | - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | |
85 | -} | |
86 | - | |
87 | -static int _fdt_string_eq(const void *fdt, int stroffset, | |
88 | - const char *s, int len) | |
89 | -{ | |
90 | - const char *p = fdt_string(fdt, stroffset); | |
91 | - | |
92 | - return (strlen(p) == len) && (memcmp(p, s, len) == 0); | |
93 | -} | |
94 | - | |
95 | -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) | |
96 | -{ | |
97 | - FDT_CHECK_HEADER(fdt); | |
98 | - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); | |
99 | - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); | |
100 | - return 0; | |
101 | -} | |
102 | - | |
103 | -int fdt_num_mem_rsv(const void *fdt) | |
104 | -{ | |
105 | - int i = 0; | |
106 | - | |
107 | - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) | |
108 | - i++; | |
109 | - return i; | |
110 | -} | |
111 | - | |
112 | -int fdt_subnode_offset_namelen(const void *fdt, int offset, | |
113 | - const char *name, int namelen) | |
114 | -{ | |
115 | - int depth; | |
116 | - | |
117 | - FDT_CHECK_HEADER(fdt); | |
118 | - | |
119 | - for (depth = 0; | |
120 | - (offset >= 0) && (depth >= 0); | |
121 | - offset = fdt_next_node(fdt, offset, &depth)) | |
122 | - if ((depth == 1) | |
123 | - && _fdt_nodename_eq(fdt, offset, name, namelen)) | |
124 | - return offset; | |
125 | - | |
126 | - if (depth < 0) | |
127 | - return -FDT_ERR_NOTFOUND; | |
128 | - return offset; /* error */ | |
129 | -} | |
130 | - | |
131 | -int fdt_subnode_offset(const void *fdt, int parentoffset, | |
132 | - const char *name) | |
133 | -{ | |
134 | - return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); | |
135 | -} | |
136 | - | |
137 | -int fdt_path_offset(const void *fdt, const char *path) | |
138 | -{ | |
139 | - const char *end = path + strlen(path); | |
140 | - const char *p = path; | |
141 | - int offset = 0; | |
142 | - | |
143 | - FDT_CHECK_HEADER(fdt); | |
144 | - | |
145 | - /* see if we have an alias */ | |
146 | - if (*path != '/') { | |
147 | - const char *q = strchr(path, '/'); | |
148 | - | |
149 | - if (!q) | |
150 | - q = end; | |
151 | - | |
152 | - p = fdt_get_alias_namelen(fdt, p, q - p); | |
153 | - if (!p) | |
154 | - return -FDT_ERR_BADPATH; | |
155 | - offset = fdt_path_offset(fdt, p); | |
156 | - | |
157 | - p = q; | |
158 | - } | |
159 | - | |
160 | - while (*p) { | |
161 | - const char *q; | |
162 | - | |
163 | - while (*p == '/') | |
164 | - p++; | |
165 | - if (! *p) | |
166 | - return offset; | |
167 | - q = strchr(p, '/'); | |
168 | - if (! q) | |
169 | - q = end; | |
170 | - | |
171 | - offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); | |
172 | - if (offset < 0) | |
173 | - return offset; | |
174 | - | |
175 | - p = q; | |
176 | - } | |
177 | - | |
178 | - return offset; | |
179 | -} | |
180 | - | |
181 | -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) | |
182 | -{ | |
183 | - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); | |
184 | - int err; | |
185 | - | |
186 | - if (((err = fdt_check_header(fdt)) != 0) | |
187 | - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) | |
188 | - goto fail; | |
189 | - | |
190 | - if (len) | |
191 | - *len = strlen(nh->name); | |
192 | - | |
193 | - return nh->name; | |
194 | - | |
195 | - fail: | |
196 | - if (len) | |
197 | - *len = err; | |
198 | - return NULL; | |
199 | -} | |
200 | - | |
201 | -const struct fdt_property *fdt_get_property_namelen(const void *fdt, | |
202 | - int nodeoffset, | |
203 | - const char *name, | |
204 | - int namelen, int *lenp) | |
205 | -{ | |
206 | - uint32_t tag; | |
207 | - const struct fdt_property *prop; | |
208 | - int offset, nextoffset; | |
209 | - int err; | |
210 | - | |
211 | - if (((err = fdt_check_header(fdt)) != 0) | |
212 | - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) | |
213 | - goto fail; | |
214 | - | |
215 | - nextoffset = err; | |
216 | - do { | |
217 | - offset = nextoffset; | |
218 | - | |
219 | - tag = fdt_next_tag(fdt, offset, &nextoffset); | |
220 | - switch (tag) { | |
221 | - case FDT_END: | |
222 | - if (nextoffset < 0) | |
223 | - err = nextoffset; | |
224 | - else | |
225 | - /* FDT_END tag with unclosed nodes */ | |
226 | - err = -FDT_ERR_BADSTRUCTURE; | |
227 | - goto fail; | |
228 | - | |
229 | - case FDT_PROP: | |
230 | - prop = _fdt_offset_ptr(fdt, offset); | |
231 | - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), | |
232 | - name, namelen)) { | |
233 | - /* Found it! */ | |
234 | - if (lenp) | |
235 | - *lenp = fdt32_to_cpu(prop->len); | |
236 | - | |
237 | - return prop; | |
238 | - } | |
239 | - break; | |
240 | - } | |
241 | - } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); | |
242 | - | |
243 | - err = -FDT_ERR_NOTFOUND; | |
244 | - fail: | |
245 | - if (lenp) | |
246 | - *lenp = err; | |
247 | - return NULL; | |
248 | -} | |
249 | - | |
250 | -const struct fdt_property *fdt_get_property(const void *fdt, | |
251 | - int nodeoffset, | |
252 | - const char *name, int *lenp) | |
253 | -{ | |
254 | - return fdt_get_property_namelen(fdt, nodeoffset, name, | |
255 | - strlen(name), lenp); | |
256 | -} | |
257 | - | |
258 | -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | |
259 | - const char *name, int namelen, int *lenp) | |
260 | -{ | |
261 | - const struct fdt_property *prop; | |
262 | - | |
263 | - prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); | |
264 | - if (! prop) | |
265 | - return NULL; | |
266 | - | |
267 | - return prop->data; | |
268 | -} | |
269 | - | |
270 | -const void *fdt_getprop(const void *fdt, int nodeoffset, | |
271 | - const char *name, int *lenp) | |
272 | -{ | |
273 | - return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); | |
274 | -} | |
275 | - | |
276 | -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) | |
277 | -{ | |
278 | - const uint32_t *php; | |
279 | - int len; | |
280 | - | |
281 | - php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); | |
282 | - if (!php || (len != sizeof(*php))) | |
283 | - return 0; | |
284 | - | |
285 | - return fdt32_to_cpu(*php); | |
286 | -} | |
287 | - | |
288 | -const char *fdt_get_alias_namelen(const void *fdt, | |
289 | - const char *name, int namelen) | |
290 | -{ | |
291 | - int aliasoffset; | |
292 | - | |
293 | - aliasoffset = fdt_path_offset(fdt, "/aliases"); | |
294 | - if (aliasoffset < 0) | |
295 | - return NULL; | |
296 | - | |
297 | - return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); | |
298 | -} | |
299 | - | |
300 | -const char *fdt_get_alias(const void *fdt, const char *name) | |
301 | -{ | |
302 | - return fdt_get_alias_namelen(fdt, name, strlen(name)); | |
303 | -} | |
304 | - | |
305 | -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |
306 | -{ | |
307 | - int pdepth = 0, p = 0; | |
308 | - int offset, depth, namelen; | |
309 | - const char *name; | |
310 | - | |
311 | - FDT_CHECK_HEADER(fdt); | |
312 | - | |
313 | - if (buflen < 2) | |
314 | - return -FDT_ERR_NOSPACE; | |
315 | - | |
316 | - for (offset = 0, depth = 0; | |
317 | - (offset >= 0) && (offset <= nodeoffset); | |
318 | - offset = fdt_next_node(fdt, offset, &depth)) { | |
319 | - while (pdepth > depth) { | |
320 | - do { | |
321 | - p--; | |
322 | - } while (buf[p-1] != '/'); | |
323 | - pdepth--; | |
324 | - } | |
325 | - | |
326 | - if (pdepth >= depth) { | |
327 | - name = fdt_get_name(fdt, offset, &namelen); | |
328 | - if (!name) | |
329 | - return namelen; | |
330 | - if ((p + namelen + 1) <= buflen) { | |
331 | - memcpy(buf + p, name, namelen); | |
332 | - p += namelen; | |
333 | - buf[p++] = '/'; | |
334 | - pdepth++; | |
335 | - } | |
336 | - } | |
337 | - | |
338 | - if (offset == nodeoffset) { | |
339 | - if (pdepth < (depth + 1)) | |
340 | - return -FDT_ERR_NOSPACE; | |
341 | - | |
342 | - if (p > 1) /* special case so that root path is "/", not "" */ | |
343 | - p--; | |
344 | - buf[p] = '\0'; | |
345 | - return 0; | |
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 | - | |
357 | -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | |
358 | - int supernodedepth, int *nodedepth) | |
359 | -{ | |
360 | - int offset, depth; | |
361 | - int supernodeoffset = -FDT_ERR_INTERNAL; | |
362 | - | |
363 | - FDT_CHECK_HEADER(fdt); | |
364 | - | |
365 | - if (supernodedepth < 0) | |
366 | - return -FDT_ERR_NOTFOUND; | |
367 | - | |
368 | - for (offset = 0, depth = 0; | |
369 | - (offset >= 0) && (offset <= nodeoffset); | |
370 | - offset = fdt_next_node(fdt, offset, &depth)) { | |
371 | - if (depth == supernodedepth) | |
372 | - supernodeoffset = offset; | |
373 | - | |
374 | - if (offset == nodeoffset) { | |
375 | - if (nodedepth) | |
376 | - *nodedepth = depth; | |
377 | - | |
378 | - if (supernodedepth > depth) | |
379 | - return -FDT_ERR_NOTFOUND; | |
380 | - else | |
381 | - return supernodeoffset; | |
382 | - } | |
383 | - } | |
384 | - | |
385 | - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | |
386 | - return -FDT_ERR_BADOFFSET; | |
387 | - else if (offset == -FDT_ERR_BADOFFSET) | |
388 | - return -FDT_ERR_BADSTRUCTURE; | |
389 | - | |
390 | - return offset; /* error from fdt_next_node() */ | |
391 | -} | |
392 | - | |
393 | -int fdt_node_depth(const void *fdt, int nodeoffset) | |
394 | -{ | |
395 | - int nodedepth; | |
396 | - int err; | |
397 | - | |
398 | - err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); | |
399 | - if (err) | |
400 | - return (err < 0) ? err : -FDT_ERR_INTERNAL; | |
401 | - return nodedepth; | |
402 | -} | |
403 | - | |
404 | -int fdt_parent_offset(const void *fdt, int nodeoffset) | |
405 | -{ | |
406 | - int nodedepth = fdt_node_depth(fdt, nodeoffset); | |
407 | - | |
408 | - if (nodedepth < 0) | |
409 | - return nodedepth; | |
410 | - return fdt_supernode_atdepth_offset(fdt, nodeoffset, | |
411 | - nodedepth - 1, NULL); | |
412 | -} | |
413 | - | |
414 | -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, | |
415 | - const char *propname, | |
416 | - const void *propval, int proplen) | |
417 | -{ | |
418 | - int offset; | |
419 | - const void *val; | |
420 | - int len; | |
421 | - | |
422 | - FDT_CHECK_HEADER(fdt); | |
423 | - | |
424 | - /* FIXME: The algorithm here is pretty horrible: we scan each | |
425 | - * property of a node in fdt_getprop(), then if that didn't | |
426 | - * find what we want, we scan over them again making our way | |
427 | - * to the next node. Still it's the easiest to implement | |
428 | - * approach; performance can come later. */ | |
429 | - for (offset = fdt_next_node(fdt, startoffset, NULL); | |
430 | - offset >= 0; | |
431 | - offset = fdt_next_node(fdt, offset, NULL)) { | |
432 | - val = fdt_getprop(fdt, offset, propname, &len); | |
433 | - if (val && (len == proplen) | |
434 | - && (memcmp(val, propval, len) == 0)) | |
435 | - return offset; | |
436 | - } | |
437 | - | |
438 | - return offset; /* error from fdt_next_node() */ | |
439 | -} | |
440 | - | |
441 | -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) | |
442 | -{ | |
443 | - if ((phandle == 0) || (phandle == -1)) | |
444 | - return -FDT_ERR_BADPHANDLE; | |
445 | - phandle = cpu_to_fdt32(phandle); | |
446 | - return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", | |
447 | - &phandle, sizeof(phandle)); | |
448 | -} | |
449 | - | |
450 | -static int _fdt_stringlist_contains(const char *strlist, int listlen, | |
451 | - const char *str) | |
452 | -{ | |
453 | - int len = strlen(str); | |
454 | - const char *p; | |
455 | - | |
456 | - while (listlen >= len) { | |
457 | - if (memcmp(str, strlist, len+1) == 0) | |
458 | - return 1; | |
459 | - p = memchr(strlist, '\0', listlen); | |
460 | - if (!p) | |
461 | - return 0; /* malformed strlist.. */ | |
462 | - listlen -= (p-strlist) + 1; | |
463 | - strlist = p + 1; | |
464 | - } | |
465 | - return 0; | |
466 | -} | |
467 | - | |
468 | -int fdt_node_check_compatible(const void *fdt, int nodeoffset, | |
469 | - const char *compatible) | |
470 | -{ | |
471 | - const void *prop; | |
472 | - int len; | |
473 | - | |
474 | - prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); | |
475 | - if (!prop) | |
476 | - return len; | |
477 | - if (_fdt_stringlist_contains(prop, len, compatible)) | |
478 | - return 0; | |
479 | - else | |
480 | - return 1; | |
481 | -} | |
482 | - | |
483 | -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | |
484 | - const char *compatible) | |
485 | -{ | |
486 | - int offset, err; | |
487 | - | |
488 | - FDT_CHECK_HEADER(fdt); | |
489 | - | |
490 | - /* FIXME: The algorithm here is pretty horrible: we scan each | |
491 | - * property of a node in fdt_node_check_compatible(), then if | |
492 | - * that didn't find what we want, we scan over them again | |
493 | - * making our way to the next node. Still it's the easiest to | |
494 | - * implement approach; performance can come later. */ | |
495 | - for (offset = fdt_next_node(fdt, startoffset, NULL); | |
496 | - offset >= 0; | |
497 | - offset = fdt_next_node(fdt, offset, NULL)) { | |
498 | - err = fdt_node_check_compatible(fdt, offset, compatible); | |
499 | - if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) | |
500 | - return err; | |
501 | - else if (err == 0) | |
502 | - return offset; | |
503 | - } | |
504 | - | |
505 | - return offset; /* error from fdt_next_node() */ | |
506 | -} |
libfdt/fdt_rw.c
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 | -#ifndef USE_HOSTCC | |
54 | -#include <fdt.h> | |
55 | -#include <libfdt.h> | |
56 | -#else | |
57 | -#include "fdt_host.h" | |
58 | -#endif | |
59 | - | |
60 | -#include "libfdt_internal.h" | |
61 | - | |
62 | -static int _fdt_blocks_misordered(const void *fdt, | |
63 | - int mem_rsv_size, int struct_size) | |
64 | -{ | |
65 | - return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) | |
66 | - || (fdt_off_dt_struct(fdt) < | |
67 | - (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) | |
68 | - || (fdt_off_dt_strings(fdt) < | |
69 | - (fdt_off_dt_struct(fdt) + struct_size)) | |
70 | - || (fdt_totalsize(fdt) < | |
71 | - (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); | |
72 | -} | |
73 | - | |
74 | -static int _fdt_rw_check_header(void *fdt) | |
75 | -{ | |
76 | - FDT_CHECK_HEADER(fdt); | |
77 | - | |
78 | - if (fdt_version(fdt) < 17) | |
79 | - return -FDT_ERR_BADVERSION; | |
80 | - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), | |
81 | - fdt_size_dt_struct(fdt))) | |
82 | - return -FDT_ERR_BADLAYOUT; | |
83 | - if (fdt_version(fdt) > 17) | |
84 | - fdt_set_version(fdt, 17); | |
85 | - | |
86 | - return 0; | |
87 | -} | |
88 | - | |
89 | -#define FDT_RW_CHECK_HEADER(fdt) \ | |
90 | - { \ | |
91 | - int err; \ | |
92 | - if ((err = _fdt_rw_check_header(fdt)) != 0) \ | |
93 | - return err; \ | |
94 | - } | |
95 | - | |
96 | -static inline int _fdt_data_size(void *fdt) | |
97 | -{ | |
98 | - return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | |
99 | -} | |
100 | - | |
101 | -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) | |
102 | -{ | |
103 | - char *p = splicepoint; | |
104 | - char *end = (char *)fdt + _fdt_data_size(fdt); | |
105 | - | |
106 | - if (((p + oldlen) < p) || ((p + oldlen) > end)) | |
107 | - return -FDT_ERR_BADOFFSET; | |
108 | - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) | |
109 | - return -FDT_ERR_NOSPACE; | |
110 | - memmove(p + newlen, p + oldlen, end - p - oldlen); | |
111 | - return 0; | |
112 | -} | |
113 | - | |
114 | -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, | |
115 | - int oldn, int newn) | |
116 | -{ | |
117 | - int delta = (newn - oldn) * sizeof(*p); | |
118 | - int err; | |
119 | - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); | |
120 | - if (err) | |
121 | - return err; | |
122 | - fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); | |
123 | - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); | |
124 | - return 0; | |
125 | -} | |
126 | - | |
127 | -static int _fdt_splice_struct(void *fdt, void *p, | |
128 | - int oldlen, int newlen) | |
129 | -{ | |
130 | - int delta = newlen - oldlen; | |
131 | - int err; | |
132 | - | |
133 | - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) | |
134 | - return err; | |
135 | - | |
136 | - fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); | |
137 | - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); | |
138 | - return 0; | |
139 | -} | |
140 | - | |
141 | -static int _fdt_splice_string(void *fdt, int newlen) | |
142 | -{ | |
143 | - void *p = (char *)fdt | |
144 | - + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); | |
145 | - int err; | |
146 | - | |
147 | - if ((err = _fdt_splice(fdt, p, 0, newlen))) | |
148 | - return err; | |
149 | - | |
150 | - fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); | |
151 | - return 0; | |
152 | -} | |
153 | - | |
154 | -static int _fdt_find_add_string(void *fdt, const char *s) | |
155 | -{ | |
156 | - char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); | |
157 | - const char *p; | |
158 | - char *new; | |
159 | - int len = strlen(s) + 1; | |
160 | - int err; | |
161 | - | |
162 | - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); | |
163 | - if (p) | |
164 | - /* found it */ | |
165 | - return (p - strtab); | |
166 | - | |
167 | - new = strtab + fdt_size_dt_strings(fdt); | |
168 | - err = _fdt_splice_string(fdt, len); | |
169 | - if (err) | |
170 | - return err; | |
171 | - | |
172 | - memcpy(new, s, len); | |
173 | - return (new - strtab); | |
174 | -} | |
175 | - | |
176 | -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) | |
177 | -{ | |
178 | - struct fdt_reserve_entry *re; | |
179 | - int err; | |
180 | - | |
181 | - FDT_RW_CHECK_HEADER(fdt); | |
182 | - | |
183 | - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); | |
184 | - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); | |
185 | - if (err) | |
186 | - return err; | |
187 | - | |
188 | - re->address = cpu_to_fdt64(address); | |
189 | - re->size = cpu_to_fdt64(size); | |
190 | - return 0; | |
191 | -} | |
192 | - | |
193 | -int fdt_del_mem_rsv(void *fdt, int n) | |
194 | -{ | |
195 | - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); | |
196 | - int err; | |
197 | - | |
198 | - FDT_RW_CHECK_HEADER(fdt); | |
199 | - | |
200 | - if (n >= fdt_num_mem_rsv(fdt)) | |
201 | - return -FDT_ERR_NOTFOUND; | |
202 | - | |
203 | - err = _fdt_splice_mem_rsv(fdt, re, 1, 0); | |
204 | - if (err) | |
205 | - return err; | |
206 | - return 0; | |
207 | -} | |
208 | - | |
209 | -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, | |
210 | - int len, struct fdt_property **prop) | |
211 | -{ | |
212 | - int oldlen; | |
213 | - int err; | |
214 | - | |
215 | - *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); | |
216 | - if (! (*prop)) | |
217 | - return oldlen; | |
218 | - | |
219 | - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), | |
220 | - FDT_TAGALIGN(len)))) | |
221 | - return err; | |
222 | - | |
223 | - (*prop)->len = cpu_to_fdt32(len); | |
224 | - return 0; | |
225 | -} | |
226 | - | |
227 | -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, | |
228 | - int len, struct fdt_property **prop) | |
229 | -{ | |
230 | - int proplen; | |
231 | - int nextoffset; | |
232 | - int namestroff; | |
233 | - int err; | |
234 | - | |
235 | - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) | |
236 | - return nextoffset; | |
237 | - | |
238 | - namestroff = _fdt_find_add_string(fdt, name); | |
239 | - if (namestroff < 0) | |
240 | - return namestroff; | |
241 | - | |
242 | - *prop = _fdt_offset_ptr_w(fdt, nextoffset); | |
243 | - proplen = sizeof(**prop) + FDT_TAGALIGN(len); | |
244 | - | |
245 | - err = _fdt_splice_struct(fdt, *prop, 0, proplen); | |
246 | - if (err) | |
247 | - return err; | |
248 | - | |
249 | - (*prop)->tag = cpu_to_fdt32(FDT_PROP); | |
250 | - (*prop)->nameoff = cpu_to_fdt32(namestroff); | |
251 | - (*prop)->len = cpu_to_fdt32(len); | |
252 | - return 0; | |
253 | -} | |
254 | - | |
255 | -int fdt_set_name(void *fdt, int nodeoffset, const char *name) | |
256 | -{ | |
257 | - char *namep; | |
258 | - int oldlen, newlen; | |
259 | - int err; | |
260 | - | |
261 | - FDT_RW_CHECK_HEADER(fdt); | |
262 | - | |
263 | - namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); | |
264 | - if (!namep) | |
265 | - return oldlen; | |
266 | - | |
267 | - newlen = strlen(name); | |
268 | - | |
269 | - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), | |
270 | - FDT_TAGALIGN(newlen+1)); | |
271 | - if (err) | |
272 | - return err; | |
273 | - | |
274 | - memcpy(namep, name, newlen+1); | |
275 | - return 0; | |
276 | -} | |
277 | - | |
278 | -int fdt_setprop(void *fdt, int nodeoffset, const char *name, | |
279 | - const void *val, int len) | |
280 | -{ | |
281 | - struct fdt_property *prop; | |
282 | - int err; | |
283 | - | |
284 | - FDT_RW_CHECK_HEADER(fdt); | |
285 | - | |
286 | - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); | |
287 | - if (err == -FDT_ERR_NOTFOUND) | |
288 | - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); | |
289 | - if (err) | |
290 | - return err; | |
291 | - | |
292 | - memcpy(prop->data, val, len); | |
293 | - return 0; | |
294 | -} | |
295 | - | |
296 | -int fdt_delprop(void *fdt, int nodeoffset, const char *name) | |
297 | -{ | |
298 | - struct fdt_property *prop; | |
299 | - int len, proplen; | |
300 | - | |
301 | - FDT_RW_CHECK_HEADER(fdt); | |
302 | - | |
303 | - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | |
304 | - if (! prop) | |
305 | - return len; | |
306 | - | |
307 | - proplen = sizeof(*prop) + FDT_TAGALIGN(len); | |
308 | - return _fdt_splice_struct(fdt, prop, proplen, 0); | |
309 | -} | |
310 | - | |
311 | -int fdt_add_subnode_namelen(void *fdt, int parentoffset, | |
312 | - const char *name, int namelen) | |
313 | -{ | |
314 | - struct fdt_node_header *nh; | |
315 | - int offset, nextoffset; | |
316 | - int nodelen; | |
317 | - int err; | |
318 | - uint32_t tag; | |
319 | - uint32_t *endtag; | |
320 | - | |
321 | - FDT_RW_CHECK_HEADER(fdt); | |
322 | - | |
323 | - offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); | |
324 | - if (offset >= 0) | |
325 | - return -FDT_ERR_EXISTS; | |
326 | - else if (offset != -FDT_ERR_NOTFOUND) | |
327 | - return offset; | |
328 | - | |
329 | - /* Try to place the new node after the parent's properties */ | |
330 | - fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ | |
331 | - do { | |
332 | - offset = nextoffset; | |
333 | - tag = fdt_next_tag(fdt, offset, &nextoffset); | |
334 | - } while ((tag == FDT_PROP) || (tag == FDT_NOP)); | |
335 | - | |
336 | - nh = _fdt_offset_ptr_w(fdt, offset); | |
337 | - nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; | |
338 | - | |
339 | - err = _fdt_splice_struct(fdt, nh, 0, nodelen); | |
340 | - if (err) | |
341 | - return err; | |
342 | - | |
343 | - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); | |
344 | - memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); | |
345 | - memcpy(nh->name, name, namelen); | |
346 | - endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE); | |
347 | - *endtag = cpu_to_fdt32(FDT_END_NODE); | |
348 | - | |
349 | - return offset; | |
350 | -} | |
351 | - | |
352 | -int fdt_add_subnode(void *fdt, int parentoffset, const char *name) | |
353 | -{ | |
354 | - return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); | |
355 | -} | |
356 | - | |
357 | -int fdt_del_node(void *fdt, int nodeoffset) | |
358 | -{ | |
359 | - int endoffset; | |
360 | - | |
361 | - FDT_RW_CHECK_HEADER(fdt); | |
362 | - | |
363 | - endoffset = _fdt_node_end_offset(fdt, nodeoffset); | |
364 | - if (endoffset < 0) | |
365 | - return endoffset; | |
366 | - | |
367 | - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), | |
368 | - endoffset - nodeoffset, 0); | |
369 | -} | |
370 | - | |
371 | -static void _fdt_packblocks(const char *old, char *new, | |
372 | - int mem_rsv_size, int struct_size) | |
373 | -{ | |
374 | - int mem_rsv_off, struct_off, strings_off; | |
375 | - | |
376 | - mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); | |
377 | - struct_off = mem_rsv_off + mem_rsv_size; | |
378 | - strings_off = struct_off + struct_size; | |
379 | - | |
380 | - memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); | |
381 | - fdt_set_off_mem_rsvmap(new, mem_rsv_off); | |
382 | - | |
383 | - memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); | |
384 | - fdt_set_off_dt_struct(new, struct_off); | |
385 | - fdt_set_size_dt_struct(new, struct_size); | |
386 | - | |
387 | - memmove(new + strings_off, old + fdt_off_dt_strings(old), | |
388 | - fdt_size_dt_strings(old)); | |
389 | - fdt_set_off_dt_strings(new, strings_off); | |
390 | - fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); | |
391 | -} | |
392 | - | |
393 | -int fdt_open_into(const void *fdt, void *buf, int bufsize) | |
394 | -{ | |
395 | - int err; | |
396 | - int mem_rsv_size, struct_size; | |
397 | - int newsize; | |
398 | - const char *fdtstart = fdt; | |
399 | - const char *fdtend = fdtstart + fdt_totalsize(fdt); | |
400 | - char *tmp; | |
401 | - | |
402 | - FDT_CHECK_HEADER(fdt); | |
403 | - | |
404 | - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | |
405 | - * sizeof(struct fdt_reserve_entry); | |
406 | - | |
407 | - if (fdt_version(fdt) >= 17) { | |
408 | - struct_size = fdt_size_dt_struct(fdt); | |
409 | - } else { | |
410 | - struct_size = 0; | |
411 | - while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) | |
412 | - ; | |
413 | - if (struct_size < 0) | |
414 | - return struct_size; | |
415 | - } | |
416 | - | |
417 | - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { | |
418 | - /* no further work necessary */ | |
419 | - err = fdt_move(fdt, buf, bufsize); | |
420 | - if (err) | |
421 | - return err; | |
422 | - fdt_set_version(buf, 17); | |
423 | - fdt_set_size_dt_struct(buf, struct_size); | |
424 | - fdt_set_totalsize(buf, bufsize); | |
425 | - return 0; | |
426 | - } | |
427 | - | |
428 | - /* Need to reorder */ | |
429 | - newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size | |
430 | - + struct_size + fdt_size_dt_strings(fdt); | |
431 | - | |
432 | - if (bufsize < newsize) | |
433 | - return -FDT_ERR_NOSPACE; | |
434 | - | |
435 | - /* First attempt to build converted tree at beginning of buffer */ | |
436 | - tmp = buf; | |
437 | - /* But if that overlaps with the old tree... */ | |
438 | - if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { | |
439 | - /* Try right after the old tree instead */ | |
440 | - tmp = (char *)(uintptr_t)fdtend; | |
441 | - if ((tmp + newsize) > ((char *)buf + bufsize)) | |
442 | - return -FDT_ERR_NOSPACE; | |
443 | - } | |
444 | - | |
445 | - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); | |
446 | - memmove(buf, tmp, newsize); | |
447 | - | |
448 | - fdt_set_magic(buf, FDT_MAGIC); | |
449 | - fdt_set_totalsize(buf, bufsize); | |
450 | - fdt_set_version(buf, 17); | |
451 | - fdt_set_last_comp_version(buf, 16); | |
452 | - fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); | |
453 | - | |
454 | - return 0; | |
455 | -} | |
456 | - | |
457 | -int fdt_pack(void *fdt) | |
458 | -{ | |
459 | - int mem_rsv_size; | |
460 | - | |
461 | - FDT_RW_CHECK_HEADER(fdt); | |
462 | - | |
463 | - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | |
464 | - * sizeof(struct fdt_reserve_entry); | |
465 | - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); | |
466 | - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); | |
467 | - | |
468 | - return 0; | |
469 | -} |
libfdt/fdt_strerror.c
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 | -#ifndef USE_HOSTCC | |
54 | -#include <fdt.h> | |
55 | -#include <libfdt.h> | |
56 | -#else | |
57 | -#include "fdt_host.h" | |
58 | -#endif | |
59 | - | |
60 | -#include "libfdt_internal.h" | |
61 | - | |
62 | -struct fdt_errtabent { | |
63 | - const char *str; | |
64 | -}; | |
65 | - | |
66 | -#define FDT_ERRTABENT(val) \ | |
67 | - [(val)] = { .str = #val, } | |
68 | - | |
69 | -static struct fdt_errtabent fdt_errtable[] = { | |
70 | - FDT_ERRTABENT(FDT_ERR_NOTFOUND), | |
71 | - FDT_ERRTABENT(FDT_ERR_EXISTS), | |
72 | - FDT_ERRTABENT(FDT_ERR_NOSPACE), | |
73 | - | |
74 | - FDT_ERRTABENT(FDT_ERR_BADOFFSET), | |
75 | - FDT_ERRTABENT(FDT_ERR_BADPATH), | |
76 | - FDT_ERRTABENT(FDT_ERR_BADSTATE), | |
77 | - | |
78 | - FDT_ERRTABENT(FDT_ERR_TRUNCATED), | |
79 | - FDT_ERRTABENT(FDT_ERR_BADMAGIC), | |
80 | - FDT_ERRTABENT(FDT_ERR_BADVERSION), | |
81 | - FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), | |
82 | - FDT_ERRTABENT(FDT_ERR_BADLAYOUT), | |
83 | -}; | |
84 | -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) | |
85 | - | |
86 | -const char *fdt_strerror(int errval) | |
87 | -{ | |
88 | - if (errval > 0) | |
89 | - return "<valid offset/length>"; | |
90 | - else if (errval == 0) | |
91 | - return "<no error>"; | |
92 | - else if (errval > -FDT_ERRTABSIZE) { | |
93 | - const char *s = fdt_errtable[-errval].str; | |
94 | - | |
95 | - if (s) | |
96 | - return s; | |
97 | - } | |
98 | - | |
99 | - return "<unknown error>"; | |
100 | -} |
libfdt/fdt_sw.c
1 | -/* | |
2 | - * libfdt - Flat Device Tree manipulation | |
3 | - * Copyright (C) 2006 David Gibson, IBM Corporation. | |
4 | - * | |
5 | - * libfdt is dual licensed: you can use it either under the terms of | |
6 | - * the GPL, or the BSD license, at your option. | |
7 | - * | |
8 | - * a) This library is free software; you can redistribute it and/or | |
9 | - * modify it under the terms of the GNU General Public License as | |
10 | - * published by the Free Software Foundation; either version 2 of the | |
11 | - * License, or (at your option) any later version. | |
12 | - * | |
13 | - * This library is distributed in the hope that it will be useful, | |
14 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | - * GNU General Public License for more details. | |
17 | - * | |
18 | - * You should have received a copy of the GNU General Public | |
19 | - * License along with this library; if not, write to the Free | |
20 | - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
21 | - * MA 02110-1301 USA | |
22 | - * | |
23 | - * Alternatively, | |
24 | - * | |
25 | - * b) Redistribution and use in source and binary forms, with or | |
26 | - * without modification, are permitted provided that the following | |
27 | - * conditions are met: | |
28 | - * | |
29 | - * 1. Redistributions of source code must retain the above | |
30 | - * copyright notice, this list of conditions and the following | |
31 | - * disclaimer. | |
32 | - * 2. Redistributions in binary form must reproduce the above | |
33 | - * copyright notice, this list of conditions and the following | |
34 | - * disclaimer in the documentation and/or other materials | |
35 | - * provided with the distribution. | |
36 | - * | |
37 | - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |
38 | - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
39 | - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
40 | - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
41 | - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
42 | - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
43 | - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
44 | - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
45 | - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
46 | - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
47 | - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
48 | - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
49 | - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
50 | - */ | |
51 | -#include "libfdt_env.h" | |
52 | - | |
53 | -#include <fdt.h> | |
54 | -#include <libfdt.h> | |
55 | - | |
56 | -#include "libfdt_internal.h" | |
57 | - | |
58 | -static 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 | - | |
73 | -static void *_fdt_grab_space(void *fdt, size_t 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); | |
86 | -} | |
87 | - | |
88 | -int 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 | - | |
110 | -int 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 | - | |
133 | -int fdt_finish_reservemap(void *fdt) | |
134 | -{ | |
135 | - return fdt_add_reservemap_entry(fdt, 0, 0); | |
136 | -} | |
137 | - | |
138 | -int 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 | - | |
154 | -int 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 | - | |
168 | -static 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 | - | |
191 | -int 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 | - | |
213 | -int 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); | |
241 | - int nameoff; | |
242 | - | |
243 | - nameoff = fdt32_to_cpu(prop->nameoff); | |
244 | - nameoff += fdt_size_dt_strings(fdt); | |
245 | - prop->nameoff = cpu_to_fdt32(nameoff); | |
246 | - } | |
247 | - offset = nextoffset; | |
248 | - } | |
249 | - if (nextoffset < 0) | |
250 | - return nextoffset; | |
251 | - | |
252 | - /* Finally, adjust the header */ | |
253 | - fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); | |
254 | - fdt_set_magic(fdt, FDT_MAGIC); | |
255 | - return 0; | |
256 | -} |
libfdt/fdt_wip.c
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 | -#ifndef USE_HOSTCC | |
54 | -#include <fdt.h> | |
55 | -#include <libfdt.h> | |
56 | -#else | |
57 | -#include "fdt_host.h" | |
58 | -#endif | |
59 | - | |
60 | -#include "libfdt_internal.h" | |
61 | - | |
62 | -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, | |
63 | - const void *val, int len) | |
64 | -{ | |
65 | - void *propval; | |
66 | - int proplen; | |
67 | - | |
68 | - propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); | |
69 | - if (! propval) | |
70 | - return proplen; | |
71 | - | |
72 | - if (proplen != len) | |
73 | - return -FDT_ERR_NOSPACE; | |
74 | - | |
75 | - memcpy(propval, val, len); | |
76 | - return 0; | |
77 | -} | |
78 | - | |
79 | -static void _fdt_nop_region(void *start, int len) | |
80 | -{ | |
81 | - uint32_t *p; | |
82 | - | |
83 | - for (p = start; (char *)p < ((char *)start + len); p++) | |
84 | - *p = cpu_to_fdt32(FDT_NOP); | |
85 | -} | |
86 | - | |
87 | -int fdt_nop_property(void *fdt, int nodeoffset, const char *name) | |
88 | -{ | |
89 | - struct fdt_property *prop; | |
90 | - int len; | |
91 | - | |
92 | - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | |
93 | - if (! prop) | |
94 | - return len; | |
95 | - | |
96 | - _fdt_nop_region(prop, len + sizeof(*prop)); | |
97 | - | |
98 | - return 0; | |
99 | -} | |
100 | - | |
101 | -int _fdt_node_end_offset(void *fdt, int offset) | |
102 | -{ | |
103 | - int depth = 0; | |
104 | - | |
105 | - while ((offset >= 0) && (depth >= 0)) | |
106 | - offset = fdt_next_node(fdt, offset, &depth); | |
107 | - | |
108 | - return offset; | |
109 | -} | |
110 | - | |
111 | -int fdt_nop_node(void *fdt, int nodeoffset) | |
112 | -{ | |
113 | - int endoffset; | |
114 | - | |
115 | - endoffset = _fdt_node_end_offset(fdt, nodeoffset); | |
116 | - if (endoffset < 0) | |
117 | - return endoffset; | |
118 | - | |
119 | - _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), | |
120 | - endoffset - nodeoffset); | |
121 | - return 0; | |
122 | -} |
libfdt/libfdt_internal.h
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 | - | |
65 | -int _fdt_check_node_offset(const void *fdt, int offset); | |
66 | -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); | |
67 | -int _fdt_node_end_offset(void *fdt, int nodeoffset); | |
68 | - | |
69 | -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) | |
70 | -{ | |
71 | - return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; | |
72 | -} | |
73 | - | |
74 | -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) | |
75 | -{ | |
76 | - return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); | |
77 | -} | |
78 | - | |
79 | -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) | |
80 | -{ | |
81 | - const struct fdt_reserve_entry *rsv_table = | |
82 | - (const struct fdt_reserve_entry *) | |
83 | - ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); | |
84 | - | |
85 | - return rsv_table + n; | |
86 | -} | |
87 | -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) | |
88 | -{ | |
89 | - return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); | |
90 | -} | |
91 | - | |
92 | -#define FDT_SW_MAGIC (~FDT_MAGIC) | |
93 | - | |
94 | -#endif /* _LIBFDT_INTERNAL_H */ |
tools/Makefile
... | ... | @@ -122,7 +122,7 @@ |
122 | 122 | # now $(obj) is defined |
123 | 123 | HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c)) |
124 | 124 | HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c)) |
125 | -HOSTSRCS += $(addprefix $(SRCTREE)/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) | |
125 | +HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) | |
126 | 126 | BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y))) |
127 | 127 | LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y)) |
128 | 128 | |
... | ... | @@ -136,7 +136,7 @@ |
136 | 136 | HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \ |
137 | 137 | -idirafter $(OBJTREE)/include2 \ |
138 | 138 | -idirafter $(OBJTREE)/include \ |
139 | - -I $(SRCTREE)/libfdt \ | |
139 | + -I $(SRCTREE)/lib/libfdt \ | |
140 | 140 | -I $(SRCTREE)/tools \ |
141 | 141 | -DTEXT_BASE=$(TEXT_BASE) -DUSE_HOSTCC \ |
142 | 142 | -D__KERNEL_STRICT_NAMES |
... | ... | @@ -199,7 +199,7 @@ |
199 | 199 | $(obj)%.o: $(SRCTREE)/lib/%.c |
200 | 200 | $(HOSTCC) -g $(HOSTCFLAGS) -c -o $@ $< |
201 | 201 | |
202 | -$(obj)%.o: $(SRCTREE)/libfdt/%.c | |
202 | +$(obj)%.o: $(SRCTREE)/lib/libfdt/%.c | |
203 | 203 | $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< |
204 | 204 | |
205 | 205 | subdirs: |
tools/imls/Makefile
... | ... | @@ -41,7 +41,7 @@ |
41 | 41 | # now $(obj) is defined |
42 | 42 | SRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c)) |
43 | 43 | SRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c)) |
44 | -SRCS += $(addprefix $(SRCTREE)/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) | |
44 | +SRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) | |
45 | 45 | BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y))) |
46 | 46 | LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y)) |
47 | 47 | |
... | ... | @@ -52,7 +52,7 @@ |
52 | 52 | HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \ |
53 | 53 | -idirafter $(OBJTREE)/include2 \ |
54 | 54 | -idirafter $(OBJTREE)/include \ |
55 | - -I $(SRCTREE)/libfdt \ | |
55 | + -I $(SRCTREE)/lib/libfdt \ | |
56 | 56 | -I $(SRCTREE)/tools \ |
57 | 57 | -DUSE_HOSTCC -D__KERNEL_STRICT_NAMES |
58 | 58 | |
... | ... | @@ -81,7 +81,7 @@ |
81 | 81 | $(obj)%.o: $(SRCTREE)/lib/%.c |
82 | 82 | $(CC) -g $(HOSTCFLAGS) -c -o $@ $< |
83 | 83 | |
84 | -$(obj)%.o: $(SRCTREE)/libfdt/%.c | |
84 | +$(obj)%.o: $(SRCTREE)/lib/libfdt/%.c | |
85 | 85 | $(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< |
86 | 86 | |
87 | 87 | clean: |