[PATCH 1/1] efi_loader: improve block device integration with DM
Matwey V. Kornilov
matwey.kornilov at gmail.com
Fri Jun 18 09:24:59 CEST 2021
Hi Heinrich,
This patch fixes my issue with am335x: EFI Grub works as expected now.
чт, 17 июн. 2021 г. в 18:15, Heinrich Schuchardt <xypron.glpk at gmx.de>:
>
> 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.glpk at gmx.de>
Tested-by: Matwey V. Kornilov <matwey.kornilov at gmail.com>
> ---
> 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.glpk at 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
>
--
With best regards,
Matwey V. Kornilov
More information about the U-Boot
mailing list