diff options
Diffstat (limited to 'scripts/dtc/libfdt/fdt_overlay.c')
-rw-r--r-- | scripts/dtc/libfdt/fdt_overlay.c | 113 |
1 files changed, 34 insertions, 79 deletions
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index 5fdab6c6371d..5c0c3981b89d 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -1,53 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2016 Free Electrons * Copyright (C) 2016 NextThing Co. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -85,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) return fdt32_to_cpu(*val); } -/** - * overlay_get_target - retrieves the offset of a fragment's target - * @fdt: Base device tree blob - * @fdto: Device tree overlay blob - * @fragment: node offset of the fragment in the overlay - * @pathp: pointer which receives the path of the target (or NULL) - * - * overlay_get_target() retrieves the target offset in the base - * device tree of a fragment, no matter how the actual targetting is - * done (through a phandle or a path) - * - * returns: - * the targetted node offset in the base device tree - * Negative error code on error - */ -static int overlay_get_target(const void *fdt, const void *fdto, - int fragment, char const **pathp) +int fdt_overlay_target_offset(const void *fdt, const void *fdto, + int fragment_offset, char const **pathp) { uint32_t phandle; const char *path = NULL; int path_len = 0, ret; /* Try first to do a phandle based lookup */ - phandle = overlay_get_target_phandle(fdto, fragment); + phandle = overlay_get_target_phandle(fdto, fragment_offset); if (phandle == (uint32_t)-1) return -FDT_ERR_BADPHANDLE; /* no phandle, try path */ if (!phandle) { /* And then a path based lookup */ - path = fdt_getprop(fdto, fragment, "target-path", &path_len); + path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len); if (path) ret = fdt_path_offset(fdt, path); else @@ -286,6 +226,7 @@ static int overlay_update_local_node_references(void *fdto, if (fixup_len % sizeof(uint32_t)) return -FDT_ERR_BADOVERLAY; + fixup_len /= sizeof(uint32_t); tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); if (!tree_val) { @@ -295,7 +236,7 @@ static int overlay_update_local_node_references(void *fdto, return tree_len; } - for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { + for (i = 0; i < fixup_len; i++) { fdt32_t adj_val; uint32_t poffset; @@ -680,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto) if (overlay < 0) return overlay; - target = overlay_get_target(fdt, fdto, fragment, NULL); + target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL); if (target < 0) return target; @@ -778,26 +719,36 @@ static int overlay_symbol_update(void *fdt, void *fdto) /* keep end marker to avoid strlen() */ e = path + path_len; - /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ - if (*path != '/') return -FDT_ERR_BADVALUE; /* get fragment name first */ s = strchr(path + 1, '/'); - if (!s) - return -FDT_ERR_BADOVERLAY; + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } frag_name = path + 1; frag_name_len = s - path - 1; /* verify format; safe since "s" lies in \0 terminated prop */ len = sizeof("/__overlay__/") - 1; - if ((e - s) < len || memcmp(s, "/__overlay__/", len)) - return -FDT_ERR_BADOVERLAY; - - rel_path = s + len; - rel_path_len = e - rel_path; + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* /<fragment-name>/__overlay__/<relative-subnode-path> */ + rel_path = s + len; + rel_path_len = e - rel_path - 1; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* /<fragment-name>/__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } /* find the fragment index in which the symbol lies */ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, @@ -813,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) return -FDT_ERR_BADOVERLAY; /* get the target of the fragment */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); + ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; @@ -835,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto) if (!target_path) { /* again in case setprop_placeholder changed it */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); + ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; @@ -863,12 +814,16 @@ static int overlay_symbol_update(void *fdt, void *fdto) int fdt_overlay_apply(void *fdt, void *fdto) { - uint32_t delta = fdt_get_max_phandle(fdt); + uint32_t delta; int ret; FDT_RO_PROBE(fdt); FDT_RO_PROBE(fdto); + ret = fdt_find_max_phandle(fdt, &delta); + if (ret) + goto err; + ret = overlay_adjust_local_phandles(fdto, delta); if (ret) goto err; |