aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2021-06-17 11:57:32 +0200
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2021-06-20 12:55:30 +0200
commit7f51279244811b6eae5d647b21d35b496562e285 (patch)
tree2fa2b4757d7481ad9a12ecaac6a54b5bda8a064c
parente23a145cf000e19b2d9dd456837fedaa1c2d6420 (diff)
downloadu-boot-7f51279244811b6eae5d647b21d35b496562e285.zip
u-boot-7f51279244811b6eae5d647b21d35b496562e285.tar.gz
u-boot-7f51279244811b6eae5d647b21d35b496562e285.tar.bz2
efi_loader: improve block device integration with DM
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. Fixes: f3866909e350 ("distro_bootcmd: call EFI bootmgr even without having /EFI/boot") Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Tested-by: Matwey V. Kornilov <matwey.kornilov@gmail.com>
-rw-r--r--drivers/core/device.c7
-rw-r--r--include/efi_loader.h6
-rw-r--r--lib/efi_driver/Makefile1
-rw-r--r--lib/efi_driver/efi_dm_integration.c36
-rw-r--r--lib/efi_loader/efi_disk.c72
5 files changed, 93 insertions, 29 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index cb960f8..7355a5c 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 0a9c82a..78dd687 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 83baa1c..f0d5fa5 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 0000000..9c6c339
--- /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.glpk@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 988907e..b798cab 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>
@@ -536,6 +537,41 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
}
/**
+ * 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
*
* U-Boot doesn't have a list of all online disk devices. So when running our
@@ -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;
}