mirror of
https://github.com/ipxe/ipxe
synced 2026-01-22 12:08:58 +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
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int fdt_enter ( struct fdt *fdt, unsigned int offset,
|
static int fdt_enter ( struct fdt *fdt, unsigned int offset,
|
||||||
struct fdt_descriptor *desc ) {
|
struct fdt_descriptor *desc ) {
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Find begin node token */
|
/* 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
|
* Find child node
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ fdt_reservations ( struct fdt *fdt ) {
|
|||||||
|
|
||||||
extern int fdt_describe ( struct fdt *fdt, unsigned int offset,
|
extern int fdt_describe ( struct fdt *fdt, unsigned int offset,
|
||||||
struct fdt_descriptor *desc );
|
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,
|
extern int fdt_path ( struct fdt *fdt, const char *path,
|
||||||
unsigned int *offset );
|
unsigned int *offset );
|
||||||
extern int fdt_alias ( struct fdt *fdt, const char *name,
|
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 ( strcmp ( desc.data, "memory" ) == 0 );
|
||||||
ok ( desc.depth == 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 */
|
/* Verify device tree creation */
|
||||||
image = image_memory ( "test.dtb", sifive_u, sizeof ( sifive_u ) );
|
image = image_memory ( "test.dtb", sifive_u, sizeof ( sifive_u ) );
|
||||||
ok ( image != NULL );
|
ok ( image != NULL );
|
||||||
|
|||||||
Reference in New Issue
Block a user