Annotation of elwix/tools/uboot_mkimage/lib/libfdt/fdt.c, revision 1.1.1.1
1.1 misho 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>