diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2017-10-17 22:30:20 +0900 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-11-17 07:44:13 -0500 |
commit | 50a327ded68b7e675389ad284ea3f8c62e683bda (patch) | |
tree | 8ca210b444ac4b4de6a5104431066b89777c8897 /lib/libfdt | |
parent | 1c4b453ad2a62d0243ae5fd6657f2d6b7eb7332d (diff) |
lib: libfdt: wrap scripts/dtc/libfdt/* where possible
lib/libfdt/ and scripts/dtc/libfdt have the same copies for the
followings 6 files:
fdt.c fdt_addresses.c fdt_empty_tree.c fdt_overlay.c fdt_strerr.c
fdt_sw.c
Make them a wrapper of scripts/dtc/libfdt/*. This is exactly what
Linux does to sync libfdt. In order to make is possible, import
<linux/libfdt.h> and <linux/libfdt_env.h> from Linux 4.14-rc5.
Unfortunately, U-Boot locally modified the following 3 files:
fdt_ro.c fdt_wip.c fdt_rw.c
The fdt_region.c is U-Boot own file.
I did not touch them in order to avoid unpredictable impact.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'lib/libfdt')
-rw-r--r-- | lib/libfdt/Makefile | 17 | ||||
-rw-r--r-- | lib/libfdt/fdt.c | 212 | ||||
-rw-r--r-- | lib/libfdt/fdt_addresses.c | 57 | ||||
-rw-r--r-- | lib/libfdt/fdt_empty_tree.c | 39 | ||||
-rw-r--r-- | lib/libfdt/fdt_overlay.c | 863 | ||||
-rw-r--r-- | lib/libfdt/fdt_strerror.c | 63 | ||||
-rw-r--r-- | lib/libfdt/fdt_sw.c | 256 |
7 files changed, 24 insertions, 1483 deletions
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile index 6ef8290f4e..369bbf9ba3 100644 --- a/lib/libfdt/Makefile +++ b/lib/libfdt/Makefile @@ -5,15 +5,22 @@ # SPDX-License-Identifier: GPL-2.0+ # +# Use upstream code. obj-y += \ fdt.o \ - fdt_ro.o \ - fdt_rw.o \ fdt_strerror.o \ fdt_sw.o \ - fdt_wip.o \ fdt_empty_tree.o \ - fdt_addresses.o \ - fdt_region.o + fdt_addresses.o obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o + +# Locally modified for U-Boot. +# TODO: split out the local modifiction. +obj-y += \ + fdt_ro.o \ + fdt_rw.o \ + fdt_wip.o \ + +# U-Boot own file +obj-y += fdt_region.o diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c index 2055734012..0958e6ba57 100644 --- a/lib/libfdt/fdt.c +++ b/lib/libfdt/fdt.c @@ -1,210 +1,2 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ -#include <libfdt_env.h> - -#ifndef USE_HOSTCC -#include <fdt.h> -#include <libfdt.h> -#else -#include "fdt_host.h" -#endif - -#include "libfdt_internal.h" - -int fdt_check_header(const void *fdt) -{ - if (fdt_magic(fdt) == FDT_MAGIC) { - /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) - return -FDT_ERR_BADSTATE; - } else { - return -FDT_ERR_BADMAGIC; - } - - return 0; -} - -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) -{ - unsigned absoffset = offset + fdt_off_dt_struct(fdt); - - if ((absoffset < offset) - || ((absoffset + len) < absoffset) - || (absoffset + len) > fdt_totalsize(fdt)) - return NULL; - - if (fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) - || ((offset + len) > fdt_size_dt_struct(fdt))) - return NULL; - - return _fdt_offset_ptr(fdt, offset); -} - -uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) -{ - const fdt32_t *tagp, *lenp; - uint32_t tag; - int offset = startoffset; - const char *p; - - *nextoffset = -FDT_ERR_TRUNCATED; - tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) - return FDT_END; /* premature end */ - tag = fdt32_to_cpu(*tagp); - offset += FDT_TAGSIZE; - - *nextoffset = -FDT_ERR_BADSTRUCTURE; - switch (tag) { - case FDT_BEGIN_NODE: - /* skip name */ - do { - p = fdt_offset_ptr(fdt, offset++, 1); - } while (p && (*p != '\0')); - if (!p) - return FDT_END; /* premature end */ - break; - - case FDT_PROP: - lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) - return FDT_END; /* premature end */ - /* skip-name offset, length and value */ - offset += sizeof(struct fdt_property) - FDT_TAGSIZE - + fdt32_to_cpu(*lenp); - break; - - case FDT_END: - case FDT_END_NODE: - case FDT_NOP: - break; - - default: - return FDT_END; - } - - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) - return FDT_END; /* premature end */ - - *nextoffset = FDT_TAGALIGN(offset); - return tag; -} - -int _fdt_check_node_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int _fdt_check_prop_offset(const void *fdt, int offset) -{ - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) - return -FDT_ERR_BADOFFSET; - - return offset; -} - -int fdt_next_node(const void *fdt, int offset, int *depth) -{ - int nextoffset = 0; - uint32_t tag; - - if (offset >= 0) - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) - return nextoffset; - - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_PROP: - case FDT_NOP: - break; - - case FDT_BEGIN_NODE: - if (depth) - (*depth)++; - break; - - case FDT_END_NODE: - if (depth && ((--(*depth)) < 0)) - return nextoffset; - break; - - case FDT_END: - if ((nextoffset >= 0) - || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) - return -FDT_ERR_NOTFOUND; - else - return nextoffset; - } - } while (tag != FDT_BEGIN_NODE); - - return offset; -} - -int fdt_first_subnode(const void *fdt, int offset) -{ - int depth = 0; - - offset = fdt_next_node(fdt, offset, &depth); - if (offset < 0 || depth != 1) - return -FDT_ERR_NOTFOUND; - - return offset; -} - -int fdt_next_subnode(const void *fdt, int offset) -{ - int depth = 1; - - /* - * With respect to the parent, the depth of the next subnode will be - * the same as the last. - */ - do { - offset = fdt_next_node(fdt, offset, &depth); - if (offset < 0 || depth < 1) - return -FDT_ERR_NOTFOUND; - } while (depth > 1); - - return offset; -} - -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) -{ - int len = strlen(s) + 1; - const char *last = strtab + tabsize - len; - const char *p; - - for (p = strtab; p <= last; p++) - if (memcmp(p, s, len) == 0) - return p; - return NULL; -} - -int fdt_move(const void *fdt, void *buf, int bufsize) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_totalsize(fdt) > bufsize) - return -FDT_ERR_NOSPACE; - - memmove(buf, fdt, fdt_totalsize(fdt)); - return 0; -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt.c" diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c index b6bc66ea32..b82a02936c 100644 --- a/lib/libfdt/fdt_addresses.c +++ b/lib/libfdt/fdt_addresses.c @@ -1,55 +1,2 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ -#include <libfdt_env.h> - -#ifndef USE_HOSTCC -#include <fdt.h> -#include <libfdt.h> -#else -#include "fdt_host.h" -#endif - -#include "libfdt_internal.h" - -int fdt_address_cells(const void *fdt, int nodeoffset) -{ - const fdt32_t *ac; - int val; - int len; - - ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); - if (!ac) - return 2; - - if (len != sizeof(*ac)) - return -FDT_ERR_BADNCELLS; - - val = fdt32_to_cpu(*ac); - if ((val <= 0) || (val > FDT_MAX_NCELLS)) - return -FDT_ERR_BADNCELLS; - - return val; -} - -int fdt_size_cells(const void *fdt, int nodeoffset) -{ - const fdt32_t *sc; - int val; - int len; - - sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); - if (!sc) - return 2; - - if (len != sizeof(*sc)) - return -FDT_ERR_BADNCELLS; - - val = fdt32_to_cpu(*sc); - if ((val < 0) || (val > FDT_MAX_NCELLS)) - return -FDT_ERR_BADNCELLS; - - return val; -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt_addresses.c" diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c index 6fde1eb9ed..2b4ae1062b 100644 --- a/lib/libfdt/fdt_empty_tree.c +++ b/lib/libfdt/fdt_empty_tree.c @@ -1,37 +1,2 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2012 David Gibson, IBM Corporation. - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ -#include <libfdt_env.h> -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -int fdt_create_empty_tree(void *buf, int bufsize) -{ - int err; - - err = fdt_create(buf, bufsize); - if (err) - return err; - - err = fdt_finish_reservemap(buf); - if (err) - return err; - - err = fdt_begin_node(buf, ""); - if (err) - return err; - - err = fdt_end_node(buf); - if (err) - return err; - - err = fdt_finish(buf); - if (err) - return err; - - return fdt_open_into(buf, buf, bufsize); -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt_empty_tree.c" diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c index bd81241e66..575c827673 100644 --- a/lib/libfdt/fdt_overlay.c +++ b/lib/libfdt/fdt_overlay.c @@ -1,861 +1,2 @@ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -/** - * overlay_get_target_phandle - retrieves the target phandle of a fragment - * @fdto: pointer to the device tree overlay blob - * @fragment: node offset of the fragment in the overlay - * - * overlay_get_target_phandle() retrieves the target phandle of an - * overlay fragment when that fragment uses a phandle (target - * property) instead of a path (target-path property). - * - * returns: - * the phandle pointed by the target property - * 0, if the phandle was not found - * -1, if the phandle was malformed - */ -static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) -{ - const fdt32_t *val; - int len; - - val = fdt_getprop(fdto, fragment, "target", &len); - if (!val) - return 0; - - if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) - return (uint32_t)-1; - - 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) -{ - 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); - 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); - if (path) - ret = fdt_path_offset(fdt, path); - else - ret = path_len; - } else - ret = fdt_node_offset_by_phandle(fdt, phandle); - - /* - * If we haven't found either a target or a - * target-path property in a node that contains a - * __overlay__ subnode (we wouldn't be called - * otherwise), consider it a improperly written - * overlay - */ - if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) - ret = -FDT_ERR_BADOVERLAY; - - /* return on error */ - if (ret < 0) - return ret; - - /* return pointer to path (if available) */ - if (pathp) - *pathp = path ? path : NULL; - - return ret; -} - -/** - * overlay_phandle_add_offset - Increases a phandle by an offset - * @fdt: Base device tree blob - * @node: Device tree overlay blob - * @name: Name of the property to modify (phandle or linux,phandle) - * @delta: offset to apply - * - * overlay_phandle_add_offset() increments a node phandle by a given - * offset. - * - * returns: - * 0 on success. - * Negative error code on error - */ -static int overlay_phandle_add_offset(void *fdt, int node, - const char *name, uint32_t delta) -{ - const fdt32_t *val; - uint32_t adj_val; - int len; - - val = fdt_getprop(fdt, node, name, &len); - if (!val) - return len; - - if (len != sizeof(*val)) - return -FDT_ERR_BADPHANDLE; - - adj_val = fdt32_to_cpu(*val); - if ((adj_val + delta) < adj_val) - return -FDT_ERR_NOPHANDLES; - - adj_val += delta; - if (adj_val == (uint32_t)-1) - return -FDT_ERR_NOPHANDLES; - - return fdt_setprop_inplace_u32(fdt, node, name, adj_val); -} - -/** - * overlay_adjust_node_phandles - Offsets the phandles of a node - * @fdto: Device tree overlay blob - * @node: Offset of the node we want to adjust - * @delta: Offset to shift the phandles of - * - * overlay_adjust_node_phandles() adds a constant to all the phandles - * of a given node. This is mainly use as part of the overlay - * application process, when we want to update all the overlay - * phandles to not conflict with the overlays of the base device tree. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_adjust_node_phandles(void *fdto, int node, - uint32_t delta) -{ - int child; - int ret; - - ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); - if (ret && ret != -FDT_ERR_NOTFOUND) - return ret; - - ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); - if (ret && ret != -FDT_ERR_NOTFOUND) - return ret; - - fdt_for_each_subnode(child, fdto, node) { - ret = overlay_adjust_node_phandles(fdto, child, delta); - if (ret) - return ret; - } - - return 0; -} - -/** - * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay - * @fdto: Device tree overlay blob - * @delta: Offset to shift the phandles of - * - * overlay_adjust_local_phandles() adds a constant to all the - * phandles of an overlay. This is mainly use as part of the overlay - * application process, when we want to update all the overlay - * phandles to not conflict with the overlays of the base device tree. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) -{ - /* - * Start adjusting the phandles from the overlay root - */ - return overlay_adjust_node_phandles(fdto, 0, delta); -} - -/** - * overlay_update_local_node_references - Adjust the overlay references - * @fdto: Device tree overlay blob - * @tree_node: Node offset of the node to operate on - * @fixup_node: Node offset of the matching local fixups node - * @delta: Offset to shift the phandles of - * - * overlay_update_local_nodes_references() update the phandles - * pointing to a node within the device tree overlay by adding a - * constant delta. - * - * This is mainly used as part of a device tree application process, - * where you want the device tree overlays phandles to not conflict - * with the ones from the base device tree before merging them. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_update_local_node_references(void *fdto, - int tree_node, - int fixup_node, - uint32_t delta) -{ - int fixup_prop; - int fixup_child; - int ret; - - fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { - const fdt32_t *fixup_val; - const char *tree_val; - const char *name; - int fixup_len; - int tree_len; - int i; - - fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, - &name, &fixup_len); - if (!fixup_val) - return fixup_len; - - if (fixup_len % sizeof(uint32_t)) - return -FDT_ERR_BADOVERLAY; - - tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); - if (!tree_val) { - if (tree_len == -FDT_ERR_NOTFOUND) - return -FDT_ERR_BADOVERLAY; - - return tree_len; - } - - for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { - fdt32_t adj_val; - uint32_t poffset; - - poffset = fdt32_to_cpu(fixup_val[i]); - - /* - * phandles to fixup can be unaligned. - * - * Use a memcpy for the architectures that do - * not support unaligned accesses. - */ - memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); - - adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); - - ret = fdt_setprop_inplace_namelen_partial(fdto, - tree_node, - name, - strlen(name), - poffset, - &adj_val, - sizeof(adj_val)); - if (ret == -FDT_ERR_NOSPACE) - return -FDT_ERR_BADOVERLAY; - - if (ret) - return ret; - } - } - - fdt_for_each_subnode(fixup_child, fdto, fixup_node) { - const char *fixup_child_name = fdt_get_name(fdto, fixup_child, - NULL); - int tree_child; - - tree_child = fdt_subnode_offset(fdto, tree_node, - fixup_child_name); - if (tree_child == -FDT_ERR_NOTFOUND) - return -FDT_ERR_BADOVERLAY; - if (tree_child < 0) - return tree_child; - - ret = overlay_update_local_node_references(fdto, - tree_child, - fixup_child, - delta); - if (ret) - return ret; - } - - return 0; -} - -/** - * overlay_update_local_references - Adjust the overlay references - * @fdto: Device tree overlay blob - * @delta: Offset to shift the phandles of - * - * overlay_update_local_references() update all the phandles pointing - * to a node within the device tree overlay by adding a constant - * delta to not conflict with the base overlay. - * - * This is mainly used as part of a device tree application process, - * where you want the device tree overlays phandles to not conflict - * with the ones from the base device tree before merging them. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_update_local_references(void *fdto, uint32_t delta) -{ - int fixups; - - fixups = fdt_path_offset(fdto, "/__local_fixups__"); - if (fixups < 0) { - /* There's no local phandles to adjust, bail out */ - if (fixups == -FDT_ERR_NOTFOUND) - return 0; - - return fixups; - } - - /* - * Update our local references from the root of the tree - */ - return overlay_update_local_node_references(fdto, 0, fixups, - delta); -} - -/** - * overlay_fixup_one_phandle - Set an overlay phandle to the base one - * @fdt: Base Device Tree blob - * @fdto: Device tree overlay blob - * @symbols_off: Node offset of the symbols node in the base device tree - * @path: Path to a node holding a phandle in the overlay - * @path_len: number of path characters to consider - * @name: Name of the property holding the phandle reference in the overlay - * @name_len: number of name characters to consider - * @poffset: Offset within the overlay property where the phandle is stored - * @label: Label of the node referenced by the phandle - * - * overlay_fixup_one_phandle() resolves an overlay phandle pointing to - * a node in the base device tree. - * - * This is part of the device tree overlay application process, when - * you want all the phandles in the overlay to point to the actual - * base dt nodes. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_fixup_one_phandle(void *fdt, void *fdto, - int symbols_off, - const char *path, uint32_t path_len, - const char *name, uint32_t name_len, - int poffset, const char *label) -{ - const char *symbol_path; - uint32_t phandle; - fdt32_t phandle_prop; - int symbol_off, fixup_off; - int prop_len; - - if (symbols_off < 0) - return symbols_off; - - symbol_path = fdt_getprop(fdt, symbols_off, label, - &prop_len); - if (!symbol_path) - return prop_len; - - symbol_off = fdt_path_offset(fdt, symbol_path); - if (symbol_off < 0) - return symbol_off; - - phandle = fdt_get_phandle(fdt, symbol_off); - if (!phandle) - return -FDT_ERR_NOTFOUND; - - fixup_off = fdt_path_offset_namelen(fdto, path, path_len); - if (fixup_off == -FDT_ERR_NOTFOUND) - return -FDT_ERR_BADOVERLAY; - if (fixup_off < 0) - return fixup_off; - - phandle_prop = cpu_to_fdt32(phandle); - return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, - name, name_len, poffset, - &phandle_prop, - sizeof(phandle_prop)); -}; - -/** - * overlay_fixup_phandle - Set an overlay phandle to the base one - * @fdt: Base Device Tree blob - * @fdto: Device tree overlay blob - * @symbols_off: Node offset of the symbols node in the base device tree - * @property: Property offset in the overlay holding the list of fixups - * - * overlay_fixup_phandle() resolves all the overlay phandles pointed - * to in a __fixups__ property, and updates them to match the phandles - * in use in the base device tree. - * - * This is part of the device tree overlay application process, when - * you want all the phandles in the overlay to point to the actual - * base dt nodes. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, - int property) -{ - const char *value; - const char *label; - int len; - - value = fdt_getprop_by_offset(fdto, property, - &label, &len); - if (!value) { - if (len == -FDT_ERR_NOTFOUND) - return -FDT_ERR_INTERNAL; - - return len; - } - - do { - const char *path, *name, *fixup_end; - const char *fixup_str = value; - uint32_t path_len, name_len; - uint32_t fixup_len; - char *sep, *endptr; - int poffset, ret; - - fixup_end = memchr(value, '\0', len); - if (!fixup_end) - return -FDT_ERR_BADOVERLAY; - fixup_len = fixup_end - fixup_str; - - len -= fixup_len + 1; - value += fixup_len + 1; - - path = fixup_str; - sep = memchr(fixup_str, ':', fixup_len); - if (!sep || *sep != ':') - return -FDT_ERR_BADOVERLAY; - - path_len = sep - path; - if (path_len == (fixup_len - 1)) - return -FDT_ERR_BADOVERLAY; - - fixup_len -= path_len + 1; - name = sep + 1; - sep = memchr(name, ':', fixup_len); - if (!sep || *sep != ':') - return -FDT_ERR_BADOVERLAY; - - name_len = sep - name; - if (!name_len) - return -FDT_ERR_BADOVERLAY; - - poffset = strtoul(sep + 1, &endptr, 10); - if ((*endptr != '\0') || (endptr <= (sep + 1))) - return -FDT_ERR_BADOVERLAY; - - ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, - path, path_len, name, name_len, - poffset, label); - if (ret) - return ret; - } while (len > 0); - - return 0; -} - -/** - * overlay_fixup_phandles - Resolve the overlay phandles to the base - * device tree - * @fdt: Base Device Tree blob - * @fdto: Device tree overlay blob - * - * overlay_fixup_phandles() resolves all the overlay phandles pointing - * to nodes in the base device tree. - * - * This is one of the steps of the device tree overlay application - * process, when you want all the phandles in the overlay to point to - * the actual base dt nodes. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_fixup_phandles(void *fdt, void *fdto) -{ - int fixups_off, symbols_off; - int property; - - /* We can have overlays without any fixups */ - fixups_off = fdt_path_offset(fdto, "/__fixups__"); - if (fixups_off == -FDT_ERR_NOTFOUND) - return 0; /* nothing to do */ - if (fixups_off < 0) - return fixups_off; - - /* And base DTs without symbols */ - symbols_off = fdt_path_offset(fdt, "/__symbols__"); - if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) - return symbols_off; - - fdt_for_each_property_offset(property, fdto, fixups_off) { - int ret; - - ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); - if (ret) - return ret; - } - - return 0; -} - -/** - * overlay_apply_node - Merges a node into the base device tree - * @fdt: Base Device Tree blob - * @target: Node offset in the base device tree to apply the fragment to - * @fdto: Device tree overlay blob - * @node: Node offset in the overlay holding the changes to merge - * - * overlay_apply_node() merges a node into a target base device tree - * node pointed. - * - * This is part of the final step in the device tree overlay - * application process, when all the phandles have been adjusted and - * resolved and you just have to merge overlay into the base device - * tree. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_apply_node(void *fdt, int target, - void *fdto, int node) -{ - int property; - int subnode; - - fdt_for_each_property_offset(property, fdto, node) { - const char *name; - const void *prop; - int prop_len; - int ret; - - prop = fdt_getprop_by_offset(fdto, property, &name, - &prop_len); - if (prop_len == -FDT_ERR_NOTFOUND) - return -FDT_ERR_INTERNAL; - if (prop_len < 0) - return prop_len; - - ret = fdt_setprop(fdt, target, name, prop, prop_len); - if (ret) - return ret; - } - - fdt_for_each_subnode(subnode, fdto, node) { - const char *name = fdt_get_name(fdto, subnode, NULL); - int nnode; - int ret; - - nnode = fdt_add_subnode(fdt, target, name); - if (nnode == -FDT_ERR_EXISTS) { - nnode = fdt_subnode_offset(fdt, target, name); - if (nnode == -FDT_ERR_NOTFOUND) - return -FDT_ERR_INTERNAL; - } - - if (nnode < 0) - return nnode; - - ret = overlay_apply_node(fdt, nnode, fdto, subnode); - if (ret) - return ret; - } - - return 0; -} - -/** - * overlay_merge - Merge an overlay into its base device tree - * @fdt: Base Device Tree blob - * @fdto: Device tree overlay blob - * - * overlay_merge() merges an overlay into its base device tree. - * - * This is the next to last step in the device tree overlay application - * process, when all the phandles have been adjusted and resolved and - * you just have to merge overlay into the base device tree. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_merge(void *fdt, void *fdto) -{ - int fragment; - - fdt_for_each_subnode(fragment, fdto, 0) { - int overlay; - int target; - int ret; - - /* - * Each fragments will have an __overlay__ node. If - * they don't, it's not supposed to be merged - */ - overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); - if (overlay == -FDT_ERR_NOTFOUND) - continue; - - if (overlay < 0) - return overlay; - - target = overlay_get_target(fdt, fdto, fragment, NULL); - if (target < 0) - return target; - - ret = overlay_apply_node(fdt, target, fdto, overlay); - if (ret) - return ret; - } - - return 0; -} - -static int get_path_len(const void *fdt, int nodeoffset) -{ - int len = 0, namelen; - const char *name; - - FDT_CHECK_HEADER(fdt); - - for (;;) { - name = fdt_get_name(fdt, nodeoffset, &namelen); - if (!name) - return namelen; - - /* root? we're done */ - if (namelen == 0) - break; - - nodeoffset = fdt_parent_offset(fdt, nodeoffset); - if (nodeoffset < 0) - return nodeoffset; - len += namelen + 1; - } - - /* in case of root pretend it's "/" */ - if (len == 0) - len++; - return len; -} - -/** - * overlay_symbol_update - Update the symbols of base tree after a merge - * @fdt: Base Device Tree blob - * @fdto: Device tree overlay blob - * - * overlay_symbol_update() updates the symbols of the base tree with the - * symbols of the applied overlay - * - * This is the last step in the device tree overlay application - * process, allowing the reference of overlay symbols by subsequent - * overlay operations. - * - * returns: - * 0 on success - * Negative error code on failure - */ -static int overlay_symbol_update(void *fdt, void *fdto) -{ - int root_sym, ov_sym, prop, path_len, fragment, target; - int len, frag_name_len, ret, rel_path_len; - const char *s, *e; - const char *path; - const char *name; - const char *frag_name; - const char *rel_path; - const char *target_path; - char *buf; - void *p; - - ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); - - /* if no overlay symbols exist no problem */ - if (ov_sym < 0) - return 0; - - root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); - - /* it no root symbols exist we should create them */ - if (root_sym == -FDT_ERR_NOTFOUND) - root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); - - /* any error is fatal now */ - if (root_sym < 0) - return root_sym; - - /* iterate over each overlay symbol */ - fdt_for_each_property_offset(prop, fdto, ov_sym) { - path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); - if (!path) - return path_len; - - /* verify it's a string property (terminated by a single \0) */ - if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) - return -FDT_ERR_BADVALUE; - - /* 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; - - 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; - - /* find the fragment index in which the symbol lies */ - ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, - frag_name_len); - /* not found? */ - if (ret < 0) - return -FDT_ERR_BADOVERLAY; - fragment = ret; - - /* an __overlay__ subnode must exist */ - ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); - if (ret < 0) - return -FDT_ERR_BADOVERLAY; - - /* get the target of the fragment */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); - if (ret < 0) - return ret; - target = ret; - - /* if we have a target path use */ - if (!target_path) { - ret = get_path_len(fdt, target); - if (ret < 0) - return ret; - len = ret; - } else { - len = strlen(target_path); - } - - ret = fdt_setprop_placeholder(fdt, root_sym, name, - len + (len > 1) + rel_path_len + 1, &p); - if (ret < 0) - return ret; - - if (!target_path) { - /* again in case setprop_placeholder changed it */ - ret = overlay_get_target(fdt, fdto, fragment, &target_path); - if (ret < 0) - return ret; - target = ret; - } - - buf = p; - if (len > 1) { /* target is not root */ - if (!target_path) { - ret = fdt_get_path(fdt, target, buf, len + 1); - if (ret < 0) - return ret; - } else - memcpy(buf, target_path, len + 1); - - } else - len--; - - buf[len] = '/'; - memcpy(buf + len + 1, rel_path, rel_path_len); - buf[len + 1 + rel_path_len] = '\0'; - } - - return 0; -} - -int fdt_overlay_apply(void *fdt, void *fdto) -{ - uint32_t delta = fdt_get_max_phandle(fdt); - int ret; - - FDT_CHECK_HEADER(fdt); - FDT_CHECK_HEADER(fdto); - - ret = overlay_adjust_local_phandles(fdto, delta); - if (ret) - goto err; - - ret = overlay_update_local_references(fdto, delta); - if (ret) - goto err; - - ret = overlay_fixup_phandles(fdt, fdto); - if (ret) - goto err; - - ret = overlay_merge(fdt, fdto); - if (ret) - goto err; - - ret = overlay_symbol_update(fdt, fdto); - if (ret) - goto err; - - /* - * The overlay has been damaged, erase its magic. - */ - fdt_set_magic(fdto, ~0); - - return 0; - -err: - /* - * The overlay might have been damaged, erase its magic. - */ - fdt_set_magic(fdto, ~0); - - /* - * The base device tree might have been damaged, erase its - * magic. - */ - fdt_set_magic(fdt, ~0); - - return ret; -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt_overlay.c" diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c index f89004c609..408a88328f 100644 --- a/lib/libfdt/fdt_strerror.c +++ b/lib/libfdt/fdt_strerror.c @@ -1,61 +1,2 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ -#include <libfdt_env.h> - -#ifndef USE_HOSTCC -#include <fdt.h> -#include <libfdt.h> -#else -#include "fdt_host.h" -#endif - -#include "libfdt_internal.h" - -struct fdt_errtabent { - const char *str; -}; - -#define FDT_ERRTABENT(val) \ - [(val)] = { .str = #val, } - -static struct fdt_errtabent fdt_errtable[] = { - FDT_ERRTABENT(FDT_ERR_NOTFOUND), - FDT_ERRTABENT(FDT_ERR_EXISTS), - FDT_ERRTABENT(FDT_ERR_NOSPACE), - - FDT_ERRTABENT(FDT_ERR_BADOFFSET), - FDT_ERRTABENT(FDT_ERR_BADPATH), - FDT_ERRTABENT(FDT_ERR_BADPHANDLE), - FDT_ERRTABENT(FDT_ERR_BADSTATE), - - FDT_ERRTABENT(FDT_ERR_TRUNCATED), - FDT_ERRTABENT(FDT_ERR_BADMAGIC), - FDT_ERRTABENT(FDT_ERR_BADVERSION), - FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), - FDT_ERRTABENT(FDT_ERR_BADLAYOUT), - FDT_ERRTABENT(FDT_ERR_INTERNAL), - FDT_ERRTABENT(FDT_ERR_BADNCELLS), - FDT_ERRTABENT(FDT_ERR_BADVALUE), - FDT_ERRTABENT(FDT_ERR_BADOVERLAY), - FDT_ERRTABENT(FDT_ERR_NOPHANDLES), -}; -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) - -const char *fdt_strerror(int errval) -{ - if (errval > 0) - return "<valid offset/length>"; - else if (errval == 0) - return "<no error>"; - else if (errval > -FDT_ERRTABSIZE) { - const char *s = fdt_errtable[-errval].str; - - if (s) - return s; - } - - return "<unknown error>"; -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt_strerror.c" diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c index 70fd026550..0da3ed92f3 100644 --- a/lib/libfdt/fdt_sw.c +++ b/lib/libfdt/fdt_sw.c @@ -1,254 +1,2 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ -#include <libfdt_env.h> -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -static int _fdt_sw_check_header(void *fdt) -{ - if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; - /* FIXME: should check more details about the header state */ - return 0; -} - -#define FDT_SW_CHECK_HEADER(fdt) \ - { \ - int err; \ - if ((err = _fdt_sw_check_header(fdt)) != 0) \ - return err; \ - } - -static void *_fdt_grab_space(void *fdt, size_t len) -{ - int offset = fdt_size_dt_struct(fdt); - int spaceleft; - - spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - - fdt_size_dt_strings(fdt); - - if ((offset + len < offset) || (offset + len > spaceleft)) - return NULL; - - fdt_set_size_dt_struct(fdt, offset + len); - return _fdt_offset_ptr_w(fdt, offset); -} - -int fdt_create(void *buf, int bufsize) -{ - void *fdt = buf; - - if (bufsize < sizeof(struct fdt_header)) - return -FDT_ERR_NOSPACE; - - memset(buf, 0, bufsize); - - fdt_set_magic(fdt, FDT_SW_MAGIC); - fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); - fdt_set_totalsize(fdt, bufsize); - - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); - fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, bufsize); - - return 0; -} - -int fdt_resize(void *fdt, void *buf, int bufsize) -{ - size_t headsize, tailsize; - char *oldtail, *newtail; - - FDT_SW_CHECK_HEADER(fdt); - - headsize = fdt_off_dt_struct(fdt); - tailsize = fdt_size_dt_strings(fdt); - - if ((headsize + tailsize) > bufsize) - return -FDT_ERR_NOSPACE; - - oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; - newtail = (char *)buf + bufsize - tailsize; - - /* Two cases to avoid clobbering data if the old and new - * buffers partially overlap */ - if (buf <= fdt) { - memmove(buf, fdt, headsize); - memmove(newtail, oldtail, tailsize); - } else { - memmove(newtail, oldtail, tailsize); - memmove(buf, fdt, headsize); - } - - fdt_set_off_dt_strings(buf, bufsize); - fdt_set_totalsize(buf, bufsize); - - return 0; -} - -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) -{ - struct fdt_reserve_entry *re; - int offset; - - FDT_SW_CHECK_HEADER(fdt); - - if (fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTATE; - - offset = fdt_off_dt_struct(fdt); - if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) - return -FDT_ERR_NOSPACE; - - re = (struct fdt_reserve_entry *)((char *)fdt + offset); - re->address = cpu_to_fdt64(addr); - re->size = cpu_to_fdt64(size); - - fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); - - return 0; -} - -int fdt_finish_reservemap(void *fdt) -{ - return fdt_add_reservemap_entry(fdt, 0, 0); -} - -int fdt_begin_node(void *fdt, const char *name) -{ - struct fdt_node_header *nh; - int namelen = strlen(name) + 1; - - FDT_SW_CHECK_HEADER(fdt); - - nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); - if (! nh) - return -FDT_ERR_NOSPACE; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memcpy(nh->name, name, namelen); - return 0; -} - -int fdt_end_node(void *fdt) -{ - fdt32_t *en; - - FDT_SW_CHECK_HEADER(fdt); - - en = _fdt_grab_space(fdt, FDT_TAGSIZE); - if (! en) - return -FDT_ERR_NOSPACE; - - *en = cpu_to_fdt32(FDT_END_NODE); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_totalsize(fdt); - const char *p; - int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; - - p = _fdt_find_string(strtab - strtabsize, strtabsize, s); - if (p) - return p - strtab; - - /* Add it */ - offset = -strtabsize - len; - struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) - return 0; /* no more room :( */ - - memcpy(strtab + offset, s, len); - fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; -} - -int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) -{ - struct fdt_property *prop; - int nameoff; - - FDT_SW_CHECK_HEADER(fdt); - - nameoff = _fdt_find_add_string(fdt, name); - if (nameoff == 0) - return -FDT_ERR_NOSPACE; - - prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) - return -FDT_ERR_NOSPACE; - - prop->tag = cpu_to_fdt32(FDT_PROP); - prop->nameoff = cpu_to_fdt32(nameoff); - prop->len = cpu_to_fdt32(len); - *valp = prop->data; - return 0; -} - -int fdt_property(void *fdt, const char *name, const void *val, int len) -{ - void *ptr; - int ret; - - ret = fdt_property_placeholder(fdt, name, len, &ptr); - if (ret) - return ret; - memcpy(ptr, val, len); - return 0; -} - -int fdt_finish(void *fdt) -{ - char *p = (char *)fdt; - fdt32_t *end; - int oldstroffset, newstroffset; - uint32_t tag; - int offset, nextoffset; - - FDT_SW_CHECK_HEADER(fdt); - - /* Add terminator */ - end = _fdt_grab_space(fdt, sizeof(*end)); - if (! end) - return -FDT_ERR_NOSPACE; - *end = cpu_to_fdt32(FDT_END); - - /* Relocate the string table */ - oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); - newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); - fdt_set_off_dt_strings(fdt, newstroffset); - - /* Walk the structure, correcting string offsets */ - offset = 0; - while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { - if (tag == FDT_PROP) { - struct fdt_property *prop = - _fdt_offset_ptr_w(fdt, offset); - int nameoff; - - nameoff = fdt32_to_cpu(prop->nameoff); - nameoff += fdt_size_dt_strings(fdt); - prop->nameoff = cpu_to_fdt32(nameoff); - } - offset = nextoffset; - } - if (nextoffset < 0) - return nextoffset; - - /* Finally, adjust the header */ - fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); - fdt_set_magic(fdt, FDT_MAGIC); - return 0; -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt_sw.c" |