1*53ee8cc1Swenshuai.xi /*
2*53ee8cc1Swenshuai.xi * libfdt - Flat Device Tree manipulation
3*53ee8cc1Swenshuai.xi * Copyright (C) 2006 David Gibson, IBM Corporation.
4*53ee8cc1Swenshuai.xi *
5*53ee8cc1Swenshuai.xi * libfdt is dual licensed: you can use it either under the terms of
6*53ee8cc1Swenshuai.xi * the GPL, or the BSD license, at your option.
7*53ee8cc1Swenshuai.xi *
8*53ee8cc1Swenshuai.xi * a) This library is free software; you can redistribute it and/or
9*53ee8cc1Swenshuai.xi * modify it under the terms of the GNU General Public License as
10*53ee8cc1Swenshuai.xi * published by the Free Software Foundation; either version 2 of the
11*53ee8cc1Swenshuai.xi * License, or (at your option) any later version.
12*53ee8cc1Swenshuai.xi *
13*53ee8cc1Swenshuai.xi * This library is distributed in the hope that it will be useful,
14*53ee8cc1Swenshuai.xi * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*53ee8cc1Swenshuai.xi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*53ee8cc1Swenshuai.xi * GNU General Public License for more details.
17*53ee8cc1Swenshuai.xi *
18*53ee8cc1Swenshuai.xi * You should have received a copy of the GNU General Public
19*53ee8cc1Swenshuai.xi * License along with this library; if not, write to the Free
20*53ee8cc1Swenshuai.xi * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21*53ee8cc1Swenshuai.xi * MA 02110-1301 USA
22*53ee8cc1Swenshuai.xi *
23*53ee8cc1Swenshuai.xi * Alternatively,
24*53ee8cc1Swenshuai.xi *
25*53ee8cc1Swenshuai.xi * b) Redistribution and use in source and binary forms, with or
26*53ee8cc1Swenshuai.xi * without modification, are permitted provided that the following
27*53ee8cc1Swenshuai.xi * conditions are met:
28*53ee8cc1Swenshuai.xi *
29*53ee8cc1Swenshuai.xi * 1. Redistributions of source code must retain the above
30*53ee8cc1Swenshuai.xi * copyright notice, this list of conditions and the following
31*53ee8cc1Swenshuai.xi * disclaimer.
32*53ee8cc1Swenshuai.xi * 2. Redistributions in binary form must reproduce the above
33*53ee8cc1Swenshuai.xi * copyright notice, this list of conditions and the following
34*53ee8cc1Swenshuai.xi * disclaimer in the documentation and/or other materials
35*53ee8cc1Swenshuai.xi * provided with the distribution.
36*53ee8cc1Swenshuai.xi *
37*53ee8cc1Swenshuai.xi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
38*53ee8cc1Swenshuai.xi * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39*53ee8cc1Swenshuai.xi * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40*53ee8cc1Swenshuai.xi * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41*53ee8cc1Swenshuai.xi * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
42*53ee8cc1Swenshuai.xi * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43*53ee8cc1Swenshuai.xi * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44*53ee8cc1Swenshuai.xi * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45*53ee8cc1Swenshuai.xi * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46*53ee8cc1Swenshuai.xi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47*53ee8cc1Swenshuai.xi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48*53ee8cc1Swenshuai.xi * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49*53ee8cc1Swenshuai.xi * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50*53ee8cc1Swenshuai.xi */
51*53ee8cc1Swenshuai.xi #include "libfdt_env.h"
52*53ee8cc1Swenshuai.xi
53*53ee8cc1Swenshuai.xi #include <fdt.h>
54*53ee8cc1Swenshuai.xi #include <libfdt.h>
55*53ee8cc1Swenshuai.xi
56*53ee8cc1Swenshuai.xi #include "libfdt_internal.h"
57*53ee8cc1Swenshuai.xi
fdt_check_header(const void * fdt)58*53ee8cc1Swenshuai.xi int fdt_check_header(const void *fdt)
59*53ee8cc1Swenshuai.xi {
60*53ee8cc1Swenshuai.xi if (fdt_magic(fdt) == FDT_MAGIC) {
61*53ee8cc1Swenshuai.xi /* Complete tree */
62*53ee8cc1Swenshuai.xi if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
63*53ee8cc1Swenshuai.xi return -FDT_ERR_BADVERSION;
64*53ee8cc1Swenshuai.xi if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
65*53ee8cc1Swenshuai.xi return -FDT_ERR_BADVERSION;
66*53ee8cc1Swenshuai.xi } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
67*53ee8cc1Swenshuai.xi /* Unfinished sequential-write blob */
68*53ee8cc1Swenshuai.xi if (fdt_size_dt_struct(fdt) == 0)
69*53ee8cc1Swenshuai.xi return -FDT_ERR_BADSTATE;
70*53ee8cc1Swenshuai.xi } else {
71*53ee8cc1Swenshuai.xi return -FDT_ERR_BADMAGIC;
72*53ee8cc1Swenshuai.xi }
73*53ee8cc1Swenshuai.xi
74*53ee8cc1Swenshuai.xi return 0;
75*53ee8cc1Swenshuai.xi }
76*53ee8cc1Swenshuai.xi
fdt_offset_ptr(const void * fdt,int offset,int len)77*53ee8cc1Swenshuai.xi const void *fdt_offset_ptr(const void *fdt, int offset, int len)
78*53ee8cc1Swenshuai.xi {
79*53ee8cc1Swenshuai.xi const char *p;
80*53ee8cc1Swenshuai.xi
81*53ee8cc1Swenshuai.xi if (fdt_version(fdt) >= 0x11)
82*53ee8cc1Swenshuai.xi if (((offset + len) < offset)
83*53ee8cc1Swenshuai.xi || ((offset + len) > fdt_size_dt_struct(fdt)))
84*53ee8cc1Swenshuai.xi return NULL;
85*53ee8cc1Swenshuai.xi
86*53ee8cc1Swenshuai.xi p = _fdt_offset_ptr(fdt, offset);
87*53ee8cc1Swenshuai.xi
88*53ee8cc1Swenshuai.xi if (p + len < p)
89*53ee8cc1Swenshuai.xi return NULL;
90*53ee8cc1Swenshuai.xi return p;
91*53ee8cc1Swenshuai.xi }
92*53ee8cc1Swenshuai.xi
fdt_next_tag(const void * fdt,int offset,int * nextoffset)93*53ee8cc1Swenshuai.xi uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
94*53ee8cc1Swenshuai.xi {
95*53ee8cc1Swenshuai.xi const uint32_t *tagp, *lenp;
96*53ee8cc1Swenshuai.xi uint32_t tag;
97*53ee8cc1Swenshuai.xi const char *p;
98*53ee8cc1Swenshuai.xi
99*53ee8cc1Swenshuai.xi if (offset % FDT_TAGSIZE)
100*53ee8cc1Swenshuai.xi return -1;
101*53ee8cc1Swenshuai.xi
102*53ee8cc1Swenshuai.xi tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
103*53ee8cc1Swenshuai.xi if (! tagp)
104*53ee8cc1Swenshuai.xi return FDT_END; /* premature end */
105*53ee8cc1Swenshuai.xi tag = fdt32_to_cpu(*tagp);
106*53ee8cc1Swenshuai.xi offset += FDT_TAGSIZE;
107*53ee8cc1Swenshuai.xi
108*53ee8cc1Swenshuai.xi switch (tag) {
109*53ee8cc1Swenshuai.xi case FDT_BEGIN_NODE:
110*53ee8cc1Swenshuai.xi /* skip name */
111*53ee8cc1Swenshuai.xi do {
112*53ee8cc1Swenshuai.xi p = fdt_offset_ptr(fdt, offset++, 1);
113*53ee8cc1Swenshuai.xi } while (p && (*p != '\0'));
114*53ee8cc1Swenshuai.xi if (! p)
115*53ee8cc1Swenshuai.xi return FDT_END;
116*53ee8cc1Swenshuai.xi break;
117*53ee8cc1Swenshuai.xi case FDT_PROP:
118*53ee8cc1Swenshuai.xi lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
119*53ee8cc1Swenshuai.xi if (! lenp)
120*53ee8cc1Swenshuai.xi return FDT_END;
121*53ee8cc1Swenshuai.xi /* skip name offset, length and value */
122*53ee8cc1Swenshuai.xi offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
123*53ee8cc1Swenshuai.xi break;
124*53ee8cc1Swenshuai.xi }
125*53ee8cc1Swenshuai.xi
126*53ee8cc1Swenshuai.xi if (nextoffset)
127*53ee8cc1Swenshuai.xi *nextoffset = FDT_TAGALIGN(offset);
128*53ee8cc1Swenshuai.xi
129*53ee8cc1Swenshuai.xi return tag;
130*53ee8cc1Swenshuai.xi }
131*53ee8cc1Swenshuai.xi
_fdt_check_node_offset(const void * fdt,int offset)132*53ee8cc1Swenshuai.xi int _fdt_check_node_offset(const void *fdt, int offset)
133*53ee8cc1Swenshuai.xi {
134*53ee8cc1Swenshuai.xi if ((offset < 0) || (offset % FDT_TAGSIZE)
135*53ee8cc1Swenshuai.xi || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
136*53ee8cc1Swenshuai.xi return -FDT_ERR_BADOFFSET;
137*53ee8cc1Swenshuai.xi
138*53ee8cc1Swenshuai.xi return offset;
139*53ee8cc1Swenshuai.xi }
140*53ee8cc1Swenshuai.xi
fdt_next_node(const void * fdt,int offset,int * depth)141*53ee8cc1Swenshuai.xi int fdt_next_node(const void *fdt, int offset, int *depth)
142*53ee8cc1Swenshuai.xi {
143*53ee8cc1Swenshuai.xi int nextoffset = 0;
144*53ee8cc1Swenshuai.xi uint32_t tag;
145*53ee8cc1Swenshuai.xi
146*53ee8cc1Swenshuai.xi if (offset >= 0)
147*53ee8cc1Swenshuai.xi if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
148*53ee8cc1Swenshuai.xi return nextoffset;
149*53ee8cc1Swenshuai.xi
150*53ee8cc1Swenshuai.xi do {
151*53ee8cc1Swenshuai.xi offset = nextoffset;
152*53ee8cc1Swenshuai.xi tag = fdt_next_tag(fdt, offset, &nextoffset);
153*53ee8cc1Swenshuai.xi
154*53ee8cc1Swenshuai.xi switch (tag) {
155*53ee8cc1Swenshuai.xi case FDT_PROP:
156*53ee8cc1Swenshuai.xi case FDT_NOP:
157*53ee8cc1Swenshuai.xi break;
158*53ee8cc1Swenshuai.xi
159*53ee8cc1Swenshuai.xi case FDT_BEGIN_NODE:
160*53ee8cc1Swenshuai.xi if (depth)
161*53ee8cc1Swenshuai.xi (*depth)++;
162*53ee8cc1Swenshuai.xi break;
163*53ee8cc1Swenshuai.xi
164*53ee8cc1Swenshuai.xi case FDT_END_NODE:
165*53ee8cc1Swenshuai.xi if (depth)
166*53ee8cc1Swenshuai.xi (*depth)--;
167*53ee8cc1Swenshuai.xi break;
168*53ee8cc1Swenshuai.xi
169*53ee8cc1Swenshuai.xi case FDT_END:
170*53ee8cc1Swenshuai.xi return -FDT_ERR_NOTFOUND;
171*53ee8cc1Swenshuai.xi
172*53ee8cc1Swenshuai.xi default:
173*53ee8cc1Swenshuai.xi return -FDT_ERR_BADSTRUCTURE;
174*53ee8cc1Swenshuai.xi }
175*53ee8cc1Swenshuai.xi } while (tag != FDT_BEGIN_NODE);
176*53ee8cc1Swenshuai.xi
177*53ee8cc1Swenshuai.xi return offset;
178*53ee8cc1Swenshuai.xi }
179*53ee8cc1Swenshuai.xi
_fdt_find_string(const char * strtab,int tabsize,const char * s)180*53ee8cc1Swenshuai.xi const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
181*53ee8cc1Swenshuai.xi {
182*53ee8cc1Swenshuai.xi int len = strlen(s) + 1;
183*53ee8cc1Swenshuai.xi const char *last = strtab + tabsize - len;
184*53ee8cc1Swenshuai.xi const char *p;
185*53ee8cc1Swenshuai.xi
186*53ee8cc1Swenshuai.xi for (p = strtab; p <= last; p++)
187*53ee8cc1Swenshuai.xi if (memcmp(p, s, len) == 0)
188*53ee8cc1Swenshuai.xi return p;
189*53ee8cc1Swenshuai.xi return NULL;
190*53ee8cc1Swenshuai.xi }
191*53ee8cc1Swenshuai.xi
fdt_move(const void * fdt,void * buf,int bufsize)192*53ee8cc1Swenshuai.xi int fdt_move(const void *fdt, void *buf, int bufsize)
193*53ee8cc1Swenshuai.xi {
194*53ee8cc1Swenshuai.xi FDT_CHECK_HEADER(fdt);
195*53ee8cc1Swenshuai.xi
196*53ee8cc1Swenshuai.xi if (fdt_totalsize(fdt) > bufsize)
197*53ee8cc1Swenshuai.xi return -FDT_ERR_NOSPACE;
198*53ee8cc1Swenshuai.xi
199*53ee8cc1Swenshuai.xi memmove(buf, fdt, fdt_totalsize(fdt));
200*53ee8cc1Swenshuai.xi return 0;
201*53ee8cc1Swenshuai.xi }
202