]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fdt] Allow paths and aliases to be terminated with separator characters
authorMichael Brown <mcb30@ipxe.org>
Wed, 11 Jun 2025 15:08:42 +0000 (16:08 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 11 Jun 2025 15:18:36 +0000 (16:18 +0100)
Non-permitted name characters such as a colon are sometimes used to
separate alias names or paths from additional metadata, such as the
baud rate for a UART in the "/chosen/stdout-path" property.

Support the use of such alias names and paths by allowing any
character not permitted in a property name to terminate a property or
node name match.  (This is a very relaxed matching rule that will
produce false positive matches on invalid input, but this is unlikely
to cause problems in practice.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/fdt.c
src/tests/fdt_test.c

index b2ee0133b9a247f77135fe016b2a2bd694170fd5..149348199fbd8c9e49873b26020dc3aee02bddfa 100644 (file)
@@ -24,6 +24,7 @@
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <string.h>
+#include <ctype.h>
 #include <errno.h>
 #include <assert.h>
 #include <byteswap.h>
@@ -50,6 +51,33 @@ struct image_tag fdt_image __image_tag = {
 /** Amount of free space to add whenever we have to reallocate a tree */
 #define FDT_INSERT_PAD 1024
 
+/**
+ * Check if character is permitted in a name
+ *
+ * @v ch               Character
+ * @ret is_permitted   Character is permitted in a name
+ */
+static int fdt_permitted ( char ch ) {
+       static const char permitted[] = ",._+?#-";
+
+       return ( isalnum ( ch ) || strchr ( permitted, ch ) );
+}
+
+/**
+ * Compare node name
+ *
+ * @v desc             Token descriptor
+ * @v name             Name (terminated by NUL or any non-permitted character)
+ * @ret is_match       Name matches token descriptor
+ */
+static int fdt_match ( const struct fdt_descriptor *desc, const char *name ) {
+       size_t len = strlen ( desc->name );
+
+       /* Check name and terminator */
+       return ( ( memcmp ( desc->name, name, len ) == 0 ) &&
+                ( ! ( name[len] && fdt_permitted ( name[len] ) ) ) );
+}
+
 /**
  * Describe device tree token
  *
@@ -318,15 +346,9 @@ int fdt_parent ( struct fdt *fdt, unsigned int offset, unsigned int *parent ) {
 static int fdt_child ( struct fdt *fdt, unsigned int offset, const char *name,
                       unsigned int *child ) {
        struct fdt_descriptor desc;
-       const char *sep;
-       size_t name_len;
        int depth;
        int rc;
 
-       /* Determine length of name (may be terminated with NUL or '/') */
-       sep = strchr ( name, '/' );
-       name_len = ( sep ? ( ( size_t ) ( sep - name ) ) : strlen ( name ) );
-
        /* Enter node */
        if ( ( rc = fdt_enter ( fdt, offset, &desc ) ) != 0 )
                return rc;
@@ -346,8 +368,7 @@ static int fdt_child ( struct fdt *fdt, unsigned int offset, const char *name,
                        DBGC2 ( fdt, "FDT +%#04x has child node \"%s\" at "
                                "+%#04x\n", offset, desc.name, desc.offset );
                        assert ( desc.depth > 0 );
-                       if ( ( strlen ( desc.name ) == name_len ) &&
-                            ( memcmp ( name, desc.name, name_len ) == 0 ) ) {
+                       if ( fdt_match ( &desc, name ) ) {
                                *child = desc.offset;
                                return 0;
                        }
@@ -495,7 +516,7 @@ static int fdt_property ( struct fdt *fdt, unsigned int offset,
                                "+%#04x len %#zx\n", offset, desc->name,
                                desc->offset, desc->len );
                        assert ( desc->depth == 0 );
-                       if ( strcmp ( name, desc->name ) == 0 ) {
+                       if ( fdt_match ( desc, name ) ) {
                                DBGC2_HDA ( fdt, 0, desc->data, desc->len );
                                return 0;
                        }
index 408f77c6d65353a4b67e28fb1ff01a0d4dadac9f..0be0acdbc0afeff2fe9c664e3fb7123837a3822c 100644 (file)
@@ -213,6 +213,10 @@ static void fdt_test_exec ( void ) {
        ok ( strcmp ( string, "sifive,uart0" ) == 0 );
        ok ( fdt_path ( &fdt, "/nonexistent", &offset ) != 0 );
        ok ( fdt_path ( &fdt, "/cpus/nonexistent", &offset ) != 0 );
+       ok ( fdt_path ( &fdt, "/soc/serial@10010000:115200n8",
+                       &offset ) == 0 );
+       ok ( ( string = fdt_string ( &fdt, offset, "compatible" ) ) != NULL );
+       ok ( strcmp ( string, "sifive,uart0" ) == 0 );
 
        /* Verify 64-bit integer properties */
        ok ( fdt_u64 ( &fdt, 0, "#address-cells", &u64 ) == 0 );
@@ -249,6 +253,9 @@ static void fdt_test_exec ( void ) {
        ok ( ( string = fdt_string ( &fdt, offset, "compatible" ) ) != NULL );
        ok ( strcmp ( string, "sifive,uart0" ) == 0 );
        ok ( fdt_alias ( &fdt, "nonexistent0", &offset ) != 0 );
+       ok ( fdt_alias ( &fdt, "ethernet0:params", &offset ) == 0 );
+       ok ( ( string = fdt_string ( &fdt, offset, "phy-mode" ) ) != NULL );
+       ok ( strcmp ( string, "gmii" ) == 0 );
 
        /* Verify node description */
        ok ( fdt_path ( &fdt, "/memory@80000000", &offset ) == 0 );