17ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson/* 27ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson * libfdt - Flat Device Tree manipulation 37ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson * Copyright (C) 2006 David Gibson, IBM Corporation. 47ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson * 5948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * libfdt is dual licensed: you can use it either under the terms of 6948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * the GPL, or the BSD license, at your option. 7948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 8948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * a) This library is free software; you can redistribute it and/or 9948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * modify it under the terms of the GNU General Public License as 10948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * published by the Free Software Foundation; either version 2 of the 11948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * License, or (at your option) any later version. 12948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 13948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * This library is distributed in the hope that it will be useful, 14948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * but WITHOUT ANY WARRANTY; without even the implied warranty of 15948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * GNU General Public License for more details. 17948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 18948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * You should have received a copy of the GNU General Public 19948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * License along with this library; if not, write to the Free 20948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 21948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * MA 02110-1301 USA 22948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 23948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * Alternatively, 24948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 25948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * b) Redistribution and use in source and binary forms, with or 26948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * without modification, are permitted provided that the following 27948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * conditions are met: 28948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 29948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 1. Redistributions of source code must retain the above 30948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * copyright notice, this list of conditions and the following 31948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * disclaimer. 32948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 2. Redistributions in binary form must reproduce the above 33948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * copyright notice, this list of conditions and the following 34948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * disclaimer in the documentation and/or other materials 35948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * provided with the distribution. 36948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * 37948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 38948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 39948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 40948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 42948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 47948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 48948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 49948160520884b10f545bec792e0d37c1c14bbf2fDavid Gibson * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 507ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson */ 517ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson#include "libfdt_env.h" 527ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 537ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson#include <fdt.h> 547ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson#include <libfdt.h> 557ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 567ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson#include "libfdt_internal.h" 577ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 58b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_blocks_misordered(const void *fdt, 59a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int mem_rsv_size, int struct_size) 60a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson{ 61b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) 62a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson || (fdt_off_dt_struct(fdt) < 63a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) 64a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson || (fdt_off_dt_strings(fdt) < 65a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson (fdt_off_dt_struct(fdt) + struct_size)) 66a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson || (fdt_totalsize(fdt) < 67a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); 68a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson} 69a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 70b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_rw_check_header(void *fdt) 717ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 72b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_CHECK_HEADER(fdt); 737ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 744a5df5c026c96f36326d4037a0658d38193e2ca1David Gibson if (fdt_version(fdt) < 17) 759a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return -FDT_ERR_BADVERSION; 76b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), 77b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson fdt_size_dt_struct(fdt))) 789a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return -FDT_ERR_BADLAYOUT; 794a5df5c026c96f36326d4037a0658d38193e2ca1David Gibson if (fdt_version(fdt) > 17) 804a5df5c026c96f36326d4037a0658d38193e2ca1David Gibson fdt_set_version(fdt, 17); 814a5df5c026c96f36326d4037a0658d38193e2ca1David Gibson 827ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return 0; 837ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 847ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 85b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson#define FDT_RW_CHECK_HEADER(fdt) \ 867ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson { \ 873a584d4760cfc81d21039346b0ce1cb5233e1d72Florian Fainelli int __err; \ 883a584d4760cfc81d21039346b0ce1cb5233e1d72Florian Fainelli if ((__err = _fdt_rw_check_header(fdt)) != 0) \ 893a584d4760cfc81d21039346b0ce1cb5233e1d72Florian Fainelli return __err; \ 907ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson } 917ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 92b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic inline int _fdt_data_size(void *fdt) 937ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 947ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); 957ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 967ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 97b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) 987ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 9936786db6154533b67d736b414ef63b4457009326David Gibson char *p = splicepoint; 100b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson char *end = (char *)fdt + _fdt_data_size(fdt); 1017ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 1027ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (((p + oldlen) < p) || ((p + oldlen) > end)) 1039a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return -FDT_ERR_BADOFFSET; 104d4c7c25c9ed138df8bafbe61097c27c9d2629ee3Courtney Cavin if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) 105d4c7c25c9ed138df8bafbe61097c27c9d2629ee3Courtney Cavin return -FDT_ERR_BADOFFSET; 10636786db6154533b67d736b414ef63b4457009326David Gibson if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) 1079a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return -FDT_ERR_NOSPACE; 1087ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson memmove(p + newlen, p + oldlen, end - p - oldlen); 1097ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return 0; 1107ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 1117ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 112b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, 113b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson int oldn, int newn) 114fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson{ 115fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson int delta = (newn - oldn) * sizeof(*p); 116fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson int err; 117b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); 118fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson if (err) 119fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson return err; 1209b91134ba3043deb7689bcee06b78a596647c626David Gibson fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); 1219b91134ba3043deb7689bcee06b78a596647c626David Gibson fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); 122fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson return 0; 123fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson} 124fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 125b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_splice_struct(void *fdt, void *p, 126b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson int oldlen, int newlen) 1277ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 1287ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int delta = newlen - oldlen; 1297ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 1307ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 131b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson if ((err = _fdt_splice(fdt, p, oldlen, newlen))) 1327ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return err; 1337ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 1349b91134ba3043deb7689bcee06b78a596647c626David Gibson fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); 1359b91134ba3043deb7689bcee06b78a596647c626David Gibson fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); 1367ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return 0; 1377ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 1387ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 139b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_splice_string(void *fdt, int newlen) 1407ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 14136786db6154533b67d736b414ef63b4457009326David Gibson void *p = (char *)fdt 14236786db6154533b67d736b414ef63b4457009326David Gibson + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); 1437ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 1447ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 145b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson if ((err = _fdt_splice(fdt, p, 0, newlen))) 1467ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return err; 1477ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 1489b91134ba3043deb7689bcee06b78a596647c626David Gibson fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); 1497ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return 0; 1507ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 1517ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 152b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_find_add_string(void *fdt, const char *s) 1537ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 1547ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); 1557ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson const char *p; 1567ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson char *new; 1577ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int len = strlen(s) + 1; 1587ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 1597ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 1607ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); 1617ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (p) 1627ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson /* found it */ 1637ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return (p - strtab); 1647ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 1657ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson new = strtab + fdt_size_dt_strings(fdt); 166b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_splice_string(fdt, len); 1677ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (err) 1689a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return err; 1697ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 1707ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson memcpy(new, s, len); 1717ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return (new - strtab); 1727ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 1737ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 174fd1bf3a5ae46962528ef89a824261a88830758a2David Gibsonint fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) 175fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson{ 176fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson struct fdt_reserve_entry *re; 177fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson int err; 178fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 179b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 180fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 181fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); 182b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_splice_mem_rsv(fdt, re, 0, 1); 183fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson if (err) 184fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson return err; 185fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 186fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson re->address = cpu_to_fdt64(address); 187fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson re->size = cpu_to_fdt64(size); 188fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson return 0; 189fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson} 190fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 191fd1bf3a5ae46962528ef89a824261a88830758a2David Gibsonint fdt_del_mem_rsv(void *fdt, int n) 192fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson{ 193fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); 194fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 195b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 196aa1baab3cc184169cfb05dfe289b5179c8333e3cDavid Gibson 197fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson if (n >= fdt_num_mem_rsv(fdt)) 198fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson return -FDT_ERR_NOTFOUND; 199fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 20036fd7331fb11276c09a6affc0d8cd4977f2fe100Masahiro Yamada return _fdt_splice_mem_rsv(fdt, re, 1, 0); 201fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson} 202fd1bf3a5ae46962528ef89a824261a88830758a2David Gibson 203b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, 204b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson int len, struct fdt_property **prop) 2057ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 2067ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int oldlen; 2077ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 2087ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 209a6c76f923dcc42102fac58375eaca28057811c20David Gibson *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); 210a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson if (! (*prop)) 2119a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return oldlen; 2127ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 213b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), 214b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_TAGALIGN(len)))) 215a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson return err; 2167ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 217a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson (*prop)->len = cpu_to_fdt32(len); 218a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson return 0; 2197ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 2207ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 221b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic int _fdt_add_property(void *fdt, int nodeoffset, const char *name, 222b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson int len, struct fdt_property **prop) 2237ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 2247ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int proplen; 2257ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int nextoffset; 2267ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int namestroff; 2277ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 2287ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 229aa1baab3cc184169cfb05dfe289b5179c8333e3cDavid Gibson if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) 230aa1baab3cc184169cfb05dfe289b5179c8333e3cDavid Gibson return nextoffset; 2317ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 232b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson namestroff = _fdt_find_add_string(fdt, name); 2337ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (namestroff < 0) 2349a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return namestroff; 2357ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 236a6c76f923dcc42102fac58375eaca28057811c20David Gibson *prop = _fdt_offset_ptr_w(fdt, nextoffset); 237b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson proplen = sizeof(**prop) + FDT_TAGALIGN(len); 2387ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 239b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_splice_struct(fdt, *prop, 0, proplen); 2407ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (err) 241a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson return err; 2427ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 243a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson (*prop)->tag = cpu_to_fdt32(FDT_PROP); 244a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson (*prop)->nameoff = cpu_to_fdt32(namestroff); 245a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson (*prop)->len = cpu_to_fdt32(len); 246a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson return 0; 2477ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 2487ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 24982b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibsonint fdt_set_name(void *fdt, int nodeoffset, const char *name) 25082b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson{ 25182b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson char *namep; 25282b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson int oldlen, newlen; 25382b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson int err; 25482b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson 255b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 25682b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson 2571409097db8be6ba662e3808654671554c5803bf0David Gibson namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); 25882b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson if (!namep) 25982b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson return oldlen; 26082b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson 26182b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson newlen = strlen(name); 26282b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson 263b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), 264b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_TAGALIGN(newlen+1)); 26582b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson if (err) 26682b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson return err; 26782b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson 26882b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson memcpy(namep, name, newlen+1); 26982b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson return 0; 27082b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson} 27182b327d38062cdb4e5628856f9b440ad6c96e7f8David Gibson 27273d60926a05814b8864c86c435e272b386513b0eDavid Gibsonint fdt_setprop(void *fdt, int nodeoffset, const char *name, 2737ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson const void *val, int len) 2747ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 2757ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson struct fdt_property *prop; 2767ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 2777ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 278b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 2797ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 280b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); 2819a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson if (err == -FDT_ERR_NOTFOUND) 282b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); 2837ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (err) 2847ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return err; 2857ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 28669a1bd6ad3f9272b3db36e6415864a1fb6af4b9dDavid Gibson if (len) 28769a1bd6ad3f9272b3db36e6415864a1fb6af4b9dDavid Gibson memcpy(prop->data, val, len); 2887ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return 0; 2897ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 2907ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 291a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lianint fdt_appendprop(void *fdt, int nodeoffset, const char *name, 292a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian const void *val, int len) 293a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian{ 294a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian struct fdt_property *prop; 295a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian int err, oldlen, newlen; 296a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian 297a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian FDT_RW_CHECK_HEADER(fdt); 298a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian 299a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); 300a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian if (prop) { 301a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian newlen = len + oldlen; 302a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian err = _fdt_splice_struct(fdt, prop->data, 303a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian FDT_TAGALIGN(oldlen), 304a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian FDT_TAGALIGN(newlen)); 305a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian if (err) 306a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian return err; 307a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian prop->len = cpu_to_fdt32(newlen); 308a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian memcpy(prop->data + oldlen, val, len); 309a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian } else { 310a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); 311a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian if (err) 312a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian return err; 313a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian memcpy(prop->data, val, len); 314a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian } 315a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian return 0; 316a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian} 317a31e3ef83bfce62d07695355e5f06cd4d0e44b86Minghuan Lian 31873d60926a05814b8864c86c435e272b386513b0eDavid Gibsonint fdt_delprop(void *fdt, int nodeoffset, const char *name) 3197ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 3207ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson struct fdt_property *prop; 3217ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int len, proplen; 3227ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 323b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 3247ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 325a6c76f923dcc42102fac58375eaca28057811c20David Gibson prop = fdt_get_property_w(fdt, nodeoffset, name, &len); 326a7ee95ded6a0d64c1c259b9c6fea090e19ca81f8David Gibson if (! prop) 3279a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return len; 3287ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 329b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson proplen = sizeof(*prop) + FDT_TAGALIGN(len); 330b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson return _fdt_splice_struct(fdt, prop, proplen, 0); 3317ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 3327ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 33373d60926a05814b8864c86c435e272b386513b0eDavid Gibsonint fdt_add_subnode_namelen(void *fdt, int parentoffset, 3347ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson const char *name, int namelen) 3357ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 3367ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson struct fdt_node_header *nh; 3377ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int offset, nextoffset; 3387ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int nodelen; 3397ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 3407ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson uint32_t tag; 341142419e43c99e88cbe72a760a72cdbf520690eb6Kim Phillips fdt32_t *endtag; 3427ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 343b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 3447ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 3457ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); 3469a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson if (offset >= 0) 3479a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return -FDT_ERR_EXISTS; 3489a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson else if (offset != -FDT_ERR_NOTFOUND) 3499a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return offset; 3507ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 3517ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson /* Try to place the new node after the parent's properties */ 3523c44c87bdeacc66f46c55090d765a9766475ee50David Gibson fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ 3537ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson do { 3547ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson offset = nextoffset; 3553c44c87bdeacc66f46c55090d765a9766475ee50David Gibson tag = fdt_next_tag(fdt, offset, &nextoffset); 356089adb9964a222499eb204198b579c231c59c42fDavid Gibson } while ((tag == FDT_PROP) || (tag == FDT_NOP)); 3577ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 358a6c76f923dcc42102fac58375eaca28057811c20David Gibson nh = _fdt_offset_ptr_w(fdt, offset); 359b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; 360568b569e8961641587cfda8ec23e64cafe45f6d7David Gibson 361b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson err = _fdt_splice_struct(fdt, nh, 0, nodelen); 3627ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson if (err) 3639a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return err; 3647ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 3657ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); 366b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); 3677ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson memcpy(nh->name, name, namelen); 368142419e43c99e88cbe72a760a72cdbf520690eb6Kim Phillips endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); 3697ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson *endtag = cpu_to_fdt32(FDT_END_NODE); 3707ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 3717ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return offset; 3727ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 3737ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 37473d60926a05814b8864c86c435e272b386513b0eDavid Gibsonint fdt_add_subnode(void *fdt, int parentoffset, const char *name) 3757ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 3767ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); 3777ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 3787ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 37973d60926a05814b8864c86c435e272b386513b0eDavid Gibsonint fdt_del_node(void *fdt, int nodeoffset) 3807ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 3817ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int endoffset; 3827ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 383b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 384394e47208df7e3b22c089745695f41966d100f3eDavid Gibson 3857ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson endoffset = _fdt_node_end_offset(fdt, nodeoffset); 3869a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson if (endoffset < 0) 3879a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return endoffset; 3887ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 389b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), 390b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson endoffset - nodeoffset, 0); 3917ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 3927ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 393b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibsonstatic void _fdt_packblocks(const char *old, char *new, 394b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson int mem_rsv_size, int struct_size) 395a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson{ 396a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int mem_rsv_off, struct_off, strings_off; 397a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 398b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); 399a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson struct_off = mem_rsv_off + mem_rsv_size; 400a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson strings_off = struct_off + struct_size; 401a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 40236786db6154533b67d736b414ef63b4457009326David Gibson memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); 40336786db6154533b67d736b414ef63b4457009326David Gibson fdt_set_off_mem_rsvmap(new, mem_rsv_off); 404a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 40536786db6154533b67d736b414ef63b4457009326David Gibson memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); 40636786db6154533b67d736b414ef63b4457009326David Gibson fdt_set_off_dt_struct(new, struct_off); 40736786db6154533b67d736b414ef63b4457009326David Gibson fdt_set_size_dt_struct(new, struct_size); 408a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 40936786db6154533b67d736b414ef63b4457009326David Gibson memmove(new + strings_off, old + fdt_off_dt_strings(old), 41036786db6154533b67d736b414ef63b4457009326David Gibson fdt_size_dt_strings(old)); 41136786db6154533b67d736b414ef63b4457009326David Gibson fdt_set_off_dt_strings(new, strings_off); 41236786db6154533b67d736b414ef63b4457009326David Gibson fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); 413a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson} 414a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 415a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibsonint fdt_open_into(const void *fdt, void *buf, int bufsize) 4167ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 4177ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson int err; 418a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int mem_rsv_size, struct_size; 419a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int newsize; 42036786db6154533b67d736b414ef63b4457009326David Gibson const char *fdtstart = fdt; 42136786db6154533b67d736b414ef63b4457009326David Gibson const char *fdtend = fdtstart + fdt_totalsize(fdt); 42236786db6154533b67d736b414ef63b4457009326David Gibson char *tmp; 4237ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 424b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_CHECK_HEADER(fdt); 4257ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 426a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) 427a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson * sizeof(struct fdt_reserve_entry); 42873d60926a05814b8864c86c435e272b386513b0eDavid Gibson 429a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson if (fdt_version(fdt) >= 17) { 430a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson struct_size = fdt_size_dt_struct(fdt); 431a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson } else { 432a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson struct_size = 0; 433a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) 434a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson ; 4351a020e403048a56ffacb8c6f71aef0944b901757David Gibson if (struct_size < 0) 4361a020e403048a56ffacb8c6f71aef0944b901757David Gibson return struct_size; 437a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson } 4387ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 439b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { 440a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson /* no further work necessary */ 441a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson err = fdt_move(fdt, buf, bufsize); 442a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson if (err) 443a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson return err; 444a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_version(buf, 17); 445a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_size_dt_struct(buf, struct_size); 446a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_totalsize(buf, bufsize); 447a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson return 0; 448a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson } 4497ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 450a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson /* Need to reorder */ 451b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size 452a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson + struct_size + fdt_size_dt_strings(fdt); 453a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 454a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson if (bufsize < newsize) 455a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson return -FDT_ERR_NOSPACE; 456a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 45736786db6154533b67d736b414ef63b4457009326David Gibson /* First attempt to build converted tree at beginning of buffer */ 45836786db6154533b67d736b414ef63b4457009326David Gibson tmp = buf; 45936786db6154533b67d736b414ef63b4457009326David Gibson /* But if that overlaps with the old tree... */ 46036786db6154533b67d736b414ef63b4457009326David Gibson if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { 46136786db6154533b67d736b414ef63b4457009326David Gibson /* Try right after the old tree instead */ 4621409097db8be6ba662e3808654671554c5803bf0David Gibson tmp = (char *)(uintptr_t)fdtend; 46336786db6154533b67d736b414ef63b4457009326David Gibson if ((tmp + newsize) > ((char *)buf + bufsize)) 464a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson return -FDT_ERR_NOSPACE; 465a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson } 466a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 467b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); 468a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson memmove(buf, tmp, newsize); 469a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 470a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_magic(buf, FDT_MAGIC); 471a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_totalsize(buf, bufsize); 472a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_version(buf, 17); 473a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_last_comp_version(buf, 16); 474a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); 4757ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 4769a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return 0; 4777ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 4787ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 47973d60926a05814b8864c86c435e272b386513b0eDavid Gibsonint fdt_pack(void *fdt) 4807ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson{ 481a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson int mem_rsv_size; 4827ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 483b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson FDT_RW_CHECK_HEADER(fdt); 4847ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson 485a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) 486a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson * sizeof(struct fdt_reserve_entry); 487b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); 488b6d80a20fc293f3b995c3ce1a6744a5574192125David Gibson fdt_set_totalsize(fdt, _fdt_data_size(fdt)); 489a041dcdc48453f26b76bccdb5e2a1ebb3a0ea987David Gibson 4909a9fdf59913c6d14f1755fe653dc8161ec6b0b7bDavid Gibson return 0; 4917ba551f96629a5273370329658a6e6b3a87068aaDavid Gibson} 492