Up to now when devices became available after executing the UEFI
sub-system initialization where not available for EFI applications.

With the patch block devices are added to the UEFI object list whenever
they are probed.

Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de>
---
 drivers/core/device.c               |  7 +++
 include/efi_loader.h                |  6 +++
 lib/efi_driver/Makefile             |  1 +
 lib/efi_driver/efi_dm_integration.c | 36 +++++++++++++++
 lib/efi_loader/efi_disk.c           | 72 +++++++++++++++++------------
 5 files changed, 93 insertions(+), 29 deletions(-)
 create mode 100644 lib/efi_driver/efi_dm_integration.c

diff --git a/drivers/core/device.c b/drivers/core/device.c
index cb960f8ec4..7355a5c2a9 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -14,6 +14,7 @@
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <clk.h>
+#include <efi_loader.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
 #include <malloc.h>
@@ -579,6 +580,12 @@ int device_probe(struct udevice *dev)
        if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL)
                pinctrl_select_state(dev, "default");

+       if (CONFIG_IS_ENABLED(EFI_LOADER)) {
+               ret = efi_post_probe_device(dev);
+               if (ret)
+                       goto fail_uclass;
+       }
+
        return 0;
 fail_uclass:
        if (device_remove(dev, DM_REMOVE_NORMAL)) {
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 0a9c82a257..78dd687913 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -17,6 +17,7 @@
 #include <pe.h>

 struct blk_desc;
+struct udevice;

 static inline int guidcmp(const void *g1, const void *g2)
 {
@@ -28,6 +29,9 @@ static inline void *guidcpy(void *dst, const void *src)
        return memcpy(dst, src, sizeof(efi_guid_t));
 }

+/* Called by device_probe() */
+int efi_post_probe_device(struct udevice *dev);
+
 /* No need for efi loader support in SPL */
 #if CONFIG_IS_ENABLED(EFI_LOADER)

@@ -420,6 +424,8 @@ efi_status_t EFIAPI efi_convert_pointer(efi_uintn_t 
debug_disposition,
 void efi_carve_out_dt_rsv(void *fdt);
 /* Called by bootefi to make console interface available */
 efi_status_t efi_console_register(void);
+/* Called when a block devices has been probed */
+efi_status_t efi_block_device_register(struct udevice *dev);
 /* Called by bootefi to make all disk storage accessible as EFI objects */
 efi_status_t efi_disk_register(void);
 /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */
diff --git a/lib/efi_driver/Makefile b/lib/efi_driver/Makefile
index 83baa1c9a4..f0d5fa5074 100644
--- a/lib/efi_driver/Makefile
+++ b/lib/efi_driver/Makefile
@@ -5,6 +5,7 @@
 # This file only gets included with CONFIG_EFI_LOADER set, so all
 # object inclusion implicitly depends on it

+obj-y += efi_dm_integration.o
 obj-y += efi_uclass.o
 ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
 obj-y += efi_block_device.o
diff --git a/lib/efi_driver/efi_dm_integration.c 
b/lib/efi_driver/efi_dm_integration.c
new file mode 100644
index 0000000000..9c6c339473
--- /dev/null
+++ b/lib/efi_driver/efi_dm_integration.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021, Heinrich Schuchardt <xypron.g...@gmx.de>
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+
+#include <common.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <log.h>
+
+/**
+ * efi_post_probe_device() - set up handle for probed device
+ *
+ * This function is called by device_probe(). After the UEFI sub-system is
+ * initialized this function adds handles for new devices.
+ *
+ * @dev:       probed device
+ * Return:     0 on success
+ */
+int efi_post_probe_device(struct udevice *dev)
+{
+       if (!dev || !dev->uclass)
+               return -EINVAL;
+
+       switch (dev->uclass->uc_drv->id) {
+       case UCLASS_BLK:
+               if (efi_block_device_register(dev) != EFI_SUCCESS)
+                       log_err("Failed to register %s\n", dev->name);
+       default:
+               break;
+       }
+
+       return 0;
+}
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 988907ecb9..b798cab345 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <blk.h>
 #include <dm.h>
+#include <dm/device-internal.h>
 #include <efi_loader.h>
 #include <fs.h>
 #include <log.h>
@@ -535,6 +536,41 @@ int efi_disk_create_partitions(efi_handle_t parent, struct 
blk_desc *desc,
        return disks;
 }

+/**
+ * efi_block_device_register() - register a block device in the UEFI sub-system
+ *
+ * @dev:       block device
+ * Return:     status code
+ */
+efi_status_t efi_block_device_register(struct udevice *dev)
+{
+       struct blk_desc *desc = dev_get_uclass_plat(dev);
+       const char *if_typename = blk_get_if_type_name(desc->if_type);
+       struct efi_disk_obj *disk;
+       efi_status_t ret;
+
+       /* Add block device for the full device */
+       ret = device_probe(dev);
+       if (ret)
+               return EFI_NOT_FOUND;
+       log_info("Scanning disk %s...\n", dev->name);
+       ret = efi_disk_add_dev(NULL, NULL, if_typename,
+                               desc, desc->devnum, NULL, 0, &disk);
+       if (ret == EFI_NOT_READY) {
+               log_notice("Disk %s not ready\n", dev->name);
+               return ret;
+       } else if (ret != EFI_SUCCESS) {
+               log_err("ERROR: failure to add disk device %s, r = %lu\n",
+                       dev->name, ret & ~EFI_ERROR_MASK);
+               return ret;
+       }
+
+       /* Partitions show up as block devices in EFI */
+       efi_disk_create_partitions(&disk->header, desc, if_typename,
+                                  desc->devnum, dev->name);
+       return ret;
+}
+
 /**
  * efi_disk_register() - register block devices
  *
@@ -552,38 +588,16 @@ int efi_disk_create_partitions(efi_handle_t parent, 
struct blk_desc *desc,
  */
 efi_status_t efi_disk_register(void)
 {
-       struct efi_disk_obj *disk;
-       int disks = 0;
-       efi_status_t ret;
 #ifdef CONFIG_BLK
        struct udevice *dev;
-
+       /* Probe all block devices */
        for (uclass_first_device_check(UCLASS_BLK, &dev); dev;
-            uclass_next_device_check(&dev)) {
-               struct blk_desc *desc = dev_get_uclass_plat(dev);
-               const char *if_typename = blk_get_if_type_name(desc->if_type);
-
-               /* Add block device for the full device */
-               log_info("Scanning disk %s...\n", dev->name);
-               ret = efi_disk_add_dev(NULL, NULL, if_typename,
-                                       desc, desc->devnum, NULL, 0, &disk);
-               if (ret == EFI_NOT_READY) {
-                       log_notice("Disk %s not ready\n", dev->name);
-                       continue;
-               }
-               if (ret) {
-                       log_err("ERROR: failure to add disk device %s, r = 
%lu\n",
-                               dev->name, ret & ~EFI_ERROR_MASK);
-                       return ret;
-               }
-               disks++;
-
-               /* Partitions show up as block devices in EFI */
-               disks += efi_disk_create_partitions(
-                                       &disk->header, desc, if_typename,
-                                       desc->devnum, dev->name);
-       }
+            uclass_next_device_check(&dev))
+               ;
 #else
+       struct efi_disk_obj *disk;
+       int disks = 0;
+       efi_status_t ret;
        int i, if_type;

        /* Search for all available disk devices */
@@ -630,8 +644,8 @@ efi_status_t efi_disk_register(void)
                                                 if_typename, i, devname);
                }
        }
-#endif
        log_info("Found %d disks\n", disks);
+#endif

        return EFI_SUCCESS;
 }
--
2.30.2

Reply via email to