Fix fdt_find_node(). We should make sure we match the full name when
authorkettenis <kettenis@openbsd.org>
Wed, 27 Mar 2024 23:05:27 +0000 (23:05 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 27 Mar 2024 23:05:27 +0000 (23:05 +0000)
matching path components (but we do allow matches with the @unit bit).

This fixes a problem on the Milk-V Pioneer where /soc/serial@123456
accidentally match a /socket0-clocks node and we would fail to find the
serial console.

ok miod@

sys/dev/ofw/fdt.c

index 42edb46..dfc00a3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fdt.c,v 1.34 2023/04/26 14:39:42 kettenis Exp $       */
+/*     $OpenBSD: fdt.c,v 1.35 2024/03/27 23:05:27 kettenis Exp $       */
 
 /*
  * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
@@ -501,6 +501,7 @@ fdt_find_node(char *name)
        while (*p) {
                void *child;
                const char *q;
+               const char *s;
 
                while (*p == '/')
                        p++;
@@ -510,18 +511,33 @@ fdt_find_node(char *name)
                if (q == NULL)
                        q = p + strlen(p);
 
+               /* Check for a complete match. */
                for (child = fdt_child_node(node); child;
                     child = fdt_next_node(child)) {
-                       if (strncmp(p, fdt_node_name(child), q - p) == 0) {
-                               node = child;
+                       s = fdt_node_name(child);
+                       if (strncmp(p, s, q - p) == 0 && s[q - p] == '\0')
                                break;
-                       }
+               }
+               if (child) {
+                       node = child;
+                       p = q;
+                       continue;
                }
 
-               if (child == NULL)
-                       return NULL; /* No match found. */
+               /* Check for a match without the unit name. */
+               for (child = fdt_child_node(node); child;
+                    child = fdt_next_node(child)) {
+                       s = fdt_node_name(child);
+                       if (strncmp(p, s, q - p) == 0 && s[q - p] == '@')
+                               break;
+               }
+               if (child) {
+                       node = child;
+                       p = q;
+                       continue;
+               }
 
-               p = q;
+               return NULL;    /* No match found. */
        }
 
        return node;