]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dt] Locate parent node at point of use in dt_ioremap()
authorMichael Brown <mcb30@ipxe.org>
Fri, 30 May 2025 15:39:10 +0000 (16:39 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 30 May 2025 15:39:10 +0000 (16:39 +0100)
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 <mcb30@ipxe.org>
src/drivers/bus/devtree.c
src/include/ipxe/devtree.h

index 55f68ee33cfdb12a034e392dfb0f97d1286c6b6c..796fe56a06bcd0613936d1b5cd374bd5f0723a1e 100644 (file)
@@ -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, &regs );
+
        /* Read address */
-       if ( ( rc = fdt_reg_address ( &sysfdt, offset, regs, index,
+       if ( ( rc = fdt_reg_address ( &sysfdt, offset, &regs, 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, &regs, 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;
index 6e9286af44d33a76e5bd5277a6bf2888658dc423..46d8b5d864d914e2a94d403c81c3ba4f8955cc43 100644 (file)
@@ -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 */