imagemap_create() names every device it binds by index "imagemap", so
two mappings taken on one block device appear as two identically named
children and the device tree does not say which partition each covers.
The name also comes straight from the caller, whose string has to outlive
the device for the driver-model pointer to stay valid.

Derive the name from the partition, by name where one was given and by
index otherwise, and hand driver model an allocated copy it releases on
unbind.

Signed-off-by: Daniel Golle <[email protected]>
---
 boot/imagemap.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/boot/imagemap.c b/boot/imagemap.c
index e7222d58c93..57a078fbc55 100644
--- a/boot/imagemap.c
+++ b/boot/imagemap.c
@@ -11,6 +11,7 @@
 #include <dm.h>
 #include <imagemap.h>
 #include <lmb.h>
+#include <malloc.h>
 #include <mapmem.h>
 #include <memalign.h>
 #include <part.h>
@@ -441,6 +442,8 @@ int imagemap_create(struct udevice *dev, const char *name,
        struct imagemap_plat *plat;
        struct disk_partition info;
        struct udevice *imdev;
+       char buf[32];
+       char *devname;
        int ret;
 
        if (name && *name)
@@ -450,10 +453,26 @@ int imagemap_create(struct udevice *dev, const char *name,
        if (ret < 0)
                return ret;
 
-       ret = device_bind_driver(desc->bdev, "imagemap",
-                                name && *name ? name : "imagemap", &imdev);
-       if (ret)
+       /*
+        * Name the device after the partition it covers, so that two mappings
+        * on one block device stay distinct in the device tree.
+        */
+       if (name && *name)
+               snprintf(buf, sizeof(buf), "%s", name);
+       else
+               snprintf(buf, sizeof(buf), "imagemap%d", part);
+
+       /* device_bind_driver() keeps the pointer, so hand it one DM can own */
+       devname = strdup(buf);
+       if (!devname)
+               return -ENOMEM;
+
+       ret = device_bind_driver(desc->bdev, "imagemap", devname, &imdev);
+       if (ret) {
+               free(devname);
                return ret;
+       }
+       device_set_name_alloced(imdev);
 
        plat = dev_get_plat(imdev);
        plat->part_start = info.start;
-- 
2.56.0

Reply via email to