On 18.01.18 21:08, Heinrich Schuchardt wrote: > On 01/17/2018 08:16 PM, Heinrich Schuchardt wrote: >> This patch provides >> * a uclass for EFI drivers >> * a EFI driver for block devices >> >> For each EFI driver the uclass >> * creates a handle >> * adds the driver binding protocol >> >> The uclass provides the bind, start, and stop entry points for the driver >> binding protocol. >> >> In bind() and stop() it checks if the controller implements the protocol >> supported by the EFI driver. In the start() function it calls the bind() >> function of the EFI driver. In the stop() function it destroys the child >> controllers. >> >> The EFI block driver binds to controllers implementing the block io >> protocol. >> >> When the bind function of the EFI block driver is called it creates a >> new U-Boot block device. It installs child handles for all partitions and >> installs the simple file protocol on these. >> >> The read and write functions of the EFI block driver delegate calls to the >> controller that it is bound to. >> >> A usage example is as following: >> >> U-Boot loads the iPXE snp.efi executable. iPXE connects an iSCSI drive and >> exposes a handle with the block IO protocol. It calls ConnectController. >> >> Now the EFI block driver installs the partions with the simple file >> protocol. >> >> iPXE uses the simple file protocol to load Grub or the Linux Kernel. >> >> Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de> >> --- >> v2 >> Print to console only in debug mode. >> Provide more comments. >> Add commit message. >> --- >> common/board_r.c | 3 + >> drivers/block/blk-uclass.c | 4 +- >> include/blk.h | 1 + >> include/config_fallbacks.h | 1 + >> include/dm/uclass-id.h | 1 + >> include/efi_driver.h | 30 ++++ >> include/efi_loader.h | 2 + >> lib/Makefile | 1 + >> lib/efi_driver/Makefile | 13 ++ >> lib/efi_driver/efi_block_device.c | 175 ++++++++++++++++++++ >> lib/efi_driver/efi_uclass.c | 330 >> ++++++++++++++++++++++++++++++++++++++ >> 11 files changed, 560 insertions(+), 1 deletion(-) >> create mode 100644 include/efi_driver.h >> create mode 100644 lib/efi_driver/Makefile >> create mode 100644 lib/efi_driver/efi_block_device.c >> create mode 100644 lib/efi_driver/efi_uclass.c >> >> diff --git a/common/board_r.c b/common/board_r.c >> index 2baa47f3a0..4ad37ee31a 100644 >> --- a/common/board_r.c >> +++ b/common/board_r.c >> @@ -715,7 +715,10 @@ static init_fnc_t init_sequence_r[] = { >> set_cpu_clk_info, /* Setup clock information */ >> #endif >> #ifdef CONFIG_EFI_LOADER >> + /* Setup EFI memory before any other EFI related code */ >> efi_memory_init, >> + /* Install EFI drivers */ >> + efi_driver_init, >> #endif >> stdio_init_tables, >> initr_serial, >> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c >> index 010ed32d3a..bfda2211f0 100644 >> --- a/drivers/block/blk-uclass.c >> +++ b/drivers/block/blk-uclass.c >> @@ -24,6 +24,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = { >> [IF_TYPE_HOST] = "host", >> [IF_TYPE_SYSTEMACE] = "ace", >> [IF_TYPE_NVME] = "nvme", >> + [IF_TYPE_EFI] = "efi", >> }; >> >> static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { >> @@ -36,8 +37,9 @@ static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { >> [IF_TYPE_SD] = UCLASS_INVALID, >> [IF_TYPE_SATA] = UCLASS_AHCI, >> [IF_TYPE_HOST] = UCLASS_ROOT, >> - [IF_TYPE_NVME] = UCLASS_NVME, >> [IF_TYPE_SYSTEMACE] = UCLASS_INVALID, >> + [IF_TYPE_NVME] = UCLASS_NVME, >> + [IF_TYPE_EFI] = UCLASS_EFI, >> }; >> >> static enum if_type if_typename_to_iftype(const char *if_typename) >> diff --git a/include/blk.h b/include/blk.h >> index 41b4d7efa8..69b5a98e56 100644 >> --- a/include/blk.h >> +++ b/include/blk.h >> @@ -34,6 +34,7 @@ enum if_type { >> IF_TYPE_HOST, >> IF_TYPE_SYSTEMACE, >> IF_TYPE_NVME, >> + IF_TYPE_EFI, >> >> IF_TYPE_COUNT, /* Number of interface types */ >> }; >> diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h >> index 2c4d43d672..524313d5aa 100644 >> --- a/include/config_fallbacks.h >> +++ b/include/config_fallbacks.h >> @@ -52,6 +52,7 @@ >> defined(CONFIG_MMC) || \ >> defined(CONFIG_NVME) || \ >> defined(CONFIG_SYSTEMACE) || \ >> + (defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD)) || \ >> defined(CONFIG_SANDBOX) >> #define HAVE_BLOCK_DEVICE >> #endif >> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h >> index 3fc20834ae..07fabc3ce6 100644 >> --- a/include/dm/uclass-id.h >> +++ b/include/dm/uclass-id.h >> @@ -34,6 +34,7 @@ enum uclass_id { >> UCLASS_CROS_EC, /* Chrome OS EC */ >> UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ >> UCLASS_DMA, /* Direct Memory Access */ >> + UCLASS_EFI, /* EFI managed devices */ >> UCLASS_ETH, /* Ethernet device */ >> UCLASS_GPIO, /* Bank of general-purpose I/O pins */ >> UCLASS_FIRMWARE, /* Firmware */ >> diff --git a/include/efi_driver.h b/include/efi_driver.h >> new file mode 100644 >> index 0000000000..2bbe26c6e3 >> --- /dev/null >> +++ b/include/efi_driver.h >> @@ -0,0 +1,30 @@ >> +/* >> + * EFI application loader >> + * >> + * Copyright (c) 2017 Heinrich Schuchardt >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#ifndef _EFI_DRIVER_H >> +#define _EFI_DRIVER_H 1 >> + >> +#include <common.h> >> +#include <dm.h> >> +#include <efi_loader.h> >> + >> +struct efi_driver_ops { >> + const efi_guid_t *protocol; >> + const efi_guid_t *child_protocol; >> + int (*bind)(efi_handle_t handle, void *interface); >> +}; >> + >> +/* >> + * This structure adds internal fields to the driver binding protocol. >> + */ >> +struct efi_driver_binding_extended_protocol { >> + struct efi_driver_binding_protocol bp; >> + const struct efi_driver_ops *ops; >> +}; >> + >> +#endif /* _EFI_DRIVER_H */ >> diff --git a/include/efi_loader.h b/include/efi_loader.h >> index 711c901eda..a465175d1f 100644 >> --- a/include/efi_loader.h >> +++ b/include/efi_loader.h >> @@ -273,6 +273,8 @@ efi_status_t efi_get_memory_map(efi_uintn_t >> *memory_map_size, >> /* Adds a range into the EFI memory map */ >> uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, >> bool overlap_only_ram); >> +/* Called by board init to initialize the EFI drivers */ >> +int efi_driver_init(void); >> /* Called by board init to initialize the EFI memory map */ >> int efi_memory_init(void); >> /* Adds new or overrides configuration table entry to the system table */ >> diff --git a/lib/Makefile b/lib/Makefile >> index 8cd779f8ca..0db41c19f3 100644 >> --- a/lib/Makefile >> +++ b/lib/Makefile >> @@ -8,6 +8,7 @@ >> ifndef CONFIG_SPL_BUILD >> >> obj-$(CONFIG_EFI) += efi/ >> +obj-$(CONFIG_EFI_LOADER) += efi_driver/ >> obj-$(CONFIG_EFI_LOADER) += efi_loader/ >> obj-$(CONFIG_EFI_LOADER) += efi_selftest/ >> obj-$(CONFIG_LZMA) += lzma/ >> diff --git a/lib/efi_driver/Makefile b/lib/efi_driver/Makefile >> new file mode 100644 >> index 0000000000..e35529a952 >> --- /dev/null >> +++ b/lib/efi_driver/Makefile >> @@ -0,0 +1,13 @@ >> +# >> +# (C) Copyright 2017 Heinrich Schuchardt >> +# >> +# SPDX-License-Identifier: GPL-2.0+ >> +# >> + >> +# This file only gets included with CONFIG_EFI_LOADER set, so all >> +# object inclusion implicitly depends on it >> + >> +obj-y += efi_uclass.o >> +ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) >> +obj-y += efi_block_device.o >> +endif >> diff --git a/lib/efi_driver/efi_block_device.c >> b/lib/efi_driver/efi_block_device.c >> new file mode 100644 >> index 0000000000..837787d563 >> --- /dev/null >> +++ b/lib/efi_driver/efi_block_device.c >> @@ -0,0 +1,175 @@ >> +/* >> + * EFI block driver >> + * >> + * Copyright (c) 2017 Heinrich Schuchardt >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + * >> + * The EFI uclass creates a handle for this driver and installs the >> + * driver binding protocol on it. >> + * >> + * The EFI block driver binds to controllers implementing the block io >> + * protocol. >> + * >> + * When the bind function of the EFI block driver is called it creates a >> + * new U-Boot block device. It installs child handles for all partitions and >> + * installs the simple file protocol on these. >> + * >> + * The read and write functions of the EFI block driver delegate calls to >> the >> + * controller that it is bound to. >> + * >> + * A usage example is as following: >> + * >> + * U-Boot loads the iPXE snp.efi executable. iPXE connects an iSCSI drive >> and >> + * exposes a handle with the block IO protocol. It calls ConnectController. >> + * >> + * Now the EFI block driver installs the partions with the simple file >> + * protocol. >> + * >> + * iPXE uses the simple file protocol to load Grub or the Linux Kernel. >> + */ >> + >> +#include <efi_driver.h> >> +#include <dm/root.h> >> + >> +static int efi_blk_max_devnum; >> + >> +/* >> + * Read from block device >> + * >> + * @dev device >> + * @blknr first block to be read >> + * @blkcnt number of blocks to read >> + * @buffer output buffer >> + * @return number of blocks transferred >> + */ >> +static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t >> blkcnt, >> + void *buffer) >> +{ >> + struct efi_block_io *io = dev->platdata; >> + efi_status_t ret; >> + >> + EFI_PRINT("%s: read '%s', from block " LBAFU ", " LBAFU " blocks\n", >> + __func__, dev->name, blknr, blkcnt); >> + ret = EFI_CALL(io->read_blocks( >> + io, io->media->media_id, (u64)blknr, >> + (efi_uintn_t)blkcnt * >> + (efi_uintn_t)io->media->block_size, buffer)); >> + EFI_PRINT("%s: r = %u\n", __func__, >> + (unsigned int)(ret & ~EFI_ERROR_MASK)); >> + if (ret != EFI_SUCCESS) >> + return 0; >> + return blkcnt; >> +} >> + >> +/* >> + * Write to block device >> + * >> + * @dev device >> + * @blknr first block to be write >> + * @blkcnt number of blocks to write >> + * @buffer input buffer >> + * @return number of blocks transferred >> + */ >> +static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t >> blkcnt, >> + const void *buffer) >> +{ >> + struct efi_block_io *io = dev->platdata; >> + efi_status_t ret; >> + >> + EFI_PRINT("%s: write '%s', from block " LBAFU ", " LBAFU " blocks\n", >> + __func__, dev->name, blknr, blkcnt); >> + ret = EFI_CALL(io->write_blocks( >> + io, io->media->media_id, (u64)blknr, >> + (efi_uintn_t)blkcnt * >> + (efi_uintn_t)io->media->block_size, >> + (void *)buffer)); >> + EFI_PRINT("%s: r = %u\n", __func__, >> + (unsigned int)(ret & ~EFI_ERROR_MASK)); >> + if (ret != EFI_SUCCESS) >> + return 0; >> + return blkcnt; >> +} >> + >> +static int efi_bl_bind_partions(efi_handle_t handle) >> +{ >> + struct efi_object *obj = efi_search_obj(handle); >> + struct blk_desc *desc; >> + const char *if_typename; >> + >> + if (!obj || !obj->dev) >> + return -ENOENT; >> + desc = dev_get_uclass_platdata(obj->dev); >> + if_typename = blk_get_if_type_name(desc->if_type); >> + >> + return efi_disk_create_partitions(handle, desc, if_typename, >> + desc->devnum, obj->dev->name); >> +} >> + >> +/* >> + * Create a block device for a handle >> + * >> + * @handle handle >> + * @interface block io protocol >> + * @return 0 = success >> + */ >> +static int efi_bl_bind(efi_handle_t handle, void *interface) >> +{ >> + struct udevice *bdev, *parent = dm_root(); >> + int ret, devnum; >> + char name[20]; >> + struct efi_object *obj = efi_search_obj(handle); >> + struct efi_block_io *io = interface; >> + int disks; >> + >> + EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io); >> + >> + if (!obj) >> + return -ENOENT; >> + >> + devnum = efi_blk_max_devnum++; >> + sprintf(name, "efi#%d", devnum); >> + >> + ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI, devnum, >> + io->media->block_size, >> + (lbaint_t)io->media->last_block, &bdev); >> + if (ret) >> + return ret; >> + EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name); >> + bdev->platdata = interface; >> + obj->dev = bdev; >> + >> + ret = blk_prepare_device(bdev); >> + >> + disks = efi_bl_bind_partions(handle); >> + EFI_PRINT("Found %d partions\n", disks); >> + >> + return 0; >> +} >> + >> +/* Block device driver operators */ >> +static const struct blk_ops efi_blk_ops = { >> + .read = efi_bl_read, >> + .write = efi_bl_write, >> +}; >> + >> +/* Identify as block device driver */ >> +U_BOOT_DRIVER(efi_blk) = { >> + .name = "efi_blk", >> + .id = UCLASS_BLK, >> + .ops = &efi_blk_ops, >> +}; >> + >> +/* EFI driver operators */ >> +static const struct efi_driver_ops driver_ops = { >> + .protocol = &efi_block_io_guid, >> + .child_protocol = &efi_block_io_guid, >> + .bind = efi_bl_bind, >> +}; >> + >> +/* Identify as EFI driver */ >> +U_BOOT_DRIVER(efi_block) = { >> + .name = "EFI block driver", >> + .id = UCLASS_EFI, >> + .ops = &driver_ops, >> +}; >> diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c >> new file mode 100644 >> index 0000000000..798431ae74 >> --- /dev/null >> +++ b/lib/efi_driver/efi_uclass.c >> @@ -0,0 +1,330 @@ >> +/* >> + * Uclass for EFI drivers >> + * >> + * Copyright (c) 2017 Heinrich Schuchardt >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + * >> + * For each EFI driver the uclass >> + * - creates a handle >> + * - installs the driver binding protocol >> + * >> + * The uclass provides the bind, start, and stop entry points for the driver >> + * binding protocol. >> + * >> + * In bind() and stop() it checks if the controller implements the protocol >> + * supported by the EFI driver. In the start() function it calls the bind() >> + * function of the EFI driver. In the stop() function it destroys the child >> + * controllers. >> + */ >> + >> +#include <efi_driver.h> >> + >> +/* >> + * Check node type. We do not support partions as controller handles. >> + * >> + * @handle handle to be checked >> + * @return status code >> + */ >> +static efi_status_t check_node_type(efi_handle_t handle) >> +{ >> + efi_status_t r, ret = EFI_SUCCESS; >> + const struct efi_device_path *dp; >> + >> + /* Open the device path protocol */ >> + r = EFI_CALL(systab.boottime->open_protocol( >> + handle, &efi_guid_device_path, (void **)&dp, >> + NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)); >> + if (r == EFI_SUCCESS && dp) { >> + /* Get the last node */ >> + const struct efi_device_path *node = efi_dp_last_node(dp); >> + /* We do not support partitions as controller */ >> + if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE) >> + ret = EFI_UNSUPPORTED; >> + } >> + return ret; >> +} >> + >> +/* >> + * Check if the driver supports the controller. >> + * >> + * @this driver binding protocol >> + * @controller_handle handle of the controller >> + * @remaining_device_path path specifying the child controller >> + * @return status code >> + */ >> +static efi_status_t EFIAPI efi_uc_supported( >> + struct efi_driver_binding_protocol *this, >> + efi_handle_t controller_handle, >> + struct efi_device_path *remaining_device_path) >> +{ >> + efi_status_t r, ret; >> + void *interface; >> + struct efi_driver_binding_extended_protocol *bp = >> + (struct efi_driver_binding_extended_protocol *)this; >> + >> + EFI_ENTRY("%p, %p, %ls", this, controller_handle, >> + efi_dp_str(remaining_device_path)); >> + >> + ret = EFI_CALL(systab.boottime->open_protocol( >> + controller_handle, bp->ops->protocol, >> + &interface, this->driver_binding_handle, >> + controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)); >> + switch (ret) { >> + case EFI_ACCESS_DENIED: >> + case EFI_ALREADY_STARTED: >> + goto out; >> + case EFI_SUCCESS: >> + break; >> + default: >> + ret = EFI_UNSUPPORTED; >> + goto out; >> + } >> + >> + ret = check_node_type(controller_handle); >> + >> + r = EFI_CALL(systab.boottime->close_protocol( >> + controller_handle, bp->ops->protocol, >> + this->driver_binding_handle, >> + controller_handle)); >> + if (r != EFI_SUCCESS) >> + ret = EFI_UNSUPPORTED; >> +out: >> + return EFI_EXIT(ret); >> +} >> + >> +/* >> + * Create child controllers and attach driver. >> + * >> + * @this driver binding protocol >> + * @controller_handle handle of the controller >> + * @remaining_device_path path specifying the child controller >> + * @return status code >> + */ >> +static efi_status_t EFIAPI efi_uc_start( >> + struct efi_driver_binding_protocol *this, >> + efi_handle_t controller_handle, >> + struct efi_device_path *remaining_device_path) >> +{ >> + efi_status_t r, ret; >> + void *interface = NULL; >> + struct efi_driver_binding_extended_protocol *bp = >> + (struct efi_driver_binding_extended_protocol *)this; >> + >> + EFI_ENTRY("%p, %pUl, %ls", this, controller_handle, >> + efi_dp_str(remaining_device_path)); >> + >> + /* Attach driver to controller */ >> + ret = EFI_CALL(systab.boottime->open_protocol( >> + controller_handle, bp->ops->protocol, >> + &interface, this->driver_binding_handle, >> + controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)); >> + switch (ret) { >> + case EFI_ACCESS_DENIED: >> + case EFI_ALREADY_STARTED: >> + goto out; >> + case EFI_SUCCESS: >> + break; >> + default: >> + ret = EFI_UNSUPPORTED; >> + goto out; >> + } >> + ret = check_node_type(controller_handle); >> + if (ret != EFI_SUCCESS) { >> + r = EFI_CALL(systab.boottime->close_protocol( >> + controller_handle, bp->ops->protocol, >> + this->driver_binding_handle, >> + controller_handle)); >> + if (r != EFI_SUCCESS) >> + EFI_PRINT("Failure to close handle\n"); >> + goto out; >> + } >> + >> + /* TODO: driver specific stuff */ >> + bp->ops->bind(controller_handle, interface); >> + >> +out: >> + return EFI_EXIT(ret); >> +} >> + >> +/* >> + * Remove a single child controller from the parent controller. >> + * >> + * @controller_handle parent controller >> + * @child_handle child controller >> + * @return status code >> + */ >> +static efi_status_t disconnect_child(efi_handle_t controller_handle, >> + efi_handle_t child_handle) >> +{ >> + efi_status_t ret; >> + efi_guid_t *guid_controller = NULL; >> + efi_guid_t *guid_child_controller = NULL; >> + >> + ret = EFI_CALL(systab.boottime->close_protocol( >> + controller_handle, guid_controller, >> + child_handle, child_handle)); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("Cannot close protocol\n"); >> + return ret; >> + } >> + ret = EFI_CALL(systab.boottime->uninstall_protocol_interface( >> + child_handle, guid_child_controller, NULL)); >> + if (ret != EFI_SUCCESS) { >> + EFI_PRINT("Cannot uninstall protocol interface\n"); >> + return ret; >> + } >> + return ret; >> +} >> + >> +/* >> + * Remove child controllers and disconnect the controller. >> + * >> + * @this driver binding protocol >> + * @controller_handle handle of the controller >> + * @number_of_children number of child controllers to remove >> + * @child_handle_buffer handles of the child controllers to >> remove >> + * @return status code >> + */ >> +static efi_status_t EFIAPI efi_uc_stop( >> + struct efi_driver_binding_protocol *this, >> + efi_handle_t controller_handle, >> + size_t number_of_children, >> + efi_handle_t *child_handle_buffer) >> +{ >> + efi_status_t ret; >> + efi_uintn_t count; >> + struct efi_open_protocol_info_entry *entry_buffer; >> + efi_guid_t *guid_controller = NULL; >> + >> + EFI_ENTRY("%p, %pUl, %zu, %p", this, controller_handle, >> + number_of_children, child_handle_buffer); >> + >> + /* Destroy provided child controllers */ >> + if (number_of_children) { >> + efi_uintn_t i; >> + >> + for (i = 0; i < number_of_children; ++i) { >> + ret = disconnect_child(controller_handle, >> + child_handle_buffer[i]); >> + if (ret != EFI_SUCCESS) >> + return ret; >> + } >> + return EFI_SUCCESS; >> + } >> + >> + /* Destroy all children */ >> + ret = EFI_CALL(systab.boottime->open_protocol_information( >> + controller_handle, guid_controller, >> + &entry_buffer, &count)); >> + if (ret != EFI_SUCCESS) >> + goto out; >> + while (count) { >> + if (entry_buffer[--count].attributes & >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { >> + ret = disconnect_child( >> + controller_handle, >> + entry_buffer[count].agent_handle); >> + if (ret != EFI_SUCCESS) >> + goto out; >> + } >> + } >> + ret = EFI_CALL(systab.boottime->free_pool(entry_buffer)); >> + if (ret != EFI_SUCCESS) >> + printf("%s(%u) %s: ERROR: Cannot free pool\n", >> + __FILE__, __LINE__, __func__); >> + >> + /* Detach driver from controller */ >> + ret = EFI_CALL(systab.boottime->close_protocol( >> + controller_handle, guid_controller, >> + this->driver_binding_handle, controller_handle)); >> +out: >> + return EFI_EXIT(ret); >> +} >> + >> +static efi_status_t efi_add_driver(struct driver *drv) >> +{ >> + efi_status_t ret; >> + const struct efi_driver_ops *ops = drv->ops; >> + struct efi_driver_binding_extended_protocol *bp; >> + >> + debug("EFI: Adding driver '%s'\n", drv->name); >> + if (!ops->protocol) { >> + printf("EFI: ERROR: protocol GUID missing for driver '%s'\n", >> + drv->name); >> + return EFI_INVALID_PARAMETER; >> + } >> + bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol)); >> + if (!bp) >> + return EFI_OUT_OF_RESOURCES; >> + >> + bp->bp.supported = efi_uc_supported; >> + bp->bp.start = efi_uc_start; >> + bp->bp.stop = efi_uc_stop; >> + bp->bp.version = 0xffffffff; >> + bp->ops = drv->ops; >> + >> + ret = efi_create_handle(&bp->bp.driver_binding_handle); >> + if (ret != EFI_SUCCESS) { >> + free(bp); >> + goto out; >> + } >> + bp->bp.image_handle = bp->bp.driver_binding_handle; >> + ret = efi_add_protocol(bp->bp.driver_binding_handle, >> + &efi_guid_driver_binding_protocol, bp); >> + if (ret != EFI_SUCCESS) { >> + efi_delete_handle(bp->bp.driver_binding_handle); >> + free(bp); >> + goto out; >> + } >> +out: >> + return ret; >> +} >> + >> +/* >> + * Initialize the EFI drivers. >> + * Called by board_init_r(). > > Hello Alex, > > in a chat you asked why this is not called in efi_init_obj_list() after > entering the bootefi command. > > My architectural perspective is that in future we will create the EFI > handles from the device tree in parallel to creating the udevices and > use ConnectController to install the EFI drivers (e.g. for the simple > network protocol in the case of network interfaces). This is only > possible if the EFI uclass exists before udevices are created.
I'm not 100% sure that's the right direction yet, let's just leave it in bootefi for now. Alex _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot