From: Mehmet Fide <[email protected]>

fdtdec_get_alias_seq() and fdtdec_get_alias_highest_id() compare the
alias name with the stem by strncmp() over the length of the stem, so
every alias that starts with the stem counts. On a Colibri VF50 the
aliases usbphy0 and usbphy1 matched the "usb" stem, the two USB
controllers were given the sequence numbers 2 and 3, and ehci-vf
indexed its two-entry tables with them. The live tree disagrees: there
of_alias_scan() splits an alias into the stem and the number and
of_alias_get_id() compares the stem exactly.

Match an alias only when the stem is followed by its number, as the
live tree does. A test covers both lookups with the sandbox aliases,
where "test" is a prefix of testbus3 and of the testfdt aliases.

Signed-off-by: Mehmet Fide <[email protected]>
---

Notes:
    Changes in v6:
    - none
    
    Changes in v5:
    - new patch, from the review of the alias lookup in v4: the live and the
      flat implementation disagreed on a stem that is a prefix of an alias
    - the test calls fdtdec directly, which checkpatch warns about; the two
      lookups under test have no livetree form

 lib/fdtdec.c     | 43 ++++++++++++++++++++++++++++++-------------
 test/dm/fdtdec.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index d25535bf36c..5fe7e85a943 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -508,10 +508,29 @@ int fdtdec_add_aliases_for_id(const void *blob, const 
char *name,
        return num_found;
 }
 
+/**
+ * alias_seq_of() - get the number an alias gives a stem
+ *
+ * @name: Alias name, e.g. "serial2"
+ * @base: Stem to match, e.g. "serial"
+ * Return: the number that follows the stem, -1 if @name is not @base
+ * followed by a number (usbphy0 is not a "usb" alias)
+ */
+static int alias_seq_of(const char *name, const char *base)
+{
+       int base_len = strlen(base);
+       const char *num = name + base_len;
+
+       if (strncmp(name, base, base_len) || !*num ||
+           strspn(num, "0123456789") != strlen(num))
+               return -1;
+
+       return dectoul(num, NULL);
+}
+
 int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
                         int *seqp)
 {
-       int base_len = strlen(base);
        const char *find_name;
        int find_namelen;
        int prop_offset;
@@ -531,8 +550,11 @@ int fdtdec_get_alias_seq(const void *blob, const char 
*base, int offset,
 
                prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
                debug("   - %s, %s\n", name, prop);
-               if (len < find_namelen || *prop != '/' || prop[len - 1] ||
-                   strncmp(name, base, base_len))
+               if (len < find_namelen || *prop != '/' || prop[len - 1])
+                       continue;
+
+               val = alias_seq_of(name, base);
+               if (val < 0)
                        continue;
 
                slash = strrchr(prop, '/');
@@ -549,12 +571,9 @@ int fdtdec_get_alias_seq(const void *blob, const char 
*base, int offset,
                                continue;
                }
 
-               val = trailing_strtol(name);
-               if (val != -1) {
-                       *seqp = val;
-                       debug("Found seq %d\n", *seqp);
-                       return 0;
-               }
+               *seqp = val;
+               debug("Found seq %d\n", *seqp);
+               return 0;
        }
 
        debug("Not found\n");
@@ -563,7 +582,6 @@ int fdtdec_get_alias_seq(const void *blob, const char 
*base, int offset,
 
 int fdtdec_get_alias_highest_id(const void *blob, const char *base)
 {
-       int base_len = strlen(base);
        int prop_offset;
        int aliases;
        int max = -1;
@@ -580,11 +598,10 @@ int fdtdec_get_alias_highest_id(const void *blob, const 
char *base)
 
                prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
                debug("   - %s, %s\n", name, prop);
-               if (*prop != '/' || prop[len - 1] ||
-                   strncmp(name, base, base_len))
+               if (*prop != '/' || prop[len - 1])
                        continue;
 
-               val = trailing_strtol(name);
+               val = alias_seq_of(name, base);
                if (val > max) {
                        debug("Found seq %d\n", val);
                        max = val;
diff --git a/test/dm/fdtdec.c b/test/dm/fdtdec.c
index 495f57234a4..075f7e5471f 100644
--- a/test/dm/fdtdec.c
+++ b/test/dm/fdtdec.c
@@ -8,6 +8,7 @@
 #include <dm/of_extra.h>
 #include <dm/test.h>
 #include <fdt_support.h>
+#include <fdtdec.h>
 #include <mapmem.h>
 #include <smbios.h>
 #include <test/ut.h>
@@ -188,3 +189,37 @@ static int dm_test_fdt_chosen_smbios(struct 
unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_fdt_chosen_smbios, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
+/* test fdtdec_get_alias_seq() and fdtdec_get_alias_highest_id() */
+static int dm_test_fdtdec_alias_seq(struct unit_test_state *uts)
+{
+       const void *blob = gd->fdt_blob;
+       int seq;
+
+       ut_assertok(fdtdec_get_alias_seq(blob, "testfdt",
+                                        fdt_path_offset(blob,
+                                                        "/some-bus/c-test@1"),
+                                        &seq));
+       ut_asserteq(12, seq);
+       ut_assertok(fdtdec_get_alias_seq(blob, "testbus",
+                                        fdt_path_offset(blob, "/some-bus"),
+                                        &seq));
+       ut_asserteq(3, seq);
+
+       /* the stem must be followed by the number: testbus3 is no "test" */
+       ut_asserteq(-ENOENT,
+                   fdtdec_get_alias_seq(blob, "test",
+                                        fdt_path_offset(blob, "/some-bus"),
+                                        &seq));
+       ut_asserteq(-ENOENT,
+                   fdtdec_get_alias_seq(blob, "spi",
+                                        fdt_path_offset(blob, "/i2c@0"),
+                                        &seq));
+
+       ut_asserteq(12, fdtdec_get_alias_highest_id(blob, "testfdt"));
+       ut_asserteq(3, fdtdec_get_alias_highest_id(blob, "testbus"));
+       ut_asserteq(-1, fdtdec_get_alias_highest_id(blob, "test"));
+
+       return 0;
+}
+DM_TEST(dm_test_fdtdec_alias_seq, UTF_SCAN_PDATA | UTF_SCAN_FDT);

base-commit: 0a55b098d6f5f6bafa84fc2f18b433dd167bf729
-- 
2.55.0

Reply via email to