]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scripts/dtc: Update to upstream version v1.7.2-62-ga26ef6400bd8
authorRob Herring (Arm) <robh@kernel.org>
Wed, 21 Jan 2026 18:49:42 +0000 (12:49 -0600)
committerRob Herring (Arm) <robh@kernel.org>
Wed, 4 Feb 2026 02:58:12 +0000 (20:58 -0600)
This adds the following commits from upstream:

a26ef6400bd8 Restore phandle references from __fixups__ node
05c524db44ff Restore phandle references from __local_fixups__ node
db65a3a3f4f0 Restore labels from __symbols__ node
64330c682cac Improve type guessing when compiling to dts format
cbb48690c697 Set DTSF_PLUGIN if needed when compiling from dtb
ef3b1baf6370 Emit /plugin/ when compiling to .dts with DTSF_PLUGIN set
7c78c8542d73 Added empty node name check
14dd76b96732 fdtdump: Change FDT_PROP prob handling to ease future addition
9a1c801a1a3c Fix discarded const qualifiers
194ac9422ac9 libfdt: fdt_get_name: Add can_assume(VALID_DTB) check
39cae0bd0031 libfdt: Improve size savings in FDT_RO_PROBE slightly
b12692473298 libfdt: libfdt_internal.h correct final comment in ASSUME block
7f3184a6c550 libfdt: Remove old MacOS strnlen workaround
9197f1ccd95c checks: Do not check overlays for alias paths
e1284ee5dc20 livetree: Add only new data to fixup nodes instead of complete regeneration
cba90ce82064 checks: Remove check for graph child addresses
763c6ab4189c livetree: Simplify append_to_property()
739403f22242 libfdt: Drop including string.h from libfdt_internal.h
1c6c51e51b29 Consider drive letters when checking for absolute paths on Windows.
617f3d9b60f7 ci: Add Cirrus CI configuration for FreeBSD testing
04f948e83fef ci: Add GitLab CI configuration for Linux builds
e89680263137 ci: Tweaks to GitHub Actions setup
2ad738722b79 build: Add FreeBSD and non-GNU linker compatibility
4132ac08ba95 libfdt: Document most remaining functions
33e66ec845b8 tests: Add compatibility with uutils
a0dd7b608102 fdtput: Use strtol() in preference to sscanf()
5b71660724d7 tests: Work around limitation in FreeBSD's printf(1)

The graph_child_address check has been removed from upstream. Drop it
from the makefiles.

Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
15 files changed:
Documentation/devicetree/bindings/Makefile
scripts/Makefile.dtbs
scripts/dtc/checks.c
scripts/dtc/dtc.c
scripts/dtc/dtc.h
scripts/dtc/flattree.c
scripts/dtc/libfdt/fdt_overlay.c
scripts/dtc/libfdt/fdt_ro.c
scripts/dtc/libfdt/libfdt.h
scripts/dtc/libfdt/libfdt_env.h
scripts/dtc/libfdt/libfdt_internal.h
scripts/dtc/livetree.c
scripts/dtc/srcpos.c
scripts/dtc/treesource.c
scripts/dtc/version_gen.h

index 1e116425ad704e1930017de5b10acccce6a4c44c..7b668f7fd4007f03bb61d942926fe493339d1f6e 100644 (file)
@@ -56,7 +56,6 @@ DT_DOCS = $(patsubst $(srctree)/%,%,$(shell $(find_all_cmd)))
 
 override DTC_FLAGS := \
        -Wno-avoid_unnecessary_addr_size \
-       -Wno-graph_child_address \
        -Wno-unique_unit_address \
        -Wunique_unit_address_if_enabled
 
index e092b460d5a1baf861dda8fc53963ccf909dd1ac..c4e4663902844d2133a9512c37ad49e6e5447ef6 100644 (file)
@@ -105,7 +105,6 @@ ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),)
 DTC_FLAGS += -Wno-unit_address_vs_reg \
              -Wno-avoid_unnecessary_addr_size \
              -Wno-alias_paths \
-             -Wno-graph_child_address \
              -Wno-interrupt_map \
              -Wno-simple_bus_reg
 else
index 7e3fed5005b310a69701e5a235f7afdd98aa6f86..45d0213f3bf3374dde6d3d86368f830c15c52c52 100644 (file)
@@ -340,6 +340,14 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
 }
 ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
 
+static void check_node_name_not_empty(struct check *c, struct dt_info *dti,
+                                     struct node *node)
+{
+       if (node->basenamelen == 0 && node->parent != NULL)
+               FAIL(c, dti, node, "Empty node name");
+}
+ERROR(node_name_not_empty, check_node_name_not_empty, NULL, &node_name_chars);
+
 static void check_node_name_vs_property_name(struct check *c,
                                             struct dt_info *dti,
                                             struct node *node)
@@ -718,11 +726,14 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
                        continue;
                }
 
-               if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
+               /* This check does not work for overlays with external paths */
+               if (!(dti->dtsflags & DTSF_PLUGIN) &&
+                   (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val))) {
                        FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
                                  prop->val.val);
                        continue;
                }
+
                if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
                        FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
        }
@@ -1894,34 +1905,9 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
 }
 WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
 
-static void check_graph_child_address(struct check *c, struct dt_info *dti,
-                                     struct node *node)
-{
-       int cnt = 0;
-       struct node *child;
-
-       if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
-               return;
-
-       for_each_child(node, child) {
-               struct property *prop = get_property(child, "reg");
-
-               /* No error if we have any non-zero unit address */
-                if (prop && propval_cell(prop) != 0 )
-                       return;
-
-               cnt++;
-       }
-
-       if (cnt == 1 && node->addr_cells != -1)
-               FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
-                    node->children->name);
-}
-WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes, &graph_port, &graph_endpoint);
-
 static struct check *check_table[] = {
        &duplicate_node_names, &duplicate_property_names,
-       &node_name_chars, &node_name_format, &property_name_chars,
+       &node_name_chars, &node_name_format, &node_name_not_empty, &property_name_chars,
        &name_is_string, &name_properties, &node_name_vs_property_name,
 
        &duplicate_label,
@@ -2005,7 +1991,7 @@ static struct check *check_table[] = {
 
        &alias_paths,
 
-       &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
+       &graph_nodes, &graph_port, &graph_endpoint,
 
        &always_fail,
 };
index b3445b7d6473b1a13499ddd176f47cf108ed8c3c..6dae60de0ea58458ee9ad284b882d6063a53a45d 100644 (file)
@@ -338,9 +338,14 @@ int main(int argc, char *argv[])
        if (auto_label_aliases)
                generate_label_tree(dti, "aliases", false);
 
+       generate_labels_from_tree(dti, "__symbols__");
+
        if (generate_symbols)
                generate_label_tree(dti, "__symbols__", true);
 
+       fixup_phandles(dti, "__fixups__");
+       local_fixup_phandles(dti, "__local_fixups__");
+
        if (generate_fixups) {
                generate_fixups_tree(dti, "__fixups__");
                generate_local_fixups_tree(dti, "__local_fixups__");
index 3a220b9afc99f92ea57d50d348eb0872bc779818..7231200e5d02ccd420b3f3e37ae41fd8314b280a 100644 (file)
@@ -339,9 +339,12 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
                              struct reserve_info *reservelist,
                              struct node *tree, uint32_t boot_cpuid_phys);
 void sort_tree(struct dt_info *dti);
+void generate_labels_from_tree(struct dt_info *dti, const char *name);
 void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
 void generate_fixups_tree(struct dt_info *dti, const char *name);
+void fixup_phandles(struct dt_info *dti, const char *name);
 void generate_local_fixups_tree(struct dt_info *dti, const char *name);
+void local_fixup_phandles(struct dt_info *dti, const char *name);
 
 /* Checks */
 
@@ -357,6 +360,9 @@ struct dt_info *dt_from_blob(const char *fname);
 
 /* Tree source */
 
+void property_add_marker(struct property *prop,
+                        enum markertype type, unsigned int offset, char *ref);
+void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset);
 void dt_to_source(FILE *f, struct dt_info *dti);
 struct dt_info *dt_from_source(const char *f);
 
index 30e6de2044b2c4368d9dc24cf1039ce6500c4664..f3b698c17e89ec642485d5cbff65d5bfa607dc1a 100644 (file)
@@ -807,6 +807,7 @@ struct dt_info *dt_from_blob(const char *fname)
        struct node *tree;
        uint32_t val;
        int flags = 0;
+       unsigned int dtsflags = DTSF_V1;
 
        f = srcfile_relative_open(fname, NULL);
 
@@ -919,5 +920,8 @@ struct dt_info *dt_from_blob(const char *fname)
 
        fclose(f);
 
-       return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
+       if (get_subnode(tree, "__fixups__") || get_subnode(tree, "__local_fixups__"))
+               dtsflags |= DTSF_PLUGIN;
+
+       return build_dt_info(dtsflags, reservelist, tree, boot_cpuid_phys);
 }
index e6b9eb6439585364ff4e84eecacea7a61bcc67eb..51a3859620a47f9f5435eb6c88b239920e2895cc 100644 (file)
@@ -407,7 +407,8 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
                const char *fixup_str = value;
                uint32_t path_len, name_len;
                uint32_t fixup_len;
-               char *sep, *endptr;
+               const char *sep;
+               char *endptr;
                int poffset, ret;
 
                fixup_end = memchr(value, '\0', len);
index b78c4e48f1cb351504af4d861513b47f375262f5..63494fb7ad904ff8b3e54c12279e6e36c10eb85c 100644 (file)
@@ -306,8 +306,8 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
        const char *nameptr;
        int err;
 
-       if (((err = fdt_ro_probe_(fdt)) < 0)
-           || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
+       if (!can_assume(VALID_DTB) && (((err = fdt_ro_probe_(fdt)) < 0)
+           || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
                        goto fail;
 
        nameptr = nh->name;
index 914bf90785ab30b6fe03047126918039b5fa2a70..81aaf7cbae13e1675f7d8d8045f5e191efac6a96 100644 (file)
@@ -116,6 +116,20 @@ extern "C" {
 /* Low-level functions (you probably don't need these)                */
 /**********************************************************************/
 
+/**
+ * fdt_offset_ptr - safely get a byte range within the device tree blob
+ * @fdt:       Pointer to the device tree blob
+ * @offset:    Offset within the blob to the desired byte range
+ * @checklen:  Required length of the byte range
+ *
+ * fdt_offset_ptr() returns a pointer to the byte range of length @checklen at
+ * the given @offset within the device tree blob, after verifying that the byte
+ * range fits entirely within the blob and does not overflow.
+ *
+ * returns:
+ *     pointer to the byte range, on success
+ *     NULL, if the requested range does not fit within the blob
+ */
 #ifndef SWIG /* This function is not useful in Python */
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
 #endif
@@ -124,6 +138,20 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
        return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
 }
 
+/**
+ * fdt_next_tag - get next tag in the device tree
+ * @fdt:       Pointer to the device tree blob
+ * @offset:    Offset within the blob to start searching
+ * @nextoffset:        Pointer to variable to store the offset of the next tag
+ *
+ * fdt_next_tag() returns the tag type of the next tag in the device tree
+ * blob starting from the given @offset. If @nextoffset is non-NULL, it will
+ * be set to the offset immediately following the tag.
+ *
+ * returns:
+ *     the tag type (FDT_BEGIN_NODE, FDT_END_NODE, FDT_PROP, FDT_NOP, FDT_END),
+ *     FDT_END, if offset is out of bounds
+ */
 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
 /*
@@ -334,6 +362,23 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
 /* Read-only functions                                                */
 /**********************************************************************/
 
+/**
+ * fdt_check_full - check device tree validity
+ * @fdt:       pointer to the device tree blob
+ * @bufsize:   size of the buffer containing the device tree
+ *
+ * fdt_check_full() checks that the given buffer contains a valid
+ * flattened device tree and that the tree structure is internally
+ * consistent. This is a more thorough check than fdt_check_header().
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_check_full(const void *fdt, size_t bufsize);
 
 /**
@@ -1540,10 +1585,90 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
  */
 int fdt_create(void *buf, int bufsize);
 
+/**
+ * fdt_resize - move and resize a device tree in sequential write state
+ * @fdt:       Pointer to the device tree to resize
+ * @buf:       Buffer where resized tree should be placed
+ * @bufsize:   Size of the buffer at @buf
+ *
+ * fdt_resize() moves the device tree blob from @fdt to @buf and
+ * resizes it to fit in the new buffer size.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if @bufsize is too small
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
 int fdt_resize(void *fdt, void *buf, int bufsize);
+
+/**
+ * fdt_add_reservemap_entry - add an entry to the memory reserve map
+ * @fdt:       Pointer to the device tree blob
+ * @addr:      Start address of the reserve map entry
+ * @size:      Size of the reserved region
+ *
+ * fdt_add_reservemap_entry() adds a memory reserve map entry to the
+ * device tree blob during the sequential write process. This function
+ * can only be called after fdt_create() and before fdt_finish_reservemap().
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if there is insufficient space in the blob
+ *     -FDT_ERR_BADSTATE, if not in the correct sequential write state
+ */
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
+
+/**
+ * fdt_finish_reservemap - complete the memory reserve map
+ * @fdt:       Pointer to the device tree blob
+ *
+ * fdt_finish_reservemap() completes the memory reserve map section
+ * of the device tree blob during sequential write. After calling this
+ * function, no more reserve map entries can be added and the blob
+ * moves to the structure creation phase.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADSTATE, if not in the correct sequential write state
+ */
 int fdt_finish_reservemap(void *fdt);
+
+/**
+ * fdt_begin_node - start creation of a new node
+ * @fdt:       Pointer to the device tree blob
+ * @name:      Name of the node to create
+ *
+ * fdt_begin_node() starts the creation of a new node with the given
+ * @name during sequential write. After calling this function, properties
+ * can be added with fdt_property() and subnodes can be created with
+ * additional fdt_begin_node() calls. The node must be completed with
+ * fdt_end_node().
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if there is insufficient space in the blob
+ *     -FDT_ERR_BADSTATE, if not in the correct sequential write state
+ */
 int fdt_begin_node(void *fdt, const char *name);
+
+/**
+ * fdt_property - add a property to the current node
+ * @fdt:       Pointer to the device tree blob
+ * @name:      Name of the property to add
+ * @val:       Pointer to the property value
+ * @len:       Length of the property value in bytes
+ *
+ * fdt_property() adds a property with the given @name and value to
+ * the current node during sequential write. This function can only
+ * be called between fdt_begin_node() and fdt_end_node().
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if there is insufficient space in the blob
+ *     -FDT_ERR_BADSTATE, if not currently within a node
+ */
 int fdt_property(void *fdt, const char *name, const void *val, int len);
 static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
 {
@@ -1580,15 +1705,94 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
 
 #define fdt_property_string(fdt, name, str) \
        fdt_property(fdt, name, str, strlen(str)+1)
+
+/**
+ * fdt_end_node - complete the current node
+ * @fdt:       Pointer to the device tree blob
+ *
+ * fdt_end_node() completes the current node during sequential write.  This
+ * function must be called to close each node started with
+ * fdt_begin_node(). After calling this function, no more properties or subnodes
+ * can be added to the node.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADSTATE, if not currently within a node
+ */
 int fdt_end_node(void *fdt);
+
+/**
+ * fdt_finish - complete device tree creation
+ * @fdt:       Pointer to the device tree blob
+ *
+ * fdt_finish() completes the device tree creation process started with
+ * fdt_create(). This function finalizes the device tree blob and makes it ready
+ * for use. After calling this function, the blob is complete and can be used
+ * with libfdt read-only and read-write functions, but not with sequential write
+ * functions.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADSTATE, if the sequential write process is incomplete
+ */
 int fdt_finish(void *fdt);
 
 /**********************************************************************/
 /* Read-write functions                                               */
 /**********************************************************************/
 
+/**
+ * fdt_create_empty_tree - create an empty device tree
+ * @buf:       Buffer where the empty tree should be created
+ * @bufsize:   Size of the buffer at @buf
+ *
+ * fdt_create_empty_tree() creates a minimal empty device tree blob
+ * in the given buffer. The tree contains only a root node with no
+ * properties or subnodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if @bufsize is too small for even an empty tree
+ */
 int fdt_create_empty_tree(void *buf, int bufsize);
+
+/**
+ * fdt_open_into - move a device tree into a new buffer and make editable
+ * @fdt:       Pointer to the device tree to move
+ * @buf:       Buffer where the editable tree should be placed
+ * @bufsize:   Size of the buffer at @buf
+ *
+ * fdt_open_into() moves and reorganizes the device tree blob from @fdt
+ * into @buf, converting it to a format suitable for read-write operations.
+ * The new buffer should allow space for modifications.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if @bufsize is too small
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_open_into(const void *fdt, void *buf, int bufsize);
+
+/**
+ * fdt_pack - pack a device tree blob
+ * @fdt:       Pointer to the device tree blob
+ *
+ * fdt_pack() reorganizes the device tree blob to eliminate any free space
+ * and pack it into the minimum possible size. This is useful after making
+ * modifications that might have left gaps in the blob.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT, standard meanings
+ */
 int fdt_pack(void *fdt);
 
 /**
@@ -2317,6 +2521,16 @@ int fdt_overlay_target_offset(const void *fdt, const void *fdto,
 /* Debugging / informational functions                                */
 /**********************************************************************/
 
+/**
+ * fdt_strerror - return string description of error code
+ * @errval:    Error code returned by a libfdt function
+ *
+ * fdt_strerror() returns a string description of the error code passed
+ * in @errval.
+ *
+ * returns:
+ *     pointer to a string describing the error code
+ */
 const char *fdt_strerror(int errval);
 
 #ifdef __cplusplus
index 73b6d40450aca51d94245be59490f6ee3454241d..5580b483e6a94c0c1083de44f6793847074cf092 100644 (file)
@@ -66,31 +66,4 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x)
 #undef CPU_TO_FDT16
 #undef EXTRACT_BYTE
 
-#ifdef __APPLE__
-#include <AvailabilityMacros.h>
-
-/* strnlen() is not available on Mac OS < 10.7 */
-# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
-                                         MAC_OS_X_VERSION_10_7)
-
-#define strnlen fdt_strnlen
-
-/*
- * fdt_strnlen: returns the length of a string or max_count - which ever is
- * smallest.
- * Input 1 string: the string whose size is to be determined
- * Input 2 max_count: the maximum value returned by this function
- * Output: length of the string or max_count (the smallest of the two)
- */
-static inline size_t fdt_strnlen(const char *string, size_t max_count)
-{
-    const char *p = memchr(string, 0, max_count);
-    return p ? p - string : max_count;
-}
-
-#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
-          MAC_OS_X_VERSION_10_7) */
-
-#endif /* __APPLE__ */
-
 #endif /* LIBFDT_ENV_H */
index b60b5456f596b8ad5d9daf9db4b182422f05549d..0e103cafa714cae4e50f58e76653d9b334d1e4c9 100644 (file)
 #define FDT_TAGALIGN(x)                (FDT_ALIGN((x), FDT_TAGSIZE))
 
 int32_t fdt_ro_probe_(const void *fdt);
-#define FDT_RO_PROBE(fdt)                                      \
-       {                                                       \
-               int32_t totalsize_;                             \
-               if ((totalsize_ = fdt_ro_probe_(fdt)) < 0)      \
-                       return totalsize_;                      \
+#define FDT_RO_PROBE(fdt)                                              \
+       {                                                               \
+               if (!can_assume(VALID_DTB)) {                           \
+                       int32_t totalsize_;                             \
+                       if ((totalsize_ = fdt_ro_probe_(fdt)) < 0)      \
+                               return totalsize_;                      \
+               }                                                       \
        }
 
 int fdt_check_node_offset_(const void *fdt, int offset);
@@ -92,7 +94,7 @@ static inline uint64_t fdt64_ld_(const fdt64_t *p)
  * signature or hash check before using libfdt.
  *
  * For situations where security is not a concern it may be safe to enable
- * ASSUME_SANE.
+ * ASSUME_PERFECT.
  */
 enum {
        /*
index d51d05830b181476ddbab878ef8b556230b58e2b..5d72abceb526611427cc9f6bcf34cc552ad0d0e7 100644 (file)
@@ -340,20 +340,73 @@ void append_to_property(struct node *node,
                        char *name, const void *data, int len,
                        enum markertype type)
 {
-       struct data d;
+       struct property *p;
+
+       p = get_property(node, name);
+       if (!p) {
+               p = build_property(name, empty_data, NULL);
+               add_property(node, p);
+       }
+
+       p->val = data_add_marker(p->val, type, name);
+       p->val = data_append_data(p->val, data, len);
+}
+
+static int append_unique_str_to_property(struct node *node,
+                                        char *name, const char *data, int len)
+{
        struct property *p;
 
        p = get_property(node, name);
        if (p) {
-               d = data_add_marker(p->val, type, name);
-               d = data_append_data(d, data, len);
-               p->val = d;
+               const char *s;
+
+               if (p->val.len && p->val.val[p->val.len - 1] != '\0')
+                       /* The current content doesn't look like a string */
+                       return -1;
+
+               for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) {
+                       if (strcmp(data, s) == 0)
+                               /* data already contained in node.name */
+                               return 0;
+               }
        } else {
-               d = data_add_marker(empty_data, type, name);
-               d = data_append_data(d, data, len);
-               p = build_property(name, d, NULL);
+               p = build_property(name, empty_data, NULL);
                add_property(node, p);
        }
+
+       p->val = data_add_marker(p->val, TYPE_STRING, name);
+       p->val = data_append_data(p->val, data, len);
+
+       return 0;
+}
+
+static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value)
+{
+       struct property *p;
+
+       p = get_property(node, name);
+       if (p) {
+               const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4;
+
+               if (p->val.len % 4 != 0)
+                       /* The current content doesn't look like a u32 array */
+                       return -1;
+
+               for (v = (const void *)p->val.val; v < val_end; v++) {
+                       if (*v == value)
+                               /* value already contained */
+                               return 0;
+               }
+       } else {
+               p = build_property(name, empty_data, NULL);
+               add_property(node, p);
+       }
+
+       p->val = data_add_marker(p->val, TYPE_UINT32, name);
+       p->val = data_append_data(p->val, &value, 4);
+
+       return 0;
 }
 
 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
@@ -918,11 +971,12 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node)
        return false;
 }
 
-static void add_fixup_entry(struct dt_info *dti, struct node *fn,
-                           struct node *node, struct property *prop,
-                           struct marker *m)
+static int add_fixup_entry(struct dt_info *dti, struct node *fn,
+                          struct node *node, struct property *prop,
+                          struct marker *m)
 {
        char *entry;
+       int ret;
 
        /* m->ref can only be a REF_PHANDLE, but check anyway */
        assert(m->type == REF_PHANDLE);
@@ -939,32 +993,39 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
 
        xasprintf(&entry, "%s:%s:%u",
                        node->fullpath, prop->name, m->offset);
-       append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
+       ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
 
        free(entry);
+
+       return ret;
 }
 
-static void generate_fixups_tree_internal(struct dt_info *dti,
-                                         struct node *fn,
-                                         struct node *node)
+static int generate_fixups_tree_internal(struct dt_info *dti,
+                                        struct node *fn,
+                                        struct node *node)
 {
        struct node *dt = dti->dt;
        struct node *c;
        struct property *prop;
        struct marker *m;
        struct node *refnode;
+       int ret = 0;
 
        for_each_property(node, prop) {
                m = prop->val.markers;
                for_each_marker_of_type(m, REF_PHANDLE) {
                        refnode = get_node_by_ref(dt, m->ref);
                        if (!refnode)
-                               add_fixup_entry(dti, fn, node, prop, m);
+                               if (add_fixup_entry(dti, fn, node, prop, m))
+                                       ret = -1;
                }
        }
 
        for_each_child(node, c)
-               generate_fixups_tree_internal(dti, fn, c);
+               if (generate_fixups_tree_internal(dti, fn, c))
+                       ret = -1;
+
+       return ret;
 }
 
 static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
@@ -989,7 +1050,7 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
        return false;
 }
 
-static void add_local_fixup_entry(struct dt_info *dti,
+static int add_local_fixup_entry(struct dt_info *dti,
                struct node *lfn, struct node *node,
                struct property *prop, struct marker *m,
                struct node *refnode)
@@ -1020,30 +1081,56 @@ static void add_local_fixup_entry(struct dt_info *dti,
        free(compp);
 
        value_32 = cpu_to_fdt32(m->offset);
-       append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
+       return append_unique_u32_to_property(wn, prop->name, value_32);
 }
 
-static void generate_local_fixups_tree_internal(struct dt_info *dti,
-                                               struct node *lfn,
-                                               struct node *node)
+static int generate_local_fixups_tree_internal(struct dt_info *dti,
+                                              struct node *lfn,
+                                              struct node *node)
 {
        struct node *dt = dti->dt;
        struct node *c;
        struct property *prop;
        struct marker *m;
        struct node *refnode;
+       int ret = 0;
 
        for_each_property(node, prop) {
                m = prop->val.markers;
                for_each_marker_of_type(m, REF_PHANDLE) {
                        refnode = get_node_by_ref(dt, m->ref);
                        if (refnode)
-                               add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
+                               if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
+                                       ret = -1;
                }
        }
 
        for_each_child(node, c)
-               generate_local_fixups_tree_internal(dti, lfn, c);
+               if (generate_local_fixups_tree_internal(dti, lfn, c))
+                       ret = -1;
+
+       return ret;
+}
+
+void generate_labels_from_tree(struct dt_info *dti, const char *name)
+{
+       struct node *an;
+       struct property *p;
+
+       an = get_subnode(dti->dt, name);
+       if (!an)
+               return;
+
+       for_each_property(an, p) {
+               struct node *labeled_node;
+
+               labeled_node = get_node_by_path(dti->dt, p->val.val);
+               if (labeled_node)
+                       add_label(&labeled_node->labels, p->name);
+               else if (quiet < 1)
+                       fprintf(stderr, "Warning: Path %s referenced in property %s/%s missing",
+                               p->val.val, name, p->name);
+       }
 }
 
 void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
@@ -1056,29 +1143,173 @@ void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
 
 void generate_fixups_tree(struct dt_info *dti, const char *name)
 {
-       struct node *n = get_subnode(dti->dt, name);
+       if (!any_fixup_tree(dti, dti->dt))
+               return;
+       if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
+               fprintf(stderr,
+                       "Warning: Preexisting data in %s malformed, some content could not be added.\n",
+                       name);
+}
 
-       /* Start with an empty __fixups__ node to not get duplicates */
-       if (n)
-               n->deleted = true;
+void fixup_phandles(struct dt_info *dti, const char *name)
+{
+       struct node *an;
+       struct property *fp;
 
-       if (!any_fixup_tree(dti, dti->dt))
+       an = get_subnode(dti->dt, name);
+       if (!an)
                return;
-       generate_fixups_tree_internal(dti,
-                                     build_and_name_child_node(dti->dt, name),
-                                     dti->dt);
+
+       for_each_property(an, fp) {
+               char *fnext = fp->val.val;
+               char *fv;
+               unsigned int fl;
+
+               while ((fl = fp->val.len - (fnext - fp->val.val))) {
+                       char *propname, *soffset;
+                       struct node *n;
+                       struct property *p;
+                       long offset;
+
+                       fv = fnext;
+                       fnext = memchr(fv, 0, fl);
+
+                       if (!fnext) {
+                               if (quiet < 1)
+                                       fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
+                                               fp->name);
+                               break;
+                       }
+                       fnext += 1;
+
+                       propname = memchr(fv, ':', fnext - 1 - fv);
+                       if (!propname) {
+                               if (quiet < 1)
+                                       fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
+                                               fp->name);
+                               continue;
+                       }
+                       propname++;
+
+                       soffset = memchr(propname, ':', fnext - 1 - propname);
+                       if (!soffset) {
+                               if (quiet < 1)
+                                       fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
+                                               fp->name);
+                               continue;
+                       }
+                       soffset++;
+
+                       /*
+                        * temporarily modify the property to not have to create
+                        * a copy for the node path.
+                        */
+                       *(propname - 1) = '\0';
+
+                       n = get_node_by_path(dti->dt, fv);
+                       if (!n && quiet < 1)
+                               fprintf(stderr, "Warning: Label %s references non-existing node %s\n",
+                                       fp->name, fv);
+
+                       *(propname - 1) = ':';
+
+                       if (!n)
+                               continue;
+
+                       /*
+                        * temporarily modify the property to not have to create
+                        * a copy for the property name.
+                        */
+                       *(soffset - 1) = '\0';
+
+                       p = get_property(n, propname);
+
+                       if (!p && quiet < 1)
+                               fprintf(stderr, "Warning: Label %s references non-existing property %s in node %s\n",
+                                       fp->name, n->fullpath, propname);
+
+                       *(soffset - 1) = ':';
+
+                       if (!p)
+                               continue;
+
+                       offset = strtol(soffset, NULL, 0);
+                       if (offset < 0 || offset + 4 > p->val.len) {
+                               if (quiet < 1)
+                                       fprintf(stderr,
+                                               "Warning: Label %s contains invalid offset for property %s in node %s\n",
+                                               fp->name, p->name, n->fullpath);
+                               continue;
+                       }
+
+                       property_add_marker(p, REF_PHANDLE, offset, fp->name);
+               }
+       }
 }
 
 void generate_local_fixups_tree(struct dt_info *dti, const char *name)
 {
-       struct node *n = get_subnode(dti->dt, name);
-
-       /* Start with an empty __local_fixups__ node to not get duplicates */
-       if (n)
-               n->deleted = true;
        if (!any_local_fixup_tree(dti, dti->dt))
                return;
-       generate_local_fixups_tree_internal(dti,
-                                           build_and_name_child_node(dti->dt, name),
-                                           dti->dt);
+       if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
+               fprintf(stderr,
+                       "Warning: Preexisting data in %s malformed, some content could not be added.\n",
+                       name);
+}
+
+static void local_fixup_phandles_node(struct dt_info *dti, struct node *lf, struct node *n)
+{
+       struct property *lfp;
+       struct node *lfsubnode;
+
+       for_each_property(lf, lfp) {
+               struct property *p = get_property(n, lfp->name);
+               fdt32_t *offsets = (fdt32_t *)lfp->val.val;
+               size_t i;
+
+               if (!p) {
+                       if (quiet < 1)
+                               fprintf(stderr, "Warning: Property %s in %s referenced in __local_fixups__ missing\n",
+                                       lfp->name, n->fullpath);
+                       continue;
+               }
+
+               /*
+                * Each property in the __local_fixups__ tree is a concatenation
+                * of offsets, so it must be a multiple of sizeof(fdt32_t).
+                */
+               if (lfp->val.len % sizeof(fdt32_t)) {
+                       if (quiet < 1)
+                               fprintf(stderr, "Warning: property %s in /__local_fixups__%s malformed\n",
+                                       lfp->name, n->fullpath);
+                       continue;
+               }
+
+               for (i = 0; i < lfp->val.len / sizeof(fdt32_t); i++)
+                       add_phandle_marker(dti, p, dtb_ld32(offsets + i));
+       }
+
+       for_each_child(lf, lfsubnode) {
+               struct node *subnode = get_subnode(n, lfsubnode->name);
+
+               if (!subnode) {
+                       if (quiet < 1)
+                               fprintf(stderr, "Warning: node %s/%s referenced in __local_fixups__ missing\n",
+                                       lfsubnode->name, n->fullpath);
+                       continue;
+               }
+
+               local_fixup_phandles_node(dti, lfsubnode, subnode);
+       }
+}
+
+void local_fixup_phandles(struct dt_info *dti, const char *name)
+{
+       struct node *an;
+
+       an = get_subnode(dti->dt, name);
+       if (!an)
+               return;
+
+       local_fixup_phandles_node(dti, an, dti->dt);
 }
index 5bb57bf6856c6ff6b8eb993aff5d216c63bf5ecb..fef892fb6fdd67e2e907c0a4cb4edc22d0bcf115 100644 (file)
@@ -88,6 +88,26 @@ static char *shorten_to_initial_path(char *fname)
        return NULL;
 }
 
+/**
+ * Returns true if the given path is an absolute one.
+ *
+ * On Windows, it either needs to begin with a forward slash or with a drive
+ * letter (e.g. "C:").
+ * On all other operating systems, it must begin with a forward slash to be
+ * considered an absolute path.
+ */
+static bool is_absolute_path(const char *path)
+{
+#ifdef WIN32
+       return (
+               path[0] == '/' ||
+               (((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':')
+       );
+#else
+       return (path[0] == '/');
+#endif
+}
+
 /**
  * Try to open a file in a given directory.
  *
@@ -103,7 +123,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
 {
        char *fullname;
 
-       if (!dirname || fname[0] == '/')
+       if (!dirname || is_absolute_path(fname))
                fullname = xstrdup(fname);
        else
                fullname = join_path(dirname, fname);
index d25f01fc693793a108f66c800683e726b436c6b1..bf648bf6c21a64a464f49ef0c53a8ba1245cd265 100644 (file)
@@ -173,23 +173,59 @@ static struct marker **add_marker(struct marker **mi,
        return &nm->next;
 }
 
-static void add_string_markers(struct property *prop)
+void property_add_marker(struct property *prop,
+                        enum markertype type, unsigned int offset, char *ref)
 {
-       int l, len = prop->val.len;
-       const char *p = prop->val.val;
+       add_marker(&prop->val.markers, type, offset, ref);
+}
+
+static void add_string_markers(struct property *prop, unsigned int offset, int len)
+{
+       int l;
+       const char *p = prop->val.val + offset;
        struct marker **mi = &prop->val.markers;
 
        for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1)
-               mi = add_marker(mi, TYPE_STRING, l, NULL);
+               mi = add_marker(mi, TYPE_STRING, offset + l, NULL);
+}
+
+void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset)
+{
+       cell_t phandle;
+       struct node *refn;
+       char *ref;
+
+       if (prop->val.len < offset + 4) {
+               if (quiet < 1)
+                       fprintf(stderr,
+                               "Warning: property %s too short to contain a phandle at offset %u\n",
+                               prop->name, offset);
+               return;
+       }
+
+       phandle = dtb_ld32(prop->val.val + offset);
+       refn = get_node_by_phandle(dti->dt, phandle);
+
+       if (!refn) {
+               if (quiet < 1)
+                       fprintf(stderr,
+                               "Warning: node referenced by phandle 0x%x in property %s not found\n",
+                               phandle, prop->name);
+               return;
+       }
+
+       if (refn->labels)
+               ref = refn->labels->label;
+       else
+               ref = refn->fullpath;
+
+       add_marker(&prop->val.markers, REF_PHANDLE, offset, ref);
 }
 
-static enum markertype guess_value_type(struct property *prop)
+static enum markertype guess_value_type(struct property *prop, unsigned int offset, int len)
 {
-       int len = prop->val.len;
-       const char *p = prop->val.val;
-       struct marker *m = prop->val.markers;
+       const char *p = prop->val.val + offset;
        int nnotstring = 0, nnul = 0;
-       int nnotstringlbl = 0, nnotcelllbl = 0;
        int i;
 
        for (i = 0; i < len; i++) {
@@ -199,30 +235,49 @@ static enum markertype guess_value_type(struct property *prop)
                        nnul++;
        }
 
-       for_each_marker_of_type(m, LABEL) {
-               if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
-                       nnotstringlbl++;
-               if ((m->offset % sizeof(cell_t)) != 0)
-                       nnotcelllbl++;
-       }
-
-       if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
-           && (nnotstringlbl == 0)) {
+       if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= len - nnul)) {
                if (nnul > 1)
-                       add_string_markers(prop);
+                       add_string_markers(prop, offset, len);
                return TYPE_STRING;
-       } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
+       } else if ((len % sizeof(cell_t)) == 0) {
                return TYPE_UINT32;
        }
 
        return TYPE_UINT8;
 }
 
+static void guess_type_markers(struct property *prop)
+{
+       struct marker **m = &prop->val.markers;
+       unsigned int offset = 0;
+
+       for (m = &prop->val.markers; *m; m = &((*m)->next)) {
+               if (is_type_marker((*m)->type))
+                       /* assume the whole property is already marked */
+                       return;
+
+               if ((*m)->offset > offset) {
+                       m = add_marker(m, guess_value_type(prop, offset, (*m)->offset - offset),
+                                      offset, NULL);
+
+                       offset = (*m)->offset;
+               }
+
+               if ((*m)->type == REF_PHANDLE) {
+                       m = add_marker(m, TYPE_UINT32, offset, NULL);
+                       offset += 4;
+               }
+       }
+
+       if (offset < prop->val.len)
+               add_marker(m, guess_value_type(prop, offset, prop->val.len - offset),
+                          offset, NULL);
+}
+
 static void write_propval(FILE *f, struct property *prop)
 {
        size_t len = prop->val.len;
-       struct marker *m = prop->val.markers;
-       struct marker dummy_marker;
+       struct marker *m;
        enum markertype emit_type = TYPE_NONE;
        char *srcstr;
 
@@ -241,14 +296,8 @@ static void write_propval(FILE *f, struct property *prop)
 
        fprintf(f, " =");
 
-       if (!next_type_marker(m)) {
-               /* data type information missing, need to guess */
-               dummy_marker.type = guess_value_type(prop);
-               dummy_marker.next = prop->val.markers;
-               dummy_marker.offset = 0;
-               dummy_marker.ref = NULL;
-               m = &dummy_marker;
-       }
+       guess_type_markers(prop);
+       m = prop->val.markers;
 
        for_each_marker(m) {
                size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
@@ -369,7 +418,10 @@ void dt_to_source(FILE *f, struct dt_info *dti)
 {
        struct reserve_info *re;
 
-       fprintf(f, "/dts-v1/;\n\n");
+       fprintf(f, "/dts-v1/;\n");
+       if (dti->dtsflags & DTSF_PLUGIN)
+               fprintf(f, "/plugin/;\n");
+       fprintf(f, "\n");
 
        for (re = dti->reservelist; re; re = re->next) {
                struct label *l;
index 226c48bf75dc03355540d60391159aef394ffe5d..5730bf457b3308301453879b3fac15bc84c70110 100644 (file)
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.7.2-g52f07dcc"
+#define DTC_VERSION "DTC 1.7.2-ga26ef640"