| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * libfdt - Flat Device Tree manipulation |
|---|
| 3 | 4 | * 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 | 5 | */ |
|---|
| 51 | 6 | #include "libfdt_env.h" |
|---|
| 52 | 7 | |
|---|
| .. | .. |
|---|
| 55 | 10 | |
|---|
| 56 | 11 | #include "libfdt_internal.h" |
|---|
| 57 | 12 | |
|---|
| 58 | | -static int fdt_sw_check_header_(void *fdt) |
|---|
| 13 | +static int fdt_sw_probe_(void *fdt) |
|---|
| 59 | 14 | { |
|---|
| 60 | | - if (fdt_magic(fdt) != FDT_SW_MAGIC) |
|---|
| 61 | | - return -FDT_ERR_BADMAGIC; |
|---|
| 62 | | - /* FIXME: should check more details about the header state */ |
|---|
| 15 | + if (!can_assume(VALID_INPUT)) { |
|---|
| 16 | + if (fdt_magic(fdt) == FDT_MAGIC) |
|---|
| 17 | + return -FDT_ERR_BADSTATE; |
|---|
| 18 | + else if (fdt_magic(fdt) != FDT_SW_MAGIC) |
|---|
| 19 | + return -FDT_ERR_BADMAGIC; |
|---|
| 20 | + } |
|---|
| 21 | + |
|---|
| 63 | 22 | return 0; |
|---|
| 64 | 23 | } |
|---|
| 65 | 24 | |
|---|
| 66 | | -#define FDT_SW_CHECK_HEADER(fdt) \ |
|---|
| 25 | +#define FDT_SW_PROBE(fdt) \ |
|---|
| 67 | 26 | { \ |
|---|
| 68 | 27 | int err; \ |
|---|
| 69 | | - if ((err = fdt_sw_check_header_(fdt)) != 0) \ |
|---|
| 28 | + if ((err = fdt_sw_probe_(fdt)) != 0) \ |
|---|
| 70 | 29 | return err; \ |
|---|
| 71 | 30 | } |
|---|
| 72 | 31 | |
|---|
| 32 | +/* 'memrsv' state: Initial state after fdt_create() |
|---|
| 33 | + * |
|---|
| 34 | + * Allowed functions: |
|---|
| 35 | + * fdt_add_reservemap_entry() |
|---|
| 36 | + * fdt_finish_reservemap() [moves to 'struct' state] |
|---|
| 37 | + */ |
|---|
| 38 | +static int fdt_sw_probe_memrsv_(void *fdt) |
|---|
| 39 | +{ |
|---|
| 40 | + int err = fdt_sw_probe_(fdt); |
|---|
| 41 | + if (err) |
|---|
| 42 | + return err; |
|---|
| 43 | + |
|---|
| 44 | + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) |
|---|
| 45 | + return -FDT_ERR_BADSTATE; |
|---|
| 46 | + return 0; |
|---|
| 47 | +} |
|---|
| 48 | + |
|---|
| 49 | +#define FDT_SW_PROBE_MEMRSV(fdt) \ |
|---|
| 50 | + { \ |
|---|
| 51 | + int err; \ |
|---|
| 52 | + if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ |
|---|
| 53 | + return err; \ |
|---|
| 54 | + } |
|---|
| 55 | + |
|---|
| 56 | +/* 'struct' state: Enter this state after fdt_finish_reservemap() |
|---|
| 57 | + * |
|---|
| 58 | + * Allowed functions: |
|---|
| 59 | + * fdt_begin_node() |
|---|
| 60 | + * fdt_end_node() |
|---|
| 61 | + * fdt_property*() |
|---|
| 62 | + * fdt_finish() [moves to 'complete' state] |
|---|
| 63 | + */ |
|---|
| 64 | +static int fdt_sw_probe_struct_(void *fdt) |
|---|
| 65 | +{ |
|---|
| 66 | + int err = fdt_sw_probe_(fdt); |
|---|
| 67 | + if (err) |
|---|
| 68 | + return err; |
|---|
| 69 | + |
|---|
| 70 | + if (!can_assume(VALID_INPUT) && |
|---|
| 71 | + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) |
|---|
| 72 | + return -FDT_ERR_BADSTATE; |
|---|
| 73 | + return 0; |
|---|
| 74 | +} |
|---|
| 75 | + |
|---|
| 76 | +#define FDT_SW_PROBE_STRUCT(fdt) \ |
|---|
| 77 | + { \ |
|---|
| 78 | + int err; \ |
|---|
| 79 | + if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ |
|---|
| 80 | + return err; \ |
|---|
| 81 | + } |
|---|
| 82 | + |
|---|
| 83 | +static inline uint32_t sw_flags(void *fdt) |
|---|
| 84 | +{ |
|---|
| 85 | + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ |
|---|
| 86 | + return fdt_last_comp_version(fdt); |
|---|
| 87 | +} |
|---|
| 88 | + |
|---|
| 89 | +/* 'complete' state: Enter this state after fdt_finish() |
|---|
| 90 | + * |
|---|
| 91 | + * Allowed functions: none |
|---|
| 92 | + */ |
|---|
| 93 | + |
|---|
| 73 | 94 | static void *fdt_grab_space_(void *fdt, size_t len) |
|---|
| 74 | 95 | { |
|---|
| 75 | | - int offset = fdt_size_dt_struct(fdt); |
|---|
| 76 | | - int spaceleft; |
|---|
| 96 | + unsigned int offset = fdt_size_dt_struct(fdt); |
|---|
| 97 | + unsigned int spaceleft; |
|---|
| 77 | 98 | |
|---|
| 78 | 99 | spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) |
|---|
| 79 | 100 | - fdt_size_dt_strings(fdt); |
|---|
| .. | .. |
|---|
| 85 | 106 | return fdt_offset_ptr_w_(fdt, offset); |
|---|
| 86 | 107 | } |
|---|
| 87 | 108 | |
|---|
| 88 | | -int fdt_create(void *buf, int bufsize) |
|---|
| 109 | +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) |
|---|
| 89 | 110 | { |
|---|
| 111 | + const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header), |
|---|
| 112 | + sizeof(struct fdt_reserve_entry)); |
|---|
| 90 | 113 | void *fdt = buf; |
|---|
| 91 | 114 | |
|---|
| 92 | | - if (bufsize < sizeof(struct fdt_header)) |
|---|
| 115 | + if (bufsize < hdrsize) |
|---|
| 93 | 116 | return -FDT_ERR_NOSPACE; |
|---|
| 117 | + |
|---|
| 118 | + if (flags & ~FDT_CREATE_FLAGS_ALL) |
|---|
| 119 | + return -FDT_ERR_BADFLAGS; |
|---|
| 94 | 120 | |
|---|
| 95 | 121 | memset(buf, 0, bufsize); |
|---|
| 96 | 122 | |
|---|
| 123 | + /* |
|---|
| 124 | + * magic and last_comp_version keep intermediate state during the fdt |
|---|
| 125 | + * creation process, which is replaced with the proper FDT format by |
|---|
| 126 | + * fdt_finish(). |
|---|
| 127 | + * |
|---|
| 128 | + * flags should be accessed with sw_flags(). |
|---|
| 129 | + */ |
|---|
| 97 | 130 | fdt_set_magic(fdt, FDT_SW_MAGIC); |
|---|
| 98 | 131 | fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); |
|---|
| 99 | | - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); |
|---|
| 132 | + fdt_set_last_comp_version(fdt, flags); |
|---|
| 133 | + |
|---|
| 100 | 134 | fdt_set_totalsize(fdt, bufsize); |
|---|
| 101 | 135 | |
|---|
| 102 | | - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), |
|---|
| 103 | | - sizeof(struct fdt_reserve_entry))); |
|---|
| 136 | + fdt_set_off_mem_rsvmap(fdt, hdrsize); |
|---|
| 104 | 137 | fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); |
|---|
| 105 | | - fdt_set_off_dt_strings(fdt, bufsize); |
|---|
| 138 | + fdt_set_off_dt_strings(fdt, 0); |
|---|
| 106 | 139 | |
|---|
| 107 | 140 | return 0; |
|---|
| 141 | +} |
|---|
| 142 | + |
|---|
| 143 | +int fdt_create(void *buf, int bufsize) |
|---|
| 144 | +{ |
|---|
| 145 | + return fdt_create_with_flags(buf, bufsize, 0); |
|---|
| 108 | 146 | } |
|---|
| 109 | 147 | |
|---|
| 110 | 148 | int fdt_resize(void *fdt, void *buf, int bufsize) |
|---|
| .. | .. |
|---|
| 112 | 150 | size_t headsize, tailsize; |
|---|
| 113 | 151 | char *oldtail, *newtail; |
|---|
| 114 | 152 | |
|---|
| 115 | | - FDT_SW_CHECK_HEADER(fdt); |
|---|
| 153 | + FDT_SW_PROBE(fdt); |
|---|
| 116 | 154 | |
|---|
| 117 | | - headsize = fdt_off_dt_struct(fdt); |
|---|
| 155 | + if (bufsize < 0) |
|---|
| 156 | + return -FDT_ERR_NOSPACE; |
|---|
| 157 | + |
|---|
| 158 | + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); |
|---|
| 118 | 159 | tailsize = fdt_size_dt_strings(fdt); |
|---|
| 119 | 160 | |
|---|
| 120 | | - if ((headsize + tailsize) > bufsize) |
|---|
| 161 | + if (!can_assume(VALID_DTB) && |
|---|
| 162 | + headsize + tailsize > fdt_totalsize(fdt)) |
|---|
| 163 | + return -FDT_ERR_INTERNAL; |
|---|
| 164 | + |
|---|
| 165 | + if ((headsize + tailsize) > (unsigned)bufsize) |
|---|
| 121 | 166 | return -FDT_ERR_NOSPACE; |
|---|
| 122 | 167 | |
|---|
| 123 | 168 | oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; |
|---|
| .. | .. |
|---|
| 133 | 178 | memmove(buf, fdt, headsize); |
|---|
| 134 | 179 | } |
|---|
| 135 | 180 | |
|---|
| 136 | | - fdt_set_off_dt_strings(buf, bufsize); |
|---|
| 137 | 181 | fdt_set_totalsize(buf, bufsize); |
|---|
| 182 | + if (fdt_off_dt_strings(buf)) |
|---|
| 183 | + fdt_set_off_dt_strings(buf, bufsize); |
|---|
| 138 | 184 | |
|---|
| 139 | 185 | return 0; |
|---|
| 140 | 186 | } |
|---|
| .. | .. |
|---|
| 144 | 190 | struct fdt_reserve_entry *re; |
|---|
| 145 | 191 | int offset; |
|---|
| 146 | 192 | |
|---|
| 147 | | - FDT_SW_CHECK_HEADER(fdt); |
|---|
| 148 | | - |
|---|
| 149 | | - if (fdt_size_dt_struct(fdt)) |
|---|
| 150 | | - return -FDT_ERR_BADSTATE; |
|---|
| 193 | + FDT_SW_PROBE_MEMRSV(fdt); |
|---|
| 151 | 194 | |
|---|
| 152 | 195 | offset = fdt_off_dt_struct(fdt); |
|---|
| 153 | 196 | if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) |
|---|
| .. | .. |
|---|
| 164 | 207 | |
|---|
| 165 | 208 | int fdt_finish_reservemap(void *fdt) |
|---|
| 166 | 209 | { |
|---|
| 167 | | - return fdt_add_reservemap_entry(fdt, 0, 0); |
|---|
| 210 | + int err = fdt_add_reservemap_entry(fdt, 0, 0); |
|---|
| 211 | + |
|---|
| 212 | + if (err) |
|---|
| 213 | + return err; |
|---|
| 214 | + |
|---|
| 215 | + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); |
|---|
| 216 | + return 0; |
|---|
| 168 | 217 | } |
|---|
| 169 | 218 | |
|---|
| 170 | 219 | int fdt_begin_node(void *fdt, const char *name) |
|---|
| 171 | 220 | { |
|---|
| 172 | 221 | struct fdt_node_header *nh; |
|---|
| 173 | | - int namelen = strlen(name) + 1; |
|---|
| 222 | + int namelen; |
|---|
| 174 | 223 | |
|---|
| 175 | | - FDT_SW_CHECK_HEADER(fdt); |
|---|
| 224 | + FDT_SW_PROBE_STRUCT(fdt); |
|---|
| 176 | 225 | |
|---|
| 226 | + namelen = strlen(name) + 1; |
|---|
| 177 | 227 | nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); |
|---|
| 178 | 228 | if (! nh) |
|---|
| 179 | 229 | return -FDT_ERR_NOSPACE; |
|---|
| .. | .. |
|---|
| 187 | 237 | { |
|---|
| 188 | 238 | fdt32_t *en; |
|---|
| 189 | 239 | |
|---|
| 190 | | - FDT_SW_CHECK_HEADER(fdt); |
|---|
| 240 | + FDT_SW_PROBE_STRUCT(fdt); |
|---|
| 191 | 241 | |
|---|
| 192 | 242 | en = fdt_grab_space_(fdt, FDT_TAGSIZE); |
|---|
| 193 | 243 | if (! en) |
|---|
| .. | .. |
|---|
| 197 | 247 | return 0; |
|---|
| 198 | 248 | } |
|---|
| 199 | 249 | |
|---|
| 200 | | -static int fdt_find_add_string_(void *fdt, const char *s) |
|---|
| 250 | +static int fdt_add_string_(void *fdt, const char *s) |
|---|
| 201 | 251 | { |
|---|
| 202 | 252 | char *strtab = (char *)fdt + fdt_totalsize(fdt); |
|---|
| 203 | | - const char *p; |
|---|
| 253 | + unsigned int strtabsize = fdt_size_dt_strings(fdt); |
|---|
| 254 | + unsigned int len = strlen(s) + 1; |
|---|
| 255 | + unsigned int struct_top, offset; |
|---|
| 256 | + |
|---|
| 257 | + offset = strtabsize + len; |
|---|
| 258 | + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); |
|---|
| 259 | + if (fdt_totalsize(fdt) - offset < struct_top) |
|---|
| 260 | + return 0; /* no more room :( */ |
|---|
| 261 | + |
|---|
| 262 | + memcpy(strtab - offset, s, len); |
|---|
| 263 | + fdt_set_size_dt_strings(fdt, strtabsize + len); |
|---|
| 264 | + return -offset; |
|---|
| 265 | +} |
|---|
| 266 | + |
|---|
| 267 | +/* Must only be used to roll back in case of error */ |
|---|
| 268 | +static void fdt_del_last_string_(void *fdt, const char *s) |
|---|
| 269 | +{ |
|---|
| 204 | 270 | int strtabsize = fdt_size_dt_strings(fdt); |
|---|
| 205 | 271 | int len = strlen(s) + 1; |
|---|
| 206 | | - int struct_top, offset; |
|---|
| 272 | + |
|---|
| 273 | + fdt_set_size_dt_strings(fdt, strtabsize - len); |
|---|
| 274 | +} |
|---|
| 275 | + |
|---|
| 276 | +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) |
|---|
| 277 | +{ |
|---|
| 278 | + char *strtab = (char *)fdt + fdt_totalsize(fdt); |
|---|
| 279 | + int strtabsize = fdt_size_dt_strings(fdt); |
|---|
| 280 | + const char *p; |
|---|
| 281 | + |
|---|
| 282 | + *allocated = 0; |
|---|
| 207 | 283 | |
|---|
| 208 | 284 | p = fdt_find_string_(strtab - strtabsize, strtabsize, s); |
|---|
| 209 | 285 | if (p) |
|---|
| 210 | 286 | return p - strtab; |
|---|
| 211 | 287 | |
|---|
| 212 | | - /* Add it */ |
|---|
| 213 | | - offset = -strtabsize - len; |
|---|
| 214 | | - struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); |
|---|
| 215 | | - if (fdt_totalsize(fdt) + offset < struct_top) |
|---|
| 216 | | - return 0; /* no more room :( */ |
|---|
| 288 | + *allocated = 1; |
|---|
| 217 | 289 | |
|---|
| 218 | | - memcpy(strtab + offset, s, len); |
|---|
| 219 | | - fdt_set_size_dt_strings(fdt, strtabsize + len); |
|---|
| 220 | | - return offset; |
|---|
| 290 | + return fdt_add_string_(fdt, s); |
|---|
| 221 | 291 | } |
|---|
| 222 | 292 | |
|---|
| 223 | 293 | int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) |
|---|
| 224 | 294 | { |
|---|
| 225 | 295 | struct fdt_property *prop; |
|---|
| 226 | 296 | int nameoff; |
|---|
| 297 | + int allocated; |
|---|
| 227 | 298 | |
|---|
| 228 | | - FDT_SW_CHECK_HEADER(fdt); |
|---|
| 299 | + FDT_SW_PROBE_STRUCT(fdt); |
|---|
| 229 | 300 | |
|---|
| 230 | | - nameoff = fdt_find_add_string_(fdt, name); |
|---|
| 301 | + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ |
|---|
| 302 | + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { |
|---|
| 303 | + allocated = 1; |
|---|
| 304 | + nameoff = fdt_add_string_(fdt, name); |
|---|
| 305 | + } else { |
|---|
| 306 | + nameoff = fdt_find_add_string_(fdt, name, &allocated); |
|---|
| 307 | + } |
|---|
| 231 | 308 | if (nameoff == 0) |
|---|
| 232 | 309 | return -FDT_ERR_NOSPACE; |
|---|
| 233 | 310 | |
|---|
| 234 | 311 | prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); |
|---|
| 235 | | - if (! prop) |
|---|
| 312 | + if (! prop) { |
|---|
| 313 | + if (allocated) |
|---|
| 314 | + fdt_del_last_string_(fdt, name); |
|---|
| 236 | 315 | return -FDT_ERR_NOSPACE; |
|---|
| 316 | + } |
|---|
| 237 | 317 | |
|---|
| 238 | 318 | prop->tag = cpu_to_fdt32(FDT_PROP); |
|---|
| 239 | 319 | prop->nameoff = cpu_to_fdt32(nameoff); |
|---|
| .. | .. |
|---|
| 262 | 342 | uint32_t tag; |
|---|
| 263 | 343 | int offset, nextoffset; |
|---|
| 264 | 344 | |
|---|
| 265 | | - FDT_SW_CHECK_HEADER(fdt); |
|---|
| 345 | + FDT_SW_PROBE_STRUCT(fdt); |
|---|
| 266 | 346 | |
|---|
| 267 | 347 | /* Add terminator */ |
|---|
| 268 | 348 | end = fdt_grab_space_(fdt, sizeof(*end)); |
|---|
| .. | .. |
|---|
| 295 | 375 | |
|---|
| 296 | 376 | /* Finally, adjust the header */ |
|---|
| 297 | 377 | fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); |
|---|
| 378 | + |
|---|
| 379 | + /* And fix up fields that were keeping intermediate state. */ |
|---|
| 380 | + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); |
|---|
| 298 | 381 | fdt_set_magic(fdt, FDT_MAGIC); |
|---|
| 382 | + |
|---|
| 299 | 383 | return 0; |
|---|
| 300 | 384 | } |
|---|