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
