Browse Source

[fdt] Provide ability to locate the parent device node

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/1473/merge
Michael Brown 1 week ago
parent
commit
1762568ec5
  1. 96
      src/core/fdt.c
  2. 2
      src/include/ipxe/fdt.h
  3. 12
      src/tests/fdt_test.c

96
src/core/fdt.c

@ -181,7 +181,7 @@ static int fdt_next ( struct fdt *fdt, struct fdt_descriptor *desc ) {
* @ret rc Return status code
*/
static int fdt_enter ( struct fdt *fdt, unsigned int offset,
struct fdt_descriptor *desc ) {
struct fdt_descriptor *desc ) {
int rc;
/* Find begin node token */
@ -212,6 +212,100 @@ static int fdt_enter ( struct fdt *fdt, unsigned int offset,
}
}
/**
* Find node relative depth
*
* @v fdt Device tree
* @v offset Starting node offset
* @v target Target node offset
* @ret depth Depth, or negative error
*/
static int fdt_depth ( struct fdt *fdt, unsigned int offset,
unsigned int target ) {
struct fdt_descriptor desc;
int depth;
int rc;
/* Enter node */
if ( ( rc = fdt_enter ( fdt, offset, &desc ) ) != 0 )
return rc;
/* Find target node */
for ( depth = 0 ; depth >= 0 ; depth += desc.depth ) {
/* Describe token */
if ( ( rc = fdt_next ( fdt, &desc ) ) != 0 ) {
DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
offset, strerror ( rc ) );
return rc;
}
/* Check for target node */
if ( desc.offset == target ) {
DBGC2 ( fdt, "FDT +%#04x has descendant node +%#04x "
"at depth +%d\n", offset, target, depth );
return depth;
}
}
DBGC ( fdt, "FDT +#%04x has no descendant node +%#04x\n",
offset, target );
return -ENOENT;
}
/**
* Find parent node
*
* @v fdt Device tree
* @v offset Starting node offset
* @v parent Parent node offset to fill in
* @ret rc Return status code
*/
int fdt_parent ( struct fdt *fdt, unsigned int offset, unsigned int *parent ) {
struct fdt_descriptor desc;
int pdepth;
int depth;
int rc;
/* Find depth from root of tree */
depth = fdt_depth ( fdt, 0, offset );
if ( depth < 0 ) {
rc = depth;
return rc;
}
pdepth = ( depth - 1 );
/* Enter root node */
if ( ( rc = fdt_enter ( fdt, 0, &desc ) ) != 0 )
return rc;
*parent = desc.offset;
/* Find parent node */
for ( depth = 0 ; depth >= 0 ; depth += desc.depth ) {
/* Describe token */
if ( ( rc = fdt_next ( fdt, &desc ) ) != 0 ) {
DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
offset, strerror ( rc ) );
return rc;
}
/* Record possible parent node */
if ( ( depth == pdepth ) && desc.name && ( ! desc.data ) )
*parent = desc.offset;
/* Check for target node */
if ( desc.offset == offset ) {
DBGC2 ( fdt, "FDT +%#04x has parent node at +%#04x\n",
offset, *parent );
return 0;
}
}
DBGC ( fdt, "FDT +#%04x has no parent node\n", offset );
return -ENOENT;
}
/**
* Find child node
*

2
src/include/ipxe/fdt.h

@ -170,6 +170,8 @@ fdt_reservations ( struct fdt *fdt ) {
extern int fdt_describe ( struct fdt *fdt, unsigned int offset,
struct fdt_descriptor *desc );
extern int fdt_parent ( struct fdt *fdt, unsigned int offset,
unsigned int *parent );
extern int fdt_path ( struct fdt *fdt, const char *path,
unsigned int *offset );
extern int fdt_alias ( struct fdt *fdt, const char *name,

12
src/tests/fdt_test.c

@ -263,6 +263,18 @@ static void fdt_test_exec ( void ) {
ok ( strcmp ( desc.data, "memory" ) == 0 );
ok ( desc.depth == 0 );
/* Verify parent lookup */
ok ( fdt_path ( &fdt, "/soc/ethernet@10090000/ethernet-phy@0",
&offset ) == 0 );
ok ( fdt_parent ( &fdt, offset, &offset ) == 0 );
ok ( fdt_describe ( &fdt, offset, &desc ) == 0 );
ok ( strcmp ( desc.name, "ethernet@10090000" ) == 0 );
ok ( fdt_parent ( &fdt, offset, &offset ) == 0 );
ok ( fdt_describe ( &fdt, offset, &desc ) == 0 );
ok ( strcmp ( desc.name, "soc" ) == 0 );
ok ( fdt_parent ( &fdt, offset, &offset ) == 0 );
ok ( offset == 0 );
/* Verify device tree creation */
image = image_memory ( "test.dtb", sifive_u, sizeof ( sifive_u ) );
ok ( image != NULL );

Loading…
Cancel
Save