From: Michael Brown Date: Fri, 30 May 2025 15:39:10 +0000 (+0100) Subject: [dt] Locate parent node at point of use in dt_ioremap() X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=bb2011241fcf15de4edd962fe9656e513ad19174;p=thirdparty%2Fipxe.git [dt] Locate parent node at point of use in dt_ioremap() We currently rely on the recursive nature of devicetree bus probing to obtain the region cell size specification from the parent device. This blocks the possibility of creating a standalone console device based on /chosen/stdout-path before probing the whole bus. Fix by using fdt_parent() to locate the parent device at the point of use within dt_ioremap(). Signed-off-by: Michael Brown --- diff --git a/src/drivers/bus/devtree.c b/src/drivers/bus/devtree.c index 55f68ee33..796fe56a0 100644 --- a/src/drivers/bus/devtree.c +++ b/src/drivers/bus/devtree.c @@ -54,16 +54,25 @@ static void dt_remove_children ( struct dt_device *parent ); */ void * dt_ioremap ( struct dt_device *dt, unsigned int offset, unsigned int index, size_t len ) { - struct dt_device *parent = - container_of ( dt->dev.parent, struct dt_device, dev ); - struct fdt_reg_cells *regs = &parent->regs; + struct fdt_reg_cells regs; + unsigned int parent; uint64_t address; uint64_t size; void *io_addr; int rc; + /* Get parent node */ + if ( ( rc = fdt_parent ( &sysfdt, offset, &parent ) ) != 0 ) { + DBGC ( dt, "DT %s could not locate parent: %s\n", + dt->path, strerror ( rc ) ); + return NULL; + } + + /* Read #address-cells and #size-cells, if present */ + fdt_reg_cells ( &sysfdt, parent, ®s ); + /* Read address */ - if ( ( rc = fdt_reg_address ( &sysfdt, offset, regs, index, + if ( ( rc = fdt_reg_address ( &sysfdt, offset, ®s, index, &address ) ) != 0 ) { DBGC ( dt, "DT %s could not read region %d address: %s\n", dt->path, index, strerror ( rc ) ); @@ -72,8 +81,8 @@ void * dt_ioremap ( struct dt_device *dt, unsigned int offset, /* Read size (or assume sufficient, if tree specifies no sizes) */ size = len; - if ( regs->size_cells && - ( ( rc = fdt_reg_size ( &sysfdt, offset, regs, index, + if ( regs.size_cells && + ( ( rc = fdt_reg_size ( &sysfdt, offset, ®s, index, &size ) ) != 0 ) ) { DBGC ( dt, "DT %s could not read region %d size: %s\n", dt->path, index, strerror ( rc ) ); @@ -222,9 +231,6 @@ static int dt_probe_node ( struct dt_device *parent, unsigned int offset, INIT_LIST_HEAD ( &dt->dev.children ); list_add_tail ( &dt->dev.siblings, &dt->dev.parent->children ); - /* Read #address-cells and #size-cells, if present */ - fdt_reg_cells ( &sysfdt, offset, &dt->regs ); - /* Probe device */ if ( ( rc = dt_probe ( dt, offset ) ) != 0 ) goto err_probe; diff --git a/src/include/ipxe/devtree.h b/src/include/ipxe/devtree.h index 6e9286af4..46d8b5d86 100644 --- a/src/include/ipxe/devtree.h +++ b/src/include/ipxe/devtree.h @@ -25,9 +25,6 @@ struct dt_device { struct dt_driver *driver; /** Driver-private data */ void *priv; - - /** Register cell size specification */ - struct fdt_reg_cells regs; }; /** A devicetree driver */