2 * libfdt - Flat Device Tree manipulation
3 * Copyright (C) 2006 David Gibson, IBM Corporation.
5 * Redistribution and use in source and binary forms, with or
6 * without modification, are permitted provided that the following
9 * 1. Redistributions of source code must retain the above
10 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "libfdt_env.h"
35 #include "libfdt_internal.h"
37 int fdt_check_header(const void *fdt
)
39 if (fdt_magic(fdt
) == FDT_MAGIC
) {
41 if (fdt_version(fdt
) < FDT_FIRST_SUPPORTED_VERSION
)
42 return -FDT_ERR_BADVERSION
;
43 if (fdt_last_comp_version(fdt
) > FDT_LAST_SUPPORTED_VERSION
)
44 return -FDT_ERR_BADVERSION
;
45 } else if (fdt_magic(fdt
) == FDT_SW_MAGIC
) {
46 /* Unfinished sequential-write blob */
47 if (fdt_size_dt_struct(fdt
) == 0)
48 return -FDT_ERR_BADSTATE
;
50 return -FDT_ERR_BADMAGIC
;
56 const void *fdt_offset_ptr(const void *fdt
, int offset
, unsigned int len
)
60 if (fdt_version(fdt
) >= 0x11)
61 if (((offset
+ len
) < offset
)
62 || ((offset
+ len
) > fdt_size_dt_struct(fdt
)))
65 p
= _fdt_offset_ptr(fdt
, offset
);
72 uint32_t fdt_next_tag(const void *fdt
, int startoffset
, int *nextoffset
)
74 const fdt32_t
*tagp
, *lenp
;
76 int offset
= startoffset
;
79 *nextoffset
= -FDT_ERR_TRUNCATED
;
80 tagp
= fdt_offset_ptr(fdt
, offset
, FDT_TAGSIZE
);
82 return FDT_END
; /* premature end */
83 tag
= fdt32_to_cpu(*tagp
);
84 offset
+= FDT_TAGSIZE
;
86 *nextoffset
= -FDT_ERR_BADSTRUCTURE
;
91 p
= fdt_offset_ptr(fdt
, offset
++, 1);
92 } while (p
&& (*p
!= '\0'));
94 return FDT_END
; /* premature end */
98 lenp
= fdt_offset_ptr(fdt
, offset
, sizeof(*lenp
));
100 return FDT_END
; /* premature end */
101 /* skip-name offset, length and value */
102 offset
+= sizeof(struct fdt_property
) - FDT_TAGSIZE
103 + fdt32_to_cpu(*lenp
);
115 if (!fdt_offset_ptr(fdt
, startoffset
, offset
- startoffset
))
116 return FDT_END
; /* premature end */
118 *nextoffset
= FDT_TAGALIGN(offset
);
122 int _fdt_check_node_offset(const void *fdt
, int offset
)
124 if ((offset
< 0) || (offset
% FDT_TAGSIZE
)
125 || (fdt_next_tag(fdt
, offset
, &offset
) != FDT_BEGIN_NODE
))
126 return -FDT_ERR_BADOFFSET
;
131 int _fdt_check_prop_offset(const void *fdt
, int offset
)
133 if ((offset
< 0) || (offset
% FDT_TAGSIZE
)
134 || (fdt_next_tag(fdt
, offset
, &offset
) != FDT_PROP
))
135 return -FDT_ERR_BADOFFSET
;
140 int fdt_next_node(const void *fdt
, int offset
, int *depth
)
146 if ((nextoffset
= _fdt_check_node_offset(fdt
, offset
)) < 0)
151 tag
= fdt_next_tag(fdt
, offset
, &nextoffset
);
164 if (depth
&& ((--(*depth
)) < 0))
169 if ((nextoffset
>= 0)
170 || ((nextoffset
== -FDT_ERR_TRUNCATED
) && !depth
))
171 return -FDT_ERR_NOTFOUND
;
175 } while (tag
!= FDT_BEGIN_NODE
);
180 const char *_fdt_find_string(const char *strtab
, int tabsize
, const char *s
)
182 int len
= strlen(s
) + 1;
183 const char *last
= strtab
+ tabsize
- len
;
186 for (p
= strtab
; p
<= last
; p
++)
187 if (memcmp(p
, s
, len
) == 0)
192 int fdt_move(const void *fdt
, void *buf
, int bufsize
)
194 FDT_CHECK_HEADER(fdt
);
196 if (fdt_totalsize(fdt
) > bufsize
)
197 return -FDT_ERR_NOSPACE
;
199 memmove(buf
, fdt
, fdt_totalsize(fdt
));