diff --git a/src/core/fdt.c b/src/core/fdt.c index b2ee0133b..149348199 100644 --- a/src/core/fdt.c +++ b/src/core/fdt.c @@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include +#include #include #include #include @@ -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; } diff --git a/src/tests/fdt_test.c b/src/tests/fdt_test.c index 408f77c6d..0be0acdbc 100644 --- a/src/tests/fdt_test.c +++ b/src/tests/fdt_test.c @@ -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 );