mirror of
https://github.com/ipxe/ipxe
synced 2026-01-22 20:19:08 +03:00
[fdt] Provide ability to locate the parent device node
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -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
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user