blob: 1ac9d682a759cd4c1d7915249f6b8ee1aab5118c [file] [log] [blame]
Mayank Groverf3b78182017-12-19 13:31:30 +05301#ifndef FDT_INTERNAL_H
2#define FDT_INTERNAL_H
3
4/*
5 * libfdt - Flat Device Tree manipulation
6 * Copyright (C) 2006 David Gibson, IBM Corporation.
7 *
8 * libfdt is dual licensed: you can use it either under the terms of
9 * the GPL, or the BSD license, at your option.
10 *
11 * a) This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this library; if not, write to the Free
23 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
24 * MA 02110-1301 USA
25 *
26 * Alternatively,
27 *
28 * b) Redistribution and use in source and binary forms, with or
29 * without modification, are permitted provided that the following
30 * conditions are met:
31 *
32 * 1. Redistributions of source code must retain the above
33 * copyright notice, this list of conditions and the following
34 * disclaimer.
35 * 2. Redistributions in binary form must reproduce the above
36 * copyright notice, this list of conditions and the following
37 * disclaimer in the documentation and/or other materials
38 * provided with the distribution.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
41 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
42 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
43 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
45 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
51 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
52 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55#include "libfdt.h"
56#include "libufdt_sysdeps.h"
57
58
59/*
60 * Most of the codes below are copied from external/dtc/libfdt/libfdt_internal.h
61 * and external/dtc/libfdt/fdt_sw.c .
62 */
63
64#define FDT_ALIGN(x, a) (((x) + (a)-1) & ~((a)-1))
65#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
66
67static inline const void *_fdt_offset_ptr(const void *fdt, int offset) {
68 return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
69}
70
71static inline void *_fdt_offset_ptr_w(void *fdt, int offset) {
72 return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
73}
74
75#define FDT_SW_MAGIC (~FDT_MAGIC)
76
77static int _fdt_sw_check_header(void *fdt) {
78 if (fdt_magic(fdt) != FDT_SW_MAGIC) return -FDT_ERR_BADMAGIC;
79 /* FIXME: should check more details about the header state */
80 return 0;
81}
82
83#define FDT_SW_CHECK_HEADER(fdt) \
84 { \
85 int err; \
86 if ((err = _fdt_sw_check_header(fdt)) != 0) return err; \
87 }
88
89static void *_fdt_grab_space(void *fdt, size_t len) {
90 int offset = fdt_size_dt_struct(fdt);
91 int spaceleft;
92
93 spaceleft =
94 fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - fdt_size_dt_strings(fdt);
95
96 if ((offset + (int)len < offset) || (offset + (int)len > spaceleft))
97 return NULL;
98
99 fdt_set_size_dt_struct(fdt, offset + len);
100 return _fdt_offset_ptr_w(fdt, offset);
101}
102
103static int _fdt_add_string(void *fdt, const char *s) {
104 char *strtab = (char *)fdt + fdt_totalsize(fdt);
105 int strtabsize = fdt_size_dt_strings(fdt);
106 int len = dto_strlen(s) + 1;
107 int struct_top, offset;
108
109 /* Add it */
110 offset = -strtabsize - len;
111 struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
112 if (fdt_totalsize(fdt) + offset < (size_t)struct_top)
113 return 0; /* no more room :( */
114
115 dto_memcpy(strtab + offset, s, len);
116 fdt_set_size_dt_strings(fdt, strtabsize + len);
117 return offset;
118}
119
120/*
121 * From Google, speed up fdt_property() by passing nameoff to the function.
122 * Adds new string to fdt if *pnameoff is 0.
123 * Otherwise, use the nameoff provided.
124 */
125static int fast_fdt_sw_property(void *fdt, const char *name, const void *val,
126 int len, int *pnameoff,
127 struct fdt_property **prop_ptr) {
128 FDT_SW_CHECK_HEADER(fdt);
129
130 if (*pnameoff == 0) {
131 *pnameoff = _fdt_add_string(fdt, name);
132 if (*pnameoff == 0) return -FDT_ERR_NOSPACE;
133 }
134
135 *prop_ptr = _fdt_grab_space(fdt, sizeof(**prop_ptr) + FDT_TAGALIGN(len));
136 if (*prop_ptr == NULL) return -FDT_ERR_NOSPACE;
137
138 (*prop_ptr)->tag = cpu_to_fdt32(FDT_PROP);
139 (*prop_ptr)->nameoff = cpu_to_fdt32(*pnameoff);
140 (*prop_ptr)->len = cpu_to_fdt32(len);
141 dto_memcpy((*prop_ptr)->data, val, len);
142 return 0;
143}
144
145#endif /* FDT_INTERNAL_H */