mirror of
https://github.com/ipxe/ipxe
synced 2025-12-08 10:20:24 +03:00
[fdt] Allow paths and aliases to be terminated with separator characters
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user